From f6baac3628d89f00cd6bb4f28163a3d089b429df Mon Sep 17 00:00:00 2001 From: Quentin Machu Date: Tue, 2 Feb 2016 13:49:27 -0500 Subject: [PATCH] *: refresh godeps --- Godeps/Godeps.json | 57 +- vendor/github.com/Sirupsen/logrus/.gitignore | 1 - vendor/github.com/Sirupsen/logrus/.travis.yml | 7 - .../github.com/Sirupsen/logrus/CHANGELOG.md | 55 - vendor/github.com/Sirupsen/logrus/LICENSE | 21 - vendor/github.com/Sirupsen/logrus/README.md | 365 - vendor/github.com/Sirupsen/logrus/doc.go | 26 - vendor/github.com/Sirupsen/logrus/entry.go | 264 - .../Sirupsen/logrus/examples/basic/basic.go | 50 - .../Sirupsen/logrus/examples/hook/hook.go | 30 - vendor/github.com/Sirupsen/logrus/exported.go | 193 - .../github.com/Sirupsen/logrus/formatter.go | 48 - .../logrus/formatters/logstash/logstash.go | 61 - vendor/github.com/Sirupsen/logrus/hooks.go | 34 - .../Sirupsen/logrus/hooks/syslog/README.md | 39 - .../Sirupsen/logrus/hooks/syslog/syslog.go | 61 - .../Sirupsen/logrus/json_formatter.go | 41 - vendor/github.com/Sirupsen/logrus/logger.go | 212 - vendor/github.com/Sirupsen/logrus/logrus.go | 98 - .../Sirupsen/logrus/terminal_bsd.go | 9 - .../Sirupsen/logrus/terminal_linux.go | 12 - .../Sirupsen/logrus/terminal_notwindows.go | 21 - .../Sirupsen/logrus/terminal_solaris.go | 15 - .../Sirupsen/logrus/terminal_windows.go | 27 - .../Sirupsen/logrus/text_formatter.go | 161 - vendor/github.com/Sirupsen/logrus/writer.go | 31 - .../go-sql-driver/mysql/.travis.yml | 1 - vendor/github.com/go-sql-driver/mysql/AUTHORS | 4 +- .../go-sql-driver/mysql/CHANGELOG.md | 13 +- .../github.com/go-sql-driver/mysql/README.md | 22 +- .../github.com/go-sql-driver/mysql/buffer.go | 27 +- .../go-sql-driver/mysql/connection.go | 79 +- .../github.com/go-sql-driver/mysql/const.go | 3 +- .../github.com/go-sql-driver/mysql/driver.go | 90 +- vendor/github.com/go-sql-driver/mysql/dsn.go | 314 - .../github.com/go-sql-driver/mysql/errors.go | 24 +- .../github.com/go-sql-driver/mysql/infile.go | 10 +- .../github.com/go-sql-driver/mysql/packets.go | 91 +- vendor/github.com/go-sql-driver/mysql/rows.go | 2 +- .../github.com/go-sql-driver/mysql/utils.go | 259 +- .../github.com/golang/protobuf/proto/lib.go | 1 - .../julienschmidt/httprouter/README.md | 34 +- vendor/github.com/lib/pq/.travis.yml | 2 - vendor/github.com/lib/pq/README.md | 2 - vendor/github.com/lib/pq/conn.go | 77 +- vendor/github.com/lib/pq/doc.go | 2 - .../mattn/go-sqlite3/code/sqlite3-binding.c | 68871 ++++------------ .../mattn/go-sqlite3/code/sqlite3-binding.h | 2594 +- .../mattn/go-sqlite3/code/sqlite3ext.h | 65 +- .../pmezard/go-difflib/difflib/difflib.go | 22 +- .../github.com/prometheus/common/log/log.go | 304 - .../prometheus/common/log/syslog_formatter.go | 119 - .../prometheus/common/model/time.go | 14 +- .../testify/assert/assertion_forward.go | 387 - .../testify/assert/assertion_forward.go.tmpl | 4 - .../stretchr/testify/assert/assertions.go | 73 +- .../testify/assert/forward_assertions.go | 270 +- .../testify/assert/http_assertions.go | 51 + vendor/github.com/tylerb/graceful/graceful.go | 17 +- vendor/golang.org/x/sys/LICENSE | 27 - vendor/golang.org/x/sys/PATENTS | 22 - vendor/golang.org/x/sys/unix/.gitignore | 1 - vendor/golang.org/x/sys/unix/asm.s | 10 - vendor/golang.org/x/sys/unix/asm_darwin_386.s | 29 - .../golang.org/x/sys/unix/asm_darwin_amd64.s | 29 - vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 - .../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 - .../golang.org/x/sys/unix/asm_dragonfly_386.s | 29 - .../x/sys/unix/asm_dragonfly_amd64.s | 29 - .../golang.org/x/sys/unix/asm_freebsd_386.s | 29 - .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 - .../golang.org/x/sys/unix/asm_freebsd_arm.s | 29 - vendor/golang.org/x/sys/unix/asm_linux_386.s | 35 - .../golang.org/x/sys/unix/asm_linux_amd64.s | 29 - vendor/golang.org/x/sys/unix/asm_linux_arm.s | 29 - .../golang.org/x/sys/unix/asm_linux_arm64.s | 24 - .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 28 - vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 - .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 29 - vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 - .../golang.org/x/sys/unix/asm_openbsd_386.s | 29 - .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 29 - .../golang.org/x/sys/unix/asm_solaris_amd64.s | 17 - vendor/golang.org/x/sys/unix/constants.go | 13 - vendor/golang.org/x/sys/unix/env_unix.go | 27 - vendor/golang.org/x/sys/unix/env_unset.go | 14 - vendor/golang.org/x/sys/unix/flock.go | 24 - .../x/sys/unix/flock_linux_32bit.go | 13 - vendor/golang.org/x/sys/unix/gccgo.go | 46 - vendor/golang.org/x/sys/unix/gccgo_c.c | 41 - .../x/sys/unix/gccgo_linux_amd64.go | 20 - vendor/golang.org/x/sys/unix/mkall.sh | 274 - vendor/golang.org/x/sys/unix/mkerrors.sh | 476 - vendor/golang.org/x/sys/unix/mksyscall.pl | 323 - .../x/sys/unix/mksyscall_solaris.pl | 294 - .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 264 - .../golang.org/x/sys/unix/mksysnum_darwin.pl | 39 - .../x/sys/unix/mksysnum_dragonfly.pl | 50 - .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 63 - .../golang.org/x/sys/unix/mksysnum_linux.pl | 58 - .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 58 - .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 50 - vendor/golang.org/x/sys/unix/race.go | 30 - vendor/golang.org/x/sys/unix/race0.go | 25 - .../golang.org/x/sys/unix/sockcmsg_linux.go | 36 - vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 103 - vendor/golang.org/x/sys/unix/str.go | 26 - vendor/golang.org/x/sys/unix/syscall.go | 74 - vendor/golang.org/x/sys/unix/syscall_bsd.go | 628 - .../golang.org/x/sys/unix/syscall_darwin.go | 509 - .../x/sys/unix/syscall_darwin_386.go | 79 - .../x/sys/unix/syscall_darwin_amd64.go | 81 - .../x/sys/unix/syscall_darwin_arm.go | 73 - .../x/sys/unix/syscall_darwin_arm64.go | 79 - .../x/sys/unix/syscall_dragonfly.go | 411 - .../x/sys/unix/syscall_dragonfly_386.go | 63 - .../x/sys/unix/syscall_dragonfly_amd64.go | 63 - .../golang.org/x/sys/unix/syscall_freebsd.go | 682 - .../x/sys/unix/syscall_freebsd_386.go | 63 - .../x/sys/unix/syscall_freebsd_amd64.go | 63 - .../x/sys/unix/syscall_freebsd_arm.go | 63 - vendor/golang.org/x/sys/unix/syscall_linux.go | 1086 - .../x/sys/unix/syscall_linux_386.go | 388 - .../x/sys/unix/syscall_linux_amd64.go | 146 - .../x/sys/unix/syscall_linux_arm.go | 233 - .../x/sys/unix/syscall_linux_arm64.go | 150 - .../x/sys/unix/syscall_linux_ppc64x.go | 96 - .../golang.org/x/sys/unix/syscall_netbsd.go | 492 - .../x/sys/unix/syscall_netbsd_386.go | 44 - .../x/sys/unix/syscall_netbsd_amd64.go | 44 - .../x/sys/unix/syscall_netbsd_arm.go | 44 - .../golang.org/x/sys/unix/syscall_no_getwd.go | 11 - .../golang.org/x/sys/unix/syscall_openbsd.go | 303 - .../x/sys/unix/syscall_openbsd_386.go | 44 - .../x/sys/unix/syscall_openbsd_amd64.go | 44 - .../golang.org/x/sys/unix/syscall_solaris.go | 713 - .../x/sys/unix/syscall_solaris_amd64.go | 37 - vendor/golang.org/x/sys/unix/syscall_unix.go | 297 - vendor/golang.org/x/sys/unix/types_darwin.go | 250 - .../golang.org/x/sys/unix/types_dragonfly.go | 242 - vendor/golang.org/x/sys/unix/types_freebsd.go | 353 - vendor/golang.org/x/sys/unix/types_linux.go | 406 - vendor/golang.org/x/sys/unix/types_netbsd.go | 232 - vendor/golang.org/x/sys/unix/types_openbsd.go | 244 - vendor/golang.org/x/sys/unix/types_solaris.go | 260 - .../x/sys/unix/zerrors_darwin_386.go | 1576 - .../x/sys/unix/zerrors_darwin_amd64.go | 1576 - .../x/sys/unix/zerrors_darwin_arm.go | 1293 - .../x/sys/unix/zerrors_darwin_arm64.go | 1576 - .../x/sys/unix/zerrors_dragonfly_386.go | 1530 - .../x/sys/unix/zerrors_dragonfly_amd64.go | 1530 - .../x/sys/unix/zerrors_freebsd_386.go | 1743 - .../x/sys/unix/zerrors_freebsd_amd64.go | 1748 - .../x/sys/unix/zerrors_freebsd_arm.go | 1729 - .../x/sys/unix/zerrors_linux_386.go | 1817 - .../x/sys/unix/zerrors_linux_amd64.go | 1818 - .../x/sys/unix/zerrors_linux_arm.go | 1742 - .../x/sys/unix/zerrors_linux_arm64.go | 1896 - .../x/sys/unix/zerrors_linux_ppc64.go | 1969 - .../x/sys/unix/zerrors_linux_ppc64le.go | 1968 - .../x/sys/unix/zerrors_netbsd_386.go | 1712 - .../x/sys/unix/zerrors_netbsd_amd64.go | 1702 - .../x/sys/unix/zerrors_netbsd_arm.go | 1688 - .../x/sys/unix/zerrors_openbsd_386.go | 1584 - .../x/sys/unix/zerrors_openbsd_amd64.go | 1583 - .../x/sys/unix/zerrors_solaris_amd64.go | 1436 - .../x/sys/unix/zsyscall_darwin_386.go | 1426 - .../x/sys/unix/zsyscall_darwin_amd64.go | 1442 - .../x/sys/unix/zsyscall_darwin_arm.go | 1426 - .../x/sys/unix/zsyscall_darwin_arm64.go | 1426 - .../x/sys/unix/zsyscall_dragonfly_386.go | 1412 - .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1412 - .../x/sys/unix/zsyscall_freebsd_386.go | 1664 - .../x/sys/unix/zsyscall_freebsd_amd64.go | 1664 - .../x/sys/unix/zsyscall_freebsd_arm.go | 1664 - .../x/sys/unix/zsyscall_linux_386.go | 1628 - .../x/sys/unix/zsyscall_linux_amd64.go | 1822 - .../x/sys/unix/zsyscall_linux_arm.go | 1756 - .../x/sys/unix/zsyscall_linux_arm64.go | 1750 - .../x/sys/unix/zsyscall_linux_ppc64.go | 1792 - .../x/sys/unix/zsyscall_linux_ppc64le.go | 1792 - .../x/sys/unix/zsyscall_netbsd_386.go | 1326 - .../x/sys/unix/zsyscall_netbsd_amd64.go | 1326 - .../x/sys/unix/zsyscall_netbsd_arm.go | 1326 - .../x/sys/unix/zsyscall_openbsd_386.go | 1386 - .../x/sys/unix/zsyscall_openbsd_amd64.go | 1386 - .../x/sys/unix/zsyscall_solaris_amd64.go | 1559 - .../golang.org/x/sys/unix/zsysctl_openbsd.go | 270 - .../x/sys/unix/zsysnum_darwin_386.go | 398 - .../x/sys/unix/zsysnum_darwin_amd64.go | 398 - .../x/sys/unix/zsysnum_darwin_arm.go | 358 - .../x/sys/unix/zsysnum_darwin_arm64.go | 398 - .../x/sys/unix/zsysnum_dragonfly_386.go | 304 - .../x/sys/unix/zsysnum_dragonfly_amd64.go | 304 - .../x/sys/unix/zsysnum_freebsd_386.go | 351 - .../x/sys/unix/zsysnum_freebsd_amd64.go | 351 - .../x/sys/unix/zsysnum_freebsd_arm.go | 351 - .../x/sys/unix/zsysnum_linux_386.go | 355 - .../x/sys/unix/zsysnum_linux_amd64.go | 321 - .../x/sys/unix/zsysnum_linux_arm.go | 356 - .../x/sys/unix/zsysnum_linux_arm64.go | 272 - .../x/sys/unix/zsysnum_linux_ppc64.go | 360 - .../x/sys/unix/zsysnum_linux_ppc64le.go | 353 - .../x/sys/unix/zsysnum_netbsd_386.go | 273 - .../x/sys/unix/zsysnum_netbsd_amd64.go | 273 - .../x/sys/unix/zsysnum_netbsd_arm.go | 273 - .../x/sys/unix/zsysnum_openbsd_386.go | 207 - .../x/sys/unix/zsysnum_openbsd_amd64.go | 207 - .../x/sys/unix/zsysnum_solaris_amd64.go | 13 - .../x/sys/unix/ztypes_darwin_386.go | 447 - .../x/sys/unix/ztypes_darwin_amd64.go | 462 - .../x/sys/unix/ztypes_darwin_arm.go | 449 - .../x/sys/unix/ztypes_darwin_arm64.go | 457 - .../x/sys/unix/ztypes_dragonfly_386.go | 437 - .../x/sys/unix/ztypes_dragonfly_amd64.go | 443 - .../x/sys/unix/ztypes_freebsd_386.go | 502 - .../x/sys/unix/ztypes_freebsd_amd64.go | 505 - .../x/sys/unix/ztypes_freebsd_arm.go | 497 - .../golang.org/x/sys/unix/ztypes_linux_386.go | 590 - .../x/sys/unix/ztypes_linux_amd64.go | 608 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 579 - .../x/sys/unix/ztypes_linux_arm64.go | 595 - .../x/sys/unix/ztypes_linux_ppc64.go | 605 - .../x/sys/unix/ztypes_linux_ppc64le.go | 605 - .../x/sys/unix/ztypes_netbsd_386.go | 396 - .../x/sys/unix/ztypes_netbsd_amd64.go | 403 - .../x/sys/unix/ztypes_netbsd_arm.go | 401 - .../x/sys/unix/ztypes_openbsd_386.go | 441 - .../x/sys/unix/ztypes_openbsd_amd64.go | 448 - .../x/sys/unix/ztypes_solaris_amd64.go | 422 - 230 files changed, 16849 insertions(+), 155664 deletions(-) delete mode 100644 vendor/github.com/Sirupsen/logrus/.gitignore delete mode 100644 vendor/github.com/Sirupsen/logrus/.travis.yml delete mode 100644 vendor/github.com/Sirupsen/logrus/CHANGELOG.md delete mode 100644 vendor/github.com/Sirupsen/logrus/LICENSE delete mode 100644 vendor/github.com/Sirupsen/logrus/README.md delete mode 100644 vendor/github.com/Sirupsen/logrus/doc.go delete mode 100644 vendor/github.com/Sirupsen/logrus/entry.go delete mode 100644 vendor/github.com/Sirupsen/logrus/examples/basic/basic.go delete mode 100644 vendor/github.com/Sirupsen/logrus/examples/hook/hook.go delete mode 100644 vendor/github.com/Sirupsen/logrus/exported.go delete mode 100644 vendor/github.com/Sirupsen/logrus/formatter.go delete mode 100644 vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go delete mode 100644 vendor/github.com/Sirupsen/logrus/hooks.go delete mode 100644 vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md delete mode 100644 vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go delete mode 100644 vendor/github.com/Sirupsen/logrus/json_formatter.go delete mode 100644 vendor/github.com/Sirupsen/logrus/logger.go delete mode 100644 vendor/github.com/Sirupsen/logrus/logrus.go delete mode 100644 vendor/github.com/Sirupsen/logrus/terminal_bsd.go delete mode 100644 vendor/github.com/Sirupsen/logrus/terminal_linux.go delete mode 100644 vendor/github.com/Sirupsen/logrus/terminal_notwindows.go delete mode 100644 vendor/github.com/Sirupsen/logrus/terminal_solaris.go delete mode 100644 vendor/github.com/Sirupsen/logrus/terminal_windows.go delete mode 100644 vendor/github.com/Sirupsen/logrus/text_formatter.go delete mode 100644 vendor/github.com/Sirupsen/logrus/writer.go delete mode 100644 vendor/github.com/go-sql-driver/mysql/dsn.go delete mode 100644 vendor/github.com/prometheus/common/log/log.go delete mode 100644 vendor/github.com/prometheus/common/log/syslog_formatter.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl delete mode 100644 vendor/golang.org/x/sys/LICENSE delete mode 100644 vendor/golang.org/x/sys/PATENTS delete mode 100644 vendor/golang.org/x/sys/unix/.gitignore delete mode 100644 vendor/golang.org/x/sys/unix/asm.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_linux_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_linux_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/asm_solaris_amd64.s delete mode 100644 vendor/golang.org/x/sys/unix/constants.go delete mode 100644 vendor/golang.org/x/sys/unix/env_unix.go delete mode 100644 vendor/golang.org/x/sys/unix/env_unset.go delete mode 100644 vendor/golang.org/x/sys/unix/flock.go delete mode 100644 vendor/golang.org/x/sys/unix/flock_linux_32bit.go delete mode 100644 vendor/golang.org/x/sys/unix/gccgo.go delete mode 100644 vendor/golang.org/x/sys/unix/gccgo_c.c delete mode 100644 vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/mkall.sh delete mode 100644 vendor/golang.org/x/sys/unix/mkerrors.sh delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_linux.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl delete mode 100644 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl delete mode 100644 vendor/golang.org/x/sys/unix/race.go delete mode 100644 vendor/golang.org/x/sys/unix/race0.go delete mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_linux.go delete mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix.go delete mode 100644 vendor/golang.org/x/sys/unix/str.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_no_getwd.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/syscall_unix.go delete mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go delete mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go delete mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_linux.go delete mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/zsysnum_solaris_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go delete mode 100644 vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4e253591..035f6282 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -9,27 +9,22 @@ "ImportPath": "bitbucket.org/liamstask/goose/lib/goose", "Rev": "8488cc47d90c8a502b1c41a462a6d9cc8ee0a895" }, - { - "ImportPath": "github.com/Sirupsen/logrus", - "Comment": "v0.8.7-55-gf7f79f7", - "Rev": "f7f79f729e0fbe2fcc061db48a9ba0263f588252" - }, { "ImportPath": "github.com/beorn7/perks/quantile", "Rev": "b965b613227fddccbfffe13eae360ed3fa822f8d" }, { "ImportPath": "github.com/coreos/go-systemd/journal", - "Comment": "v4-40-g2ed5b50", - "Rev": "2ed5b5012ccde5f057c197890a2c801295941149" + "Comment": "v4-34-g4f14f6d", + "Rev": "4f14f6deef2da87e4aa59e6c1c1f3e02ba44c5e1" }, { "ImportPath": "github.com/coreos/pkg/capnslog", - "Rev": "fa92df939cff437b00010275644a10882beaeca8" + "Rev": "2c77715c4df99b5420ffcae14ead08f52104065d" }, { "ImportPath": "github.com/coreos/pkg/timeutil", - "Rev": "fa92df939cff437b00010275644a10882beaeca8" + "Rev": "2c77715c4df99b5420ffcae14ead08f52104065d" }, { "ImportPath": "github.com/davecgh/go-spew/spew", @@ -37,12 +32,12 @@ }, { "ImportPath": "github.com/go-sql-driver/mysql", - "Comment": "v1.2-156-g7c7f556", - "Rev": "7c7f556282622f94213bc028b4d0a7b6151ba239" + "Comment": "v1.2-125-gd512f20", + "Rev": "d512f204a577a4ab037a1816604c48c9c13210be" }, { "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "6aaa8d47701fa6cf07e914ec01fde3d4a1fe79c3" + "Rev": "5fc2294e655b78ed8a02082d37808d46c17d7e64" }, { "ImportPath": "github.com/guregu/null/zero", @@ -55,8 +50,8 @@ }, { "ImportPath": "github.com/julienschmidt/httprouter", - "Comment": "v1.1-16-gabb0dc9", - "Rev": "abb0dc9f755ff0a9d818db28d9d8b9810066e2b5" + "Comment": "v1.1-14-g21439ef", + "Rev": "21439ef4d70ba4f3e2a5ed9249e7b03af4019b40" }, { "ImportPath": "github.com/kylelemons/go-gypsy/yaml", @@ -65,13 +60,13 @@ }, { "ImportPath": "github.com/lib/pq", - "Comment": "go1.0-cutoff-74-g8ad2b29", - "Rev": "8ad2b298cadd691a77015666a5372eae5dbfac8f" + "Comment": "go1.0-cutoff-63-g11fc39a", + "Rev": "11fc39a580a008f1f39bb3d11d984fb34ed778d9" }, { "ImportPath": "github.com/mattn/go-sqlite3", - "Comment": "v1.1.0-32-gf33c976", - "Rev": "f33c9767fbdd0d10fab2b7bf056e80bdf30c8ed1" + "Comment": "v1.1.0-30-g5510da3", + "Rev": "5510da399572b4962c020184bb291120c0a412e2" }, { "ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil", @@ -83,7 +78,7 @@ }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", - "Rev": "792786c7400a136282c1664665ae0a8db921c6c2" + "Rev": "e8554b8641db39598be7f6342874b958f12ae1d4" }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", @@ -97,19 +92,15 @@ }, { "ImportPath": "github.com/prometheus/common/expfmt", - "Rev": "14ca1097bbe21584194c15e391a9dab95ad42a59" + "Rev": "dba5e39d4516169e840def50e507ef5f21b985f9" }, { "ImportPath": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", - "Rev": "14ca1097bbe21584194c15e391a9dab95ad42a59" - }, - { - "ImportPath": "github.com/prometheus/common/log", - "Rev": "14ca1097bbe21584194c15e391a9dab95ad42a59" + "Rev": "dba5e39d4516169e840def50e507ef5f21b985f9" }, { "ImportPath": "github.com/prometheus/common/model", - "Rev": "14ca1097bbe21584194c15e391a9dab95ad42a59" + "Rev": "dba5e39d4516169e840def50e507ef5f21b985f9" }, { "ImportPath": "github.com/prometheus/procfs", @@ -117,13 +108,13 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Comment": "v1.1.3", - "Rev": "f390dcf405f7b83c997eac1b06768bb9f44dec18" + "Comment": "v1.0-91-g5b9da39", + "Rev": "5b9da39b66e8e994455c2525c4421c8cc00a7f93" }, { "ImportPath": "github.com/tylerb/graceful", - "Comment": "v1.2.4", - "Rev": "119c58e176bce26fd40698146d9a106c8f1723a5" + "Comment": "v1.2.3", + "Rev": "48afeb21e2fcbcff0f30bd5ad6b97747b0fae38e" }, { "ImportPath": "github.com/ziutek/mymysql/godrv", @@ -142,11 +133,7 @@ }, { "ImportPath": "golang.org/x/net/netutil", - "Rev": "04b9de9b512f58addf28c9853d50ebef61c3953e" - }, - { - "ImportPath": "golang.org/x/sys/unix", - "Rev": "eb2c74142fd19a79b3f237334c7384d5167b1b46" + "Rev": "1d7a0b2100da090d8b02afcfb42f97e2c77e71a4" }, { "ImportPath": "gopkg.in/yaml.v2", diff --git a/vendor/github.com/Sirupsen/logrus/.gitignore b/vendor/github.com/Sirupsen/logrus/.gitignore deleted file mode 100644 index 66be63a0..00000000 --- a/vendor/github.com/Sirupsen/logrus/.gitignore +++ /dev/null @@ -1 +0,0 @@ -logrus diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml deleted file mode 100644 index ec641142..00000000 --- a/vendor/github.com/Sirupsen/logrus/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go -go: - - 1.3 - - 1.4 - - tip -install: - - go get -t ./... diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md deleted file mode 100644 index ecc84327..00000000 --- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md +++ /dev/null @@ -1,55 +0,0 @@ -# 0.9.0 (Unreleased) - -* logrus/text_formatter: don't emit empty msg -* logrus/hooks/airbrake: move out of main repository -* logrus/hooks/sentry: move out of main repository -* logrus/hooks/papertrail: move out of main repository -* logrus/hooks/bugsnag: move out of main repository - -# 0.8.7 - -* logrus/core: fix possible race (#216) -* logrus/doc: small typo fixes and doc improvements - - -# 0.8.6 - -* hooks/raven: allow passing an initialized client - -# 0.8.5 - -* logrus/core: revert #208 - -# 0.8.4 - -* formatter/text: fix data race (#218) - -# 0.8.3 - -* logrus/core: fix entry log level (#208) -* logrus/core: improve performance of text formatter by 40% -* logrus/core: expose `LevelHooks` type -* logrus/core: add support for DragonflyBSD and NetBSD -* formatter/text: print structs more verbosely - -# 0.8.2 - -* logrus: fix more Fatal family functions - -# 0.8.1 - -* logrus: fix not exiting on `Fatalf` and `Fatalln` - -# 0.8.0 - -* logrus: defaults to stderr instead of stdout -* hooks/sentry: add special field for `*http.Request` -* formatter/text: ignore Windows for colors - -# 0.7.3 - -* formatter/\*: allow configuration of timestamp layout - -# 0.7.2 - -* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/Sirupsen/logrus/LICENSE deleted file mode 100644 index f090cb42..00000000 --- a/vendor/github.com/Sirupsen/logrus/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Simon Eskildsen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md deleted file mode 100644 index 55d3a8d5..00000000 --- a/vendor/github.com/Sirupsen/logrus/README.md +++ /dev/null @@ -1,365 +0,0 @@ -# Logrus :walrus: [![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus) [![godoc reference](https://godoc.org/github.com/Sirupsen/logrus?status.png)][godoc] - -Logrus is a structured logger for Go (golang), completely API compatible with -the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not -yet stable (pre 1.0). Logrus itself is completely stable and has been used in -many large deployments. The core API is unlikely to change much but please -version control your Logrus to make sure you aren't fetching latest `master` on -every build.** - -Nicely color-coded in development (when a TTY is attached, otherwise just -plain text): - -![Colored](http://i.imgur.com/PY7qMwd.png) - -With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash -or Splunk: - -```json -{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the -ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} - -{"level":"warning","msg":"The group's number increased tremendously!", -"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} - -{"animal":"walrus","level":"info","msg":"A giant walrus appears!", -"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} - -{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", -"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} - -{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, -"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} -``` - -With the default `log.Formatter = new(&log.TextFormatter{})` when a TTY is not -attached, the output is compatible with the -[logfmt](http://godoc.org/github.com/kr/logfmt) format: - -```text -time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 -time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 -time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true -time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 -time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 -time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true -exit status 1 -``` - -#### Example - -The simplest way to use Logrus is simply the package-level exported logger: - -```go -package main - -import ( - log "github.com/Sirupsen/logrus" -) - -func main() { - log.WithFields(log.Fields{ - "animal": "walrus", - }).Info("A walrus appears") -} -``` - -Note that it's completely api-compatible with the stdlib logger, so you can -replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"` -and you'll now have the flexibility of Logrus. You can customize it all you -want: - -```go -package main - -import ( - "os" - log "github.com/Sirupsen/logrus" -) - -func init() { - // Log as JSON instead of the default ASCII formatter. - log.SetFormatter(&log.JSONFormatter{}) - - // Output to stderr instead of stdout, could also be a file. - log.SetOutput(os.Stderr) - - // Only log the warning severity or above. - log.SetLevel(log.WarnLevel) -} - -func main() { - log.WithFields(log.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") - - log.WithFields(log.Fields{ - "omg": true, - "number": 122, - }).Warn("The group's number increased tremendously!") - - log.WithFields(log.Fields{ - "omg": true, - "number": 100, - }).Fatal("The ice breaks!") - - // A common pattern is to re-use fields between logging statements by re-using - // the logrus.Entry returned from WithFields() - contextLogger := log.WithFields(log.Fields{ - "common": "this is a common field", - "other": "I also should be logged always", - }) - - contextLogger.Info("I'll be logged with common and other field") - contextLogger.Info("Me too") -} -``` - -For more advanced usage such as logging to multiple locations from the same -application, you can also create an instance of the `logrus` Logger: - -```go -package main - -import ( - "github.com/Sirupsen/logrus" -) - -// Create a new instance of the logger. You can have any number of instances. -var log = logrus.New() - -func main() { - // The API for setting attributes is a little different than the package level - // exported logger. See Godoc. - log.Out = os.Stderr - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") -} -``` - -#### Fields - -Logrus encourages careful, structured logging though logging fields instead of -long, unparseable error messages. For example, instead of: `log.Fatalf("Failed -to send event %s to topic %s with key %d")`, you should log the much more -discoverable: - -```go -log.WithFields(log.Fields{ - "event": event, - "topic": topic, - "key": key, -}).Fatal("Failed to send event") -``` - -We've found this API forces you to think about logging in a way that produces -much more useful logging messages. We've been in countless situations where just -a single added field to a log statement that was already there would've saved us -hours. The `WithFields` call is optional. - -In general, with Logrus using any of the `printf`-family functions should be -seen as a hint you should add a field, however, you can still use the -`printf`-family functions with Logrus. - -#### Hooks - -You can add hooks for logging levels. For example to send errors to an exception -tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to -multiple places simultaneously, e.g. syslog. - -Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in -`init`: - -```go -import ( - log "github.com/Sirupsen/logrus" - "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" - logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" - "log/syslog" -) - -func init() { - - // Use the Airbrake hook to report errors that have Error severity or above to - // an exception tracker. You can create custom hooks, see the Hooks section. - log.AddHook(airbrake.NewHook(123, "xyz", "production")) - - hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") - if err != nil { - log.Error("Unable to connect to local syslog daemon") - } else { - log.AddHook(hook) - } -} -``` -Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). - -| Hook | Description | -| ----- | ----------- | -| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | -| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. | -| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | -| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | -| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | -| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | -| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | -| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | -| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | -| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | -| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | -| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | -| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | -| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | -| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | -| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | -| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | -| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | -| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | -| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | -| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | - -#### Level logging - -Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. - -```go -log.Debug("Useful debugging information.") -log.Info("Something noteworthy happened!") -log.Warn("You should probably take a look at this.") -log.Error("Something failed but I'm not quitting.") -// Calls os.Exit(1) after logging -log.Fatal("Bye.") -// Calls panic() after logging -log.Panic("I'm bailing.") -``` - -You can set the logging level on a `Logger`, then it will only log entries with -that severity or anything above it: - -```go -// Will log anything that is info or above (warn, error, fatal, panic). Default. -log.SetLevel(log.InfoLevel) -``` - -It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose -environment if your application has that. - -#### Entries - -Besides the fields added with `WithField` or `WithFields` some fields are -automatically added to all logging events: - -1. `time`. The timestamp when the entry was created. -2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after - the `AddFields` call. E.g. `Failed to send event.` -3. `level`. The logging level. E.g. `info`. - -#### Environments - -Logrus has no notion of environment. - -If you wish for hooks and formatters to only be used in specific environments, -you should handle that yourself. For example, if your application has a global -variable `Environment`, which is a string representation of the environment you -could do: - -```go -import ( - log "github.com/Sirupsen/logrus" -) - -init() { - // do something here to set environment depending on an environment variable - // or command-line flag - if Environment == "production" { - log.SetFormatter(&log.JSONFormatter{}) - } else { - // The TextFormatter is default, you don't actually have to do this. - log.SetFormatter(&log.TextFormatter{}) - } -} -``` - -This configuration is how `logrus` was intended to be used, but JSON in -production is mostly only useful if you do log aggregation with tools like -Splunk or Logstash. - -#### Formatters - -The built-in logging formatters are: - -* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise - without colors. - * *Note:* to force colored output when there is no TTY, set the `ForceColors` - field to `true`. To force no colored output even if there is a TTY set the - `DisableColors` field to `true` -* `logrus.JSONFormatter`. Logs fields as JSON. -* `logrus/formatters/logstash.LogstashFormatter`. Logs fields as [Logstash](http://logstash.net) Events. - - ```go - logrus.SetFormatter(&logstash.LogstashFormatter{Type: "application_name"}) - ``` - -Third party logging formatters: - -* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. -* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. - -You can define your formatter by implementing the `Formatter` interface, -requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a -`Fields` type (`map[string]interface{}`) with all your fields as well as the -default ones (see Entries section above): - -```go -type MyJSONFormatter struct { -} - -log.SetFormatter(new(MyJSONFormatter)) - -func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { - // Note this doesn't include Time, Level and Message which are available on - // the Entry. Consult `godoc` on information about those fields or read the - // source of the official loggers. - serialized, err := json.Marshal(entry.Data) - if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) - } - return append(serialized, '\n'), nil -} -``` - -#### Logger as an `io.Writer` - -Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. - -```go -w := logger.Writer() -defer w.Close() - -srv := http.Server{ - // create a stdlib log.Logger that writes to - // logrus.Logger. - ErrorLog: log.New(w, "", 0), -} -``` - -Each line written to that writer will be printed the usual way, using formatters -and hooks. The level for those entries is `info`. - -#### Rotation - -Log rotation is not provided with Logrus. Log rotation should be done by an -external program (like `logrotate(8)`) that can compress and delete old log -entries. It should not be a feature of the application-level logger. - -#### Tools - -| Tool | Description | -| ---- | ----------- | -|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| - -[godoc]: https://godoc.org/github.com/Sirupsen/logrus diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/Sirupsen/logrus/doc.go deleted file mode 100644 index dddd5f87..00000000 --- a/vendor/github.com/Sirupsen/logrus/doc.go +++ /dev/null @@ -1,26 +0,0 @@ -/* -Package logrus is a structured logger for Go, completely API compatible with the standard library logger. - - -The simplest way to use Logrus is simply the package-level exported logger: - - package main - - import ( - log "github.com/Sirupsen/logrus" - ) - - func main() { - log.WithFields(log.Fields{ - "animal": "walrus", - "number": 1, - "size": 10, - }).Info("A walrus appears") - } - -Output: - time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 - -For a full guide visit https://github.com/Sirupsen/logrus -*/ -package logrus diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go deleted file mode 100644 index 9ae900bc..00000000 --- a/vendor/github.com/Sirupsen/logrus/entry.go +++ /dev/null @@ -1,264 +0,0 @@ -package logrus - -import ( - "bytes" - "fmt" - "io" - "os" - "time" -) - -// Defines the key when adding errors using WithError. -var ErrorKey = "error" - -// An entry is the final or intermediate Logrus logging entry. It contains all -// the fields passed with WithField{,s}. It's finally logged when Debug, Info, -// Warn, Error, Fatal or Panic is called on it. These objects can be reused and -// passed around as much as you wish to avoid field duplication. -type Entry struct { - Logger *Logger - - // Contains all the fields set by the user. - Data Fields - - // Time at which the log entry was created - Time time.Time - - // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic - Level Level - - // Message passed to Debug, Info, Warn, Error, Fatal or Panic - Message string -} - -func NewEntry(logger *Logger) *Entry { - return &Entry{ - Logger: logger, - // Default is three fields, give a little extra room - Data: make(Fields, 5), - } -} - -// Returns a reader for the entry, which is a proxy to the formatter. -func (entry *Entry) Reader() (*bytes.Buffer, error) { - serialized, err := entry.Logger.Formatter.Format(entry) - return bytes.NewBuffer(serialized), err -} - -// Returns the string representation from the reader and ultimately the -// formatter. -func (entry *Entry) String() (string, error) { - reader, err := entry.Reader() - if err != nil { - return "", err - } - - return reader.String(), err -} - -// Add an error as single field (using the key defined in ErrorKey) to the Entry. -func (entry *Entry) WithError(err error) *Entry { - return entry.WithField(ErrorKey, err) -} - -// Add a single field to the Entry. -func (entry *Entry) WithField(key string, value interface{}) *Entry { - return entry.WithFields(Fields{key: value}) -} - -// Add a map of fields to the Entry. -func (entry *Entry) WithFields(fields Fields) *Entry { - data := Fields{} - for k, v := range entry.Data { - data[k] = v - } - for k, v := range fields { - data[k] = v - } - return &Entry{Logger: entry.Logger, Data: data} -} - -// This function is not declared with a pointer value because otherwise -// race conditions will occur when using multiple goroutines -func (entry Entry) log(level Level, msg string) { - entry.Time = time.Now() - entry.Level = level - entry.Message = msg - - if err := entry.Logger.Hooks.Fire(level, &entry); err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) - entry.Logger.mu.Unlock() - } - - reader, err := entry.Reader() - if err != nil { - entry.Logger.mu.Lock() - fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) - entry.Logger.mu.Unlock() - } - - entry.Logger.mu.Lock() - defer entry.Logger.mu.Unlock() - - _, err = io.Copy(entry.Logger.Out, reader) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) - } - - // To avoid Entry#log() returning a value that only would make sense for - // panic() to use in Entry#Panic(), we avoid the allocation by checking - // directly here. - if level <= PanicLevel { - panic(&entry) - } -} - -func (entry *Entry) Debug(args ...interface{}) { - if entry.Logger.Level >= DebugLevel { - entry.log(DebugLevel, fmt.Sprint(args...)) - } -} - -func (entry *Entry) Print(args ...interface{}) { - entry.Info(args...) -} - -func (entry *Entry) Info(args ...interface{}) { - if entry.Logger.Level >= InfoLevel { - entry.log(InfoLevel, fmt.Sprint(args...)) - } -} - -func (entry *Entry) Warn(args ...interface{}) { - if entry.Logger.Level >= WarnLevel { - entry.log(WarnLevel, fmt.Sprint(args...)) - } -} - -func (entry *Entry) Warning(args ...interface{}) { - entry.Warn(args...) -} - -func (entry *Entry) Error(args ...interface{}) { - if entry.Logger.Level >= ErrorLevel { - entry.log(ErrorLevel, fmt.Sprint(args...)) - } -} - -func (entry *Entry) Fatal(args ...interface{}) { - if entry.Logger.Level >= FatalLevel { - entry.log(FatalLevel, fmt.Sprint(args...)) - } - os.Exit(1) -} - -func (entry *Entry) Panic(args ...interface{}) { - if entry.Logger.Level >= PanicLevel { - entry.log(PanicLevel, fmt.Sprint(args...)) - } - panic(fmt.Sprint(args...)) -} - -// Entry Printf family functions - -func (entry *Entry) Debugf(format string, args ...interface{}) { - if entry.Logger.Level >= DebugLevel { - entry.Debug(fmt.Sprintf(format, args...)) - } -} - -func (entry *Entry) Infof(format string, args ...interface{}) { - if entry.Logger.Level >= InfoLevel { - entry.Info(fmt.Sprintf(format, args...)) - } -} - -func (entry *Entry) Printf(format string, args ...interface{}) { - entry.Infof(format, args...) -} - -func (entry *Entry) Warnf(format string, args ...interface{}) { - if entry.Logger.Level >= WarnLevel { - entry.Warn(fmt.Sprintf(format, args...)) - } -} - -func (entry *Entry) Warningf(format string, args ...interface{}) { - entry.Warnf(format, args...) -} - -func (entry *Entry) Errorf(format string, args ...interface{}) { - if entry.Logger.Level >= ErrorLevel { - entry.Error(fmt.Sprintf(format, args...)) - } -} - -func (entry *Entry) Fatalf(format string, args ...interface{}) { - if entry.Logger.Level >= FatalLevel { - entry.Fatal(fmt.Sprintf(format, args...)) - } - os.Exit(1) -} - -func (entry *Entry) Panicf(format string, args ...interface{}) { - if entry.Logger.Level >= PanicLevel { - entry.Panic(fmt.Sprintf(format, args...)) - } -} - -// Entry Println family functions - -func (entry *Entry) Debugln(args ...interface{}) { - if entry.Logger.Level >= DebugLevel { - entry.Debug(entry.sprintlnn(args...)) - } -} - -func (entry *Entry) Infoln(args ...interface{}) { - if entry.Logger.Level >= InfoLevel { - entry.Info(entry.sprintlnn(args...)) - } -} - -func (entry *Entry) Println(args ...interface{}) { - entry.Infoln(args...) -} - -func (entry *Entry) Warnln(args ...interface{}) { - if entry.Logger.Level >= WarnLevel { - entry.Warn(entry.sprintlnn(args...)) - } -} - -func (entry *Entry) Warningln(args ...interface{}) { - entry.Warnln(args...) -} - -func (entry *Entry) Errorln(args ...interface{}) { - if entry.Logger.Level >= ErrorLevel { - entry.Error(entry.sprintlnn(args...)) - } -} - -func (entry *Entry) Fatalln(args ...interface{}) { - if entry.Logger.Level >= FatalLevel { - entry.Fatal(entry.sprintlnn(args...)) - } - os.Exit(1) -} - -func (entry *Entry) Panicln(args ...interface{}) { - if entry.Logger.Level >= PanicLevel { - entry.Panic(entry.sprintlnn(args...)) - } -} - -// Sprintlnn => Sprint no newline. This is to get the behavior of how -// fmt.Sprintln where spaces are always added between operands, regardless of -// their type. Instead of vendoring the Sprintln implementation to spare a -// string allocation, we do the simplest thing. -func (entry *Entry) sprintlnn(args ...interface{}) string { - msg := fmt.Sprintln(args...) - return msg[:len(msg)-1] -} diff --git a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go deleted file mode 100644 index a1623ec0..00000000 --- a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "github.com/Sirupsen/logrus" -) - -var log = logrus.New() - -func init() { - log.Formatter = new(logrus.JSONFormatter) - log.Formatter = new(logrus.TextFormatter) // default - log.Level = logrus.DebugLevel -} - -func main() { - defer func() { - err := recover() - if err != nil { - log.WithFields(logrus.Fields{ - "omg": true, - "err": err, - "number": 100, - }).Fatal("The ice breaks!") - } - }() - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "number": 8, - }).Debug("Started observing beach") - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") - - log.WithFields(logrus.Fields{ - "omg": true, - "number": 122, - }).Warn("The group's number increased tremendously!") - - log.WithFields(logrus.Fields{ - "temperature": -4, - }).Debug("Temperature changes") - - log.WithFields(logrus.Fields{ - "animal": "orca", - "size": 9009, - }).Panic("It's over 9000!") -} diff --git a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go deleted file mode 100644 index 3187f6d3..00000000 --- a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "github.com/Sirupsen/logrus" - "gopkg.in/gemnasium/logrus-airbrake-hook.v2" -) - -var log = logrus.New() - -func init() { - log.Formatter = new(logrus.TextFormatter) // default - log.Hooks.Add(airbrake.NewHook(123, "xyz", "development")) -} - -func main() { - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") - - log.WithFields(logrus.Fields{ - "omg": true, - "number": 122, - }).Warn("The group's number increased tremendously!") - - log.WithFields(logrus.Fields{ - "omg": true, - "number": 100, - }).Fatal("The ice breaks!") -} diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go deleted file mode 100644 index 9a0120ac..00000000 --- a/vendor/github.com/Sirupsen/logrus/exported.go +++ /dev/null @@ -1,193 +0,0 @@ -package logrus - -import ( - "io" -) - -var ( - // std is the name of the standard logger in stdlib `log` - std = New() -) - -func StandardLogger() *Logger { - return std -} - -// SetOutput sets the standard logger output. -func SetOutput(out io.Writer) { - std.mu.Lock() - defer std.mu.Unlock() - std.Out = out -} - -// SetFormatter sets the standard logger formatter. -func SetFormatter(formatter Formatter) { - std.mu.Lock() - defer std.mu.Unlock() - std.Formatter = formatter -} - -// SetLevel sets the standard logger level. -func SetLevel(level Level) { - std.mu.Lock() - defer std.mu.Unlock() - std.Level = level -} - -// GetLevel returns the standard logger level. -func GetLevel() Level { - std.mu.Lock() - defer std.mu.Unlock() - return std.Level -} - -// AddHook adds a hook to the standard logger hooks. -func AddHook(hook Hook) { - std.mu.Lock() - defer std.mu.Unlock() - std.Hooks.Add(hook) -} - -// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. -func WithError(err error) *Entry { - return std.WithField(ErrorKey, err) -} - -// WithField creates an entry from the standard logger and adds a field to -// it. If you want multiple fields, use `WithFields`. -// -// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal -// or Panic on the Entry it returns. -func WithField(key string, value interface{}) *Entry { - return std.WithField(key, value) -} - -// WithFields creates an entry from the standard logger and adds multiple -// fields to it. This is simply a helper for `WithField`, invoking it -// once for each field. -// -// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal -// or Panic on the Entry it returns. -func WithFields(fields Fields) *Entry { - return std.WithFields(fields) -} - -// Debug logs a message at level Debug on the standard logger. -func Debug(args ...interface{}) { - std.Debug(args...) -} - -// Print logs a message at level Info on the standard logger. -func Print(args ...interface{}) { - std.Print(args...) -} - -// Info logs a message at level Info on the standard logger. -func Info(args ...interface{}) { - std.Info(args...) -} - -// Warn logs a message at level Warn on the standard logger. -func Warn(args ...interface{}) { - std.Warn(args...) -} - -// Warning logs a message at level Warn on the standard logger. -func Warning(args ...interface{}) { - std.Warning(args...) -} - -// Error logs a message at level Error on the standard logger. -func Error(args ...interface{}) { - std.Error(args...) -} - -// Panic logs a message at level Panic on the standard logger. -func Panic(args ...interface{}) { - std.Panic(args...) -} - -// Fatal logs a message at level Fatal on the standard logger. -func Fatal(args ...interface{}) { - std.Fatal(args...) -} - -// Debugf logs a message at level Debug on the standard logger. -func Debugf(format string, args ...interface{}) { - std.Debugf(format, args...) -} - -// Printf logs a message at level Info on the standard logger. -func Printf(format string, args ...interface{}) { - std.Printf(format, args...) -} - -// Infof logs a message at level Info on the standard logger. -func Infof(format string, args ...interface{}) { - std.Infof(format, args...) -} - -// Warnf logs a message at level Warn on the standard logger. -func Warnf(format string, args ...interface{}) { - std.Warnf(format, args...) -} - -// Warningf logs a message at level Warn on the standard logger. -func Warningf(format string, args ...interface{}) { - std.Warningf(format, args...) -} - -// Errorf logs a message at level Error on the standard logger. -func Errorf(format string, args ...interface{}) { - std.Errorf(format, args...) -} - -// Panicf logs a message at level Panic on the standard logger. -func Panicf(format string, args ...interface{}) { - std.Panicf(format, args...) -} - -// Fatalf logs a message at level Fatal on the standard logger. -func Fatalf(format string, args ...interface{}) { - std.Fatalf(format, args...) -} - -// Debugln logs a message at level Debug on the standard logger. -func Debugln(args ...interface{}) { - std.Debugln(args...) -} - -// Println logs a message at level Info on the standard logger. -func Println(args ...interface{}) { - std.Println(args...) -} - -// Infoln logs a message at level Info on the standard logger. -func Infoln(args ...interface{}) { - std.Infoln(args...) -} - -// Warnln logs a message at level Warn on the standard logger. -func Warnln(args ...interface{}) { - std.Warnln(args...) -} - -// Warningln logs a message at level Warn on the standard logger. -func Warningln(args ...interface{}) { - std.Warningln(args...) -} - -// Errorln logs a message at level Error on the standard logger. -func Errorln(args ...interface{}) { - std.Errorln(args...) -} - -// Panicln logs a message at level Panic on the standard logger. -func Panicln(args ...interface{}) { - std.Panicln(args...) -} - -// Fatalln logs a message at level Fatal on the standard logger. -func Fatalln(args ...interface{}) { - std.Fatalln(args...) -} diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go deleted file mode 100644 index 104d689f..00000000 --- a/vendor/github.com/Sirupsen/logrus/formatter.go +++ /dev/null @@ -1,48 +0,0 @@ -package logrus - -import "time" - -const DefaultTimestampFormat = time.RFC3339 - -// The Formatter interface is used to implement a custom Formatter. It takes an -// `Entry`. It exposes all the fields, including the default ones: -// -// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. -// * `entry.Data["time"]`. The timestamp. -// * `entry.Data["level"]. The level the entry was logged at. -// -// Any additional fields added with `WithField` or `WithFields` are also in -// `entry.Data`. Format is expected to return an array of bytes which are then -// logged to `logger.Out`. -type Formatter interface { - Format(*Entry) ([]byte, error) -} - -// This is to not silently overwrite `time`, `msg` and `level` fields when -// dumping it. If this code wasn't there doing: -// -// logrus.WithField("level", 1).Info("hello") -// -// Would just silently drop the user provided level. Instead with this code -// it'll logged as: -// -// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} -// -// It's not exported because it's still using Data in an opinionated way. It's to -// avoid code duplication between the two default formatters. -func prefixFieldClashes(data Fields) { - _, ok := data["time"] - if ok { - data["fields.time"] = data["time"] - } - - _, ok = data["msg"] - if ok { - data["fields.msg"] = data["msg"] - } - - _, ok = data["level"] - if ok { - data["fields.level"] = data["level"] - } -} diff --git a/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go b/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go deleted file mode 100644 index aad646ab..00000000 --- a/vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go +++ /dev/null @@ -1,61 +0,0 @@ -package logstash - -import ( - "encoding/json" - "fmt" - - "github.com/Sirupsen/logrus" -) - -// Formatter generates json in logstash format. -// Logstash site: http://logstash.net/ -type LogstashFormatter struct { - Type string // if not empty use for logstash type field. - - // TimestampFormat sets the format used for timestamps. - TimestampFormat string -} - -func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { - fields := make(logrus.Fields) - for k, v := range entry.Data { - fields[k] = v - } - - fields["@version"] = 1 - - if f.TimestampFormat == "" { - f.TimestampFormat = logrus.DefaultTimestampFormat - } - - fields["@timestamp"] = entry.Time.Format(f.TimestampFormat) - - // set message field - v, ok := entry.Data["message"] - if ok { - fields["fields.message"] = v - } - fields["message"] = entry.Message - - // set level field - v, ok = entry.Data["level"] - if ok { - fields["fields.level"] = v - } - fields["level"] = entry.Level.String() - - // set type field - if f.Type != "" { - v, ok = entry.Data["type"] - if ok { - fields["fields.type"] = v - } - fields["type"] = f.Type - } - - serialized, err := json.Marshal(fields) - if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) - } - return append(serialized, '\n'), nil -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/Sirupsen/logrus/hooks.go deleted file mode 100644 index 3f151cdc..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks.go +++ /dev/null @@ -1,34 +0,0 @@ -package logrus - -// A hook to be fired when logging on the logging levels returned from -// `Levels()` on your implementation of the interface. Note that this is not -// fired in a goroutine or a channel with workers, you should handle such -// functionality yourself if your call is non-blocking and you don't wish for -// the logging calls for levels returned from `Levels()` to block. -type Hook interface { - Levels() []Level - Fire(*Entry) error -} - -// Internal type for storing the hooks on a logger instance. -type LevelHooks map[Level][]Hook - -// Add a hook to an instance of logger. This is called with -// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. -func (hooks LevelHooks) Add(hook Hook) { - for _, level := range hook.Levels() { - hooks[level] = append(hooks[level], hook) - } -} - -// Fire all the hooks for the passed level. Used by `entry.log` to fire -// appropriate hooks for a log entry. -func (hooks LevelHooks) Fire(level Level, entry *Entry) error { - for _, hook := range hooks[level] { - if err := hook.Fire(entry); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md deleted file mode 100644 index 066704b3..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Syslog Hooks for Logrus :walrus: - -## Usage - -```go -import ( - "log/syslog" - "github.com/Sirupsen/logrus" - logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" -) - -func main() { - log := logrus.New() - hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") - - if err == nil { - log.Hooks.Add(hook) - } -} -``` - -If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following. - -```go -import ( - "log/syslog" - "github.com/Sirupsen/logrus" - logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" -) - -func main() { - log := logrus.New() - hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") - - if err == nil { - log.Hooks.Add(hook) - } -} -``` \ No newline at end of file diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go deleted file mode 100644 index c59f331d..00000000 --- a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build !windows,!nacl,!plan9 - -package logrus_syslog - -import ( - "fmt" - "github.com/Sirupsen/logrus" - "log/syslog" - "os" -) - -// SyslogHook to send logs via syslog. -type SyslogHook struct { - Writer *syslog.Writer - SyslogNetwork string - SyslogRaddr string -} - -// Creates a hook to be added to an instance of logger. This is called with -// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` -// `if err == nil { log.Hooks.Add(hook) }` -func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { - w, err := syslog.Dial(network, raddr, priority, tag) - return &SyslogHook{w, network, raddr}, err -} - -func (hook *SyslogHook) Fire(entry *logrus.Entry) error { - line, err := entry.String() - if err != nil { - fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) - return err - } - - switch entry.Level { - case logrus.PanicLevel: - return hook.Writer.Crit(line) - case logrus.FatalLevel: - return hook.Writer.Crit(line) - case logrus.ErrorLevel: - return hook.Writer.Err(line) - case logrus.WarnLevel: - return hook.Writer.Warning(line) - case logrus.InfoLevel: - return hook.Writer.Info(line) - case logrus.DebugLevel: - return hook.Writer.Debug(line) - default: - return nil - } -} - -func (hook *SyslogHook) Levels() []logrus.Level { - return []logrus.Level{ - logrus.PanicLevel, - logrus.FatalLevel, - logrus.ErrorLevel, - logrus.WarnLevel, - logrus.InfoLevel, - logrus.DebugLevel, - } -} diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go deleted file mode 100644 index 2ad6dc5c..00000000 --- a/vendor/github.com/Sirupsen/logrus/json_formatter.go +++ /dev/null @@ -1,41 +0,0 @@ -package logrus - -import ( - "encoding/json" - "fmt" -) - -type JSONFormatter struct { - // TimestampFormat sets the format used for marshaling timestamps. - TimestampFormat string -} - -func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { - data := make(Fields, len(entry.Data)+3) - for k, v := range entry.Data { - switch v := v.(type) { - case error: - // Otherwise errors are ignored by `encoding/json` - // https://github.com/Sirupsen/logrus/issues/137 - data[k] = v.Error() - default: - data[k] = v - } - } - prefixFieldClashes(data) - - timestampFormat := f.TimestampFormat - if timestampFormat == "" { - timestampFormat = DefaultTimestampFormat - } - - data["time"] = entry.Time.Format(timestampFormat) - data["msg"] = entry.Message - data["level"] = entry.Level.String() - - serialized, err := json.Marshal(data) - if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) - } - return append(serialized, '\n'), nil -} diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go deleted file mode 100644 index 2fdb2317..00000000 --- a/vendor/github.com/Sirupsen/logrus/logger.go +++ /dev/null @@ -1,212 +0,0 @@ -package logrus - -import ( - "io" - "os" - "sync" -) - -type Logger struct { - // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a - // file, or leave it default which is `os.Stderr`. You can also set this to - // something more adventorous, such as logging to Kafka. - Out io.Writer - // Hooks for the logger instance. These allow firing events based on logging - // levels and log entries. For example, to send errors to an error tracking - // service, log to StatsD or dump the core on fatal errors. - Hooks LevelHooks - // All log entries pass through the formatter before logged to Out. The - // included formatters are `TextFormatter` and `JSONFormatter` for which - // TextFormatter is the default. In development (when a TTY is attached) it - // logs with colors, but to a file it wouldn't. You can easily implement your - // own that implements the `Formatter` interface, see the `README` or included - // formatters for examples. - Formatter Formatter - // The logging level the logger should log at. This is typically (and defaults - // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be - // logged. `logrus.Debug` is useful in - Level Level - // Used to sync writing to the log. - mu sync.Mutex -} - -// Creates a new logger. Configuration should be set by changing `Formatter`, -// `Out` and `Hooks` directly on the default logger instance. You can also just -// instantiate your own: -// -// var log = &Logger{ -// Out: os.Stderr, -// Formatter: new(JSONFormatter), -// Hooks: make(LevelHooks), -// Level: logrus.DebugLevel, -// } -// -// It's recommended to make this a global instance called `log`. -func New() *Logger { - return &Logger{ - Out: os.Stderr, - Formatter: new(TextFormatter), - Hooks: make(LevelHooks), - Level: InfoLevel, - } -} - -// Adds a field to the log entry, note that you it doesn't log until you call -// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry. -// If you want multiple fields, use `WithFields`. -func (logger *Logger) WithField(key string, value interface{}) *Entry { - return NewEntry(logger).WithField(key, value) -} - -// Adds a struct of fields to the log entry. All it does is call `WithField` for -// each `Field`. -func (logger *Logger) WithFields(fields Fields) *Entry { - return NewEntry(logger).WithFields(fields) -} - -// Add an error as single field to the log entry. All it does is call -// `WithError` for the given `error`. -func (logger *Logger) WithError(err error) *Entry { - return NewEntry(logger).WithError(err) -} - -func (logger *Logger) Debugf(format string, args ...interface{}) { - if logger.Level >= DebugLevel { - NewEntry(logger).Debugf(format, args...) - } -} - -func (logger *Logger) Infof(format string, args ...interface{}) { - if logger.Level >= InfoLevel { - NewEntry(logger).Infof(format, args...) - } -} - -func (logger *Logger) Printf(format string, args ...interface{}) { - NewEntry(logger).Printf(format, args...) -} - -func (logger *Logger) Warnf(format string, args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warnf(format, args...) - } -} - -func (logger *Logger) Warningf(format string, args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warnf(format, args...) - } -} - -func (logger *Logger) Errorf(format string, args ...interface{}) { - if logger.Level >= ErrorLevel { - NewEntry(logger).Errorf(format, args...) - } -} - -func (logger *Logger) Fatalf(format string, args ...interface{}) { - if logger.Level >= FatalLevel { - NewEntry(logger).Fatalf(format, args...) - } - os.Exit(1) -} - -func (logger *Logger) Panicf(format string, args ...interface{}) { - if logger.Level >= PanicLevel { - NewEntry(logger).Panicf(format, args...) - } -} - -func (logger *Logger) Debug(args ...interface{}) { - if logger.Level >= DebugLevel { - NewEntry(logger).Debug(args...) - } -} - -func (logger *Logger) Info(args ...interface{}) { - if logger.Level >= InfoLevel { - NewEntry(logger).Info(args...) - } -} - -func (logger *Logger) Print(args ...interface{}) { - NewEntry(logger).Info(args...) -} - -func (logger *Logger) Warn(args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warn(args...) - } -} - -func (logger *Logger) Warning(args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warn(args...) - } -} - -func (logger *Logger) Error(args ...interface{}) { - if logger.Level >= ErrorLevel { - NewEntry(logger).Error(args...) - } -} - -func (logger *Logger) Fatal(args ...interface{}) { - if logger.Level >= FatalLevel { - NewEntry(logger).Fatal(args...) - } - os.Exit(1) -} - -func (logger *Logger) Panic(args ...interface{}) { - if logger.Level >= PanicLevel { - NewEntry(logger).Panic(args...) - } -} - -func (logger *Logger) Debugln(args ...interface{}) { - if logger.Level >= DebugLevel { - NewEntry(logger).Debugln(args...) - } -} - -func (logger *Logger) Infoln(args ...interface{}) { - if logger.Level >= InfoLevel { - NewEntry(logger).Infoln(args...) - } -} - -func (logger *Logger) Println(args ...interface{}) { - NewEntry(logger).Println(args...) -} - -func (logger *Logger) Warnln(args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warnln(args...) - } -} - -func (logger *Logger) Warningln(args ...interface{}) { - if logger.Level >= WarnLevel { - NewEntry(logger).Warnln(args...) - } -} - -func (logger *Logger) Errorln(args ...interface{}) { - if logger.Level >= ErrorLevel { - NewEntry(logger).Errorln(args...) - } -} - -func (logger *Logger) Fatalln(args ...interface{}) { - if logger.Level >= FatalLevel { - NewEntry(logger).Fatalln(args...) - } - os.Exit(1) -} - -func (logger *Logger) Panicln(args ...interface{}) { - if logger.Level >= PanicLevel { - NewEntry(logger).Panicln(args...) - } -} diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go deleted file mode 100644 index 0c09fbc2..00000000 --- a/vendor/github.com/Sirupsen/logrus/logrus.go +++ /dev/null @@ -1,98 +0,0 @@ -package logrus - -import ( - "fmt" - "log" -) - -// Fields type, used to pass to `WithFields`. -type Fields map[string]interface{} - -// Level type -type Level uint8 - -// Convert the Level to a string. E.g. PanicLevel becomes "panic". -func (level Level) String() string { - switch level { - case DebugLevel: - return "debug" - case InfoLevel: - return "info" - case WarnLevel: - return "warning" - case ErrorLevel: - return "error" - case FatalLevel: - return "fatal" - case PanicLevel: - return "panic" - } - - return "unknown" -} - -// ParseLevel takes a string level and returns the Logrus log level constant. -func ParseLevel(lvl string) (Level, error) { - switch lvl { - case "panic": - return PanicLevel, nil - case "fatal": - return FatalLevel, nil - case "error": - return ErrorLevel, nil - case "warn", "warning": - return WarnLevel, nil - case "info": - return InfoLevel, nil - case "debug": - return DebugLevel, nil - } - - var l Level - return l, fmt.Errorf("not a valid logrus Level: %q", lvl) -} - -// These are the different logging levels. You can set the logging level to log -// on your instance of logger, obtained with `logrus.New()`. -const ( - // PanicLevel level, highest level of severity. Logs and then calls panic with the - // message passed to Debug, Info, ... - PanicLevel Level = iota - // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the - // logging level is set to Panic. - FatalLevel - // ErrorLevel level. Logs. Used for errors that should definitely be noted. - // Commonly used for hooks to send errors to an error tracking service. - ErrorLevel - // WarnLevel level. Non-critical entries that deserve eyes. - WarnLevel - // InfoLevel level. General operational entries about what's going on inside the - // application. - InfoLevel - // DebugLevel level. Usually only enabled when debugging. Very verbose logging. - DebugLevel -) - -// Won't compile if StdLogger can't be realized by a log.Logger -var ( - _ StdLogger = &log.Logger{} - _ StdLogger = &Entry{} - _ StdLogger = &Logger{} -) - -// StdLogger is what your logrus-enabled library should take, that way -// it'll accept a stdlib logger and a logrus logger. There's no standard -// interface, this is the closest we get, unfortunately. -type StdLogger interface { - Print(...interface{}) - Printf(string, ...interface{}) - Println(...interface{}) - - Fatal(...interface{}) - Fatalf(string, ...interface{}) - Fatalln(...interface{}) - - Panic(...interface{}) - Panicf(string, ...interface{}) - Panicln(...interface{}) -} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go deleted file mode 100644 index 71f8d67a..00000000 --- a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build darwin freebsd openbsd netbsd dragonfly - -package logrus - -import "syscall" - -const ioctlReadTermios = syscall.TIOCGETA - -type Termios syscall.Termios diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go deleted file mode 100644 index a2c0b40d..00000000 --- a/vendor/github.com/Sirupsen/logrus/terminal_linux.go +++ /dev/null @@ -1,12 +0,0 @@ -// Based on ssh/terminal: -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package logrus - -import "syscall" - -const ioctlReadTermios = syscall.TCGETS - -type Termios syscall.Termios diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go deleted file mode 100644 index b343b3a3..00000000 --- a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go +++ /dev/null @@ -1,21 +0,0 @@ -// Based on ssh/terminal: -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux darwin freebsd openbsd netbsd dragonfly - -package logrus - -import ( - "syscall" - "unsafe" -) - -// IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { - fd := syscall.Stderr - var termios Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 -} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go deleted file mode 100644 index 3e70bf7b..00000000 --- a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build solaris - -package logrus - -import ( - "os" - - "golang.org/x/sys/unix" -) - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal() bool { - _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) - return err == nil -} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go deleted file mode 100644 index 0146845d..00000000 --- a/vendor/github.com/Sirupsen/logrus/terminal_windows.go +++ /dev/null @@ -1,27 +0,0 @@ -// Based on ssh/terminal: -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -package logrus - -import ( - "syscall" - "unsafe" -) - -var kernel32 = syscall.NewLazyDLL("kernel32.dll") - -var ( - procGetConsoleMode = kernel32.NewProc("GetConsoleMode") -) - -// IsTerminal returns true if stderr's file descriptor is a terminal. -func IsTerminal() bool { - fd := syscall.Stderr - var st uint32 - r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - return r != 0 && e == 0 -} diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go deleted file mode 100644 index 06ef2023..00000000 --- a/vendor/github.com/Sirupsen/logrus/text_formatter.go +++ /dev/null @@ -1,161 +0,0 @@ -package logrus - -import ( - "bytes" - "fmt" - "runtime" - "sort" - "strings" - "time" -) - -const ( - nocolor = 0 - red = 31 - green = 32 - yellow = 33 - blue = 34 - gray = 37 -) - -var ( - baseTimestamp time.Time - isTerminal bool -) - -func init() { - baseTimestamp = time.Now() - isTerminal = IsTerminal() -} - -func miniTS() int { - return int(time.Since(baseTimestamp) / time.Second) -} - -type TextFormatter struct { - // Set to true to bypass checking for a TTY before outputting colors. - ForceColors bool - - // Force disabling colors. - DisableColors bool - - // Disable timestamp logging. useful when output is redirected to logging - // system that already adds timestamps. - DisableTimestamp bool - - // Enable logging the full timestamp when a TTY is attached instead of just - // the time passed since beginning of execution. - FullTimestamp bool - - // TimestampFormat to use for display when a full timestamp is printed - TimestampFormat string - - // The fields are sorted by default for a consistent output. For applications - // that log extremely frequently and don't use the JSON formatter this may not - // be desired. - DisableSorting bool -} - -func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { - var keys []string = make([]string, 0, len(entry.Data)) - for k := range entry.Data { - keys = append(keys, k) - } - - if !f.DisableSorting { - sort.Strings(keys) - } - - b := &bytes.Buffer{} - - prefixFieldClashes(entry.Data) - - isColorTerminal := isTerminal && (runtime.GOOS != "windows") - isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors - - timestampFormat := f.TimestampFormat - if timestampFormat == "" { - timestampFormat = DefaultTimestampFormat - } - if isColored { - f.printColored(b, entry, keys, timestampFormat) - } else { - if !f.DisableTimestamp { - f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) - } - f.appendKeyValue(b, "level", entry.Level.String()) - if entry.Message != "" { - f.appendKeyValue(b, "msg", entry.Message) - } - for _, key := range keys { - f.appendKeyValue(b, key, entry.Data[key]) - } - } - - b.WriteByte('\n') - return b.Bytes(), nil -} - -func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { - var levelColor int - switch entry.Level { - case DebugLevel: - levelColor = gray - case WarnLevel: - levelColor = yellow - case ErrorLevel, FatalLevel, PanicLevel: - levelColor = red - default: - levelColor = blue - } - - levelText := strings.ToUpper(entry.Level.String())[0:4] - - if !f.FullTimestamp { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message) - } else { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) - } - for _, k := range keys { - v := entry.Data[k] - fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v) - } -} - -func needsQuoting(text string) bool { - for _, ch := range text { - if !((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '-' || ch == '.') { - return false - } - } - return true -} - -func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { - - b.WriteString(key) - b.WriteByte('=') - - switch value := value.(type) { - case string: - if needsQuoting(value) { - b.WriteString(value) - } else { - fmt.Fprintf(b, "%q", value) - } - case error: - errmsg := value.Error() - if needsQuoting(errmsg) { - b.WriteString(errmsg) - } else { - fmt.Fprintf(b, "%q", value) - } - default: - fmt.Fprint(b, value) - } - - b.WriteByte(' ') -} diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go deleted file mode 100644 index 1e30b1c7..00000000 --- a/vendor/github.com/Sirupsen/logrus/writer.go +++ /dev/null @@ -1,31 +0,0 @@ -package logrus - -import ( - "bufio" - "io" - "runtime" -) - -func (logger *Logger) Writer() *io.PipeWriter { - reader, writer := io.Pipe() - - go logger.writerScanner(reader) - runtime.SetFinalizer(writer, writerFinalizer) - - return writer -} - -func (logger *Logger) writerScanner(reader *io.PipeReader) { - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - logger.Print(scanner.Text()) - } - if err := scanner.Err(); err != nil { - logger.Errorf("Error while reading from Writer: %s", err) - } - reader.Close() -} - -func writerFinalizer(writer *io.PipeWriter) { - writer.Close() -} diff --git a/vendor/github.com/go-sql-driver/mysql/.travis.yml b/vendor/github.com/go-sql-driver/mysql/.travis.yml index c48cedd8..2f4e3c2f 100644 --- a/vendor/github.com/go-sql-driver/mysql/.travis.yml +++ b/vendor/github.com/go-sql-driver/mysql/.travis.yml @@ -4,7 +4,6 @@ go: - 1.2 - 1.3 - 1.4 - - 1.5 - tip before_script: diff --git a/vendor/github.com/go-sql-driver/mysql/AUTHORS b/vendor/github.com/go-sql-driver/mysql/AUTHORS index e86676ff..6dd0167f 100644 --- a/vendor/github.com/go-sql-driver/mysql/AUTHORS +++ b/vendor/github.com/go-sql-driver/mysql/AUTHORS @@ -15,7 +15,6 @@ Aaron Hopkins Arne Hormann Carlos Nieto Chris Moos -Daniel Nichter DisposaBoy Frederick Mayle Gustavo Kristic @@ -26,10 +25,8 @@ INADA Naoki James Harr Jian Zhen Joshua Prunier -Julien Lefevre Julien Schmidt Kamil Dziedzic -Kevin Malachowski Leonardo YongUk Kim Lucas Liu Luke Scott @@ -40,6 +37,7 @@ Soroush Pour Stan Putrya Xiaobing Jiang Xiuming Chen +Julien Lefevre # Organizations diff --git a/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md b/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md index 381d9182..161ad0fc 100644 --- a/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md +++ b/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md @@ -12,21 +12,10 @@ Bugfixes: - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249) - Fixed handling of queries without columns and rows (#255) - Fixed a panic when SetKeepAlive() failed (#298) - - Support receiving ERR packet while reading rows (#321) - - Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349) - - Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356) - - Actually zero out bytes in handshake response (#378) - - Fixed race condition in registering LOAD DATA INFILE handler (#383) - - Fixed tests with MySQL 5.7.9+ (#380) - - QueryUnescape TLS config names (#397) - - Fixed "broken pipe" error by writing to closed socket (#390) New Features: - - Support for returning table alias on Columns() (#289, #359, #382) + - Support for returning table alias on Columns() (#289) - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318) - - Support for uint64 parameters with high bit set (#332, #345) - - Cleartext authentication plugin support (#327) - ## Version 1.2 (2014-06-03) diff --git a/vendor/github.com/go-sql-driver/mysql/README.md b/vendor/github.com/go-sql-driver/mysql/README.md index f3190e8a..706b7ef2 100644 --- a/vendor/github.com/go-sql-driver/mysql/README.md +++ b/vendor/github.com/go-sql-driver/mysql/README.md @@ -231,16 +231,6 @@ Default: false `parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string` -##### `readTimeout` - -``` -Type: decimal number -Default: 0 -``` - -I/O read timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. - - ##### `strict` ``` @@ -261,7 +251,7 @@ Type: decimal number Default: OS default ``` -*Driver* side connection timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout). +*Driver* side connection timeout. The value must be a string of decimal numbers, each with optional fraction and a unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout). ##### `tls` @@ -275,16 +265,6 @@ Default: false `tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](http://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). -##### `writeTimeout` - -``` -Type: decimal number -Default: 0 -``` - -I/O write timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. - - ##### System Variables All other parameters are interpreted as system variables: diff --git a/vendor/github.com/go-sql-driver/mysql/buffer.go b/vendor/github.com/go-sql-driver/mysql/buffer.go index 2001feac..509ce89e 100644 --- a/vendor/github.com/go-sql-driver/mysql/buffer.go +++ b/vendor/github.com/go-sql-driver/mysql/buffer.go @@ -8,11 +8,7 @@ package mysql -import ( - "io" - "net" - "time" -) +import "io" const defaultBufSize = 4096 @@ -22,18 +18,17 @@ const defaultBufSize = 4096 // The buffer is similar to bufio.Reader / Writer but zero-copy-ish // Also highly optimized for this particular use case. type buffer struct { - buf []byte - nc net.Conn - idx int - length int - timeout time.Duration + buf []byte + rd io.Reader + idx int + length int } -func newBuffer(nc net.Conn) buffer { +func newBuffer(rd io.Reader) buffer { var b [defaultBufSize]byte return buffer{ buf: b[:], - nc: nc, + rd: rd, } } @@ -59,13 +54,7 @@ func (b *buffer) fill(need int) error { b.idx = 0 for { - if b.timeout > 0 { - if err := b.nc.SetReadDeadline(time.Now().Add(b.timeout)); err != nil { - return err - } - } - - nn, err := b.nc.Read(b.buf[n:]) + nn, err := b.rd.Read(b.buf[n:]) n += nn switch err { diff --git a/vendor/github.com/go-sql-driver/mysql/connection.go b/vendor/github.com/go-sql-driver/mysql/connection.go index c3899de0..72ed09d6 100644 --- a/vendor/github.com/go-sql-driver/mysql/connection.go +++ b/vendor/github.com/go-sql-driver/mysql/connection.go @@ -9,7 +9,9 @@ package mysql import ( + "crypto/tls" "database/sql/driver" + "errors" "net" "strconv" "strings" @@ -21,10 +23,9 @@ type mysqlConn struct { netConn net.Conn affectedRows uint64 insertId uint64 - cfg *Config + cfg *config maxPacketAllowed int maxWriteSize int - writeTimeout time.Duration flags clientFlag status statusFlag sequence uint8 @@ -32,9 +33,28 @@ type mysqlConn struct { strict bool } +type config struct { + user string + passwd string + net string + addr string + dbname string + params map[string]string + loc *time.Location + tls *tls.Config + timeout time.Duration + collation uint8 + allowAllFiles bool + allowOldPasswords bool + allowCleartextPasswords bool + clientFoundRows bool + columnsWithAlias bool + interpolateParams bool +} + // Handles parameters set in DSN after the connection is established func (mc *mysqlConn) handleParams() (err error) { - for param, val := range mc.cfg.Params { + for param, val := range mc.cfg.params { switch param { // Charset case "charset": @@ -50,6 +70,27 @@ func (mc *mysqlConn) handleParams() (err error) { return } + // time.Time parsing + case "parseTime": + var isBool bool + mc.parseTime, isBool = readBool(val) + if !isBool { + return errors.New("Invalid Bool value: " + val) + } + + // Strict mode + case "strict": + var isBool bool + mc.strict, isBool = readBool(val) + if !isBool { + return errors.New("Invalid Bool value: " + val) + } + + // Compression + case "compress": + err = errors.New("Compression not implemented yet") + return + // System Vars default: err = mc.exec("SET " + param + "=" + val + "") @@ -79,27 +120,18 @@ func (mc *mysqlConn) Close() (err error) { // Makes Close idempotent if mc.netConn != nil { err = mc.writeCommandPacket(comQuit) - } - - mc.cleanup() - - return -} - -// Closes the network connection and unsets internal variables. Do not call this -// function after successfully authentication, call Close instead. This function -// is called before auth or on auth failure because MySQL will have already -// closed the network connection. -func (mc *mysqlConn) cleanup() { - // Makes cleanup idempotent - if mc.netConn != nil { - if err := mc.netConn.Close(); err != nil { - errLog.Print(err) + if err == nil { + err = mc.netConn.Close() + } else { + mc.netConn.Close() } mc.netConn = nil } + mc.cfg = nil - mc.buf.nc = nil + mc.buf.rd = nil + + return } func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) { @@ -176,7 +208,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin if v.IsZero() { buf = append(buf, "'0000-00-00'"...) } else { - v := v.In(mc.cfg.Loc) + v := v.In(mc.cfg.loc) v = v.Add(time.Nanosecond * 500) // To round under microsecond year := v.Year() year100 := year / 100 @@ -257,7 +289,7 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err return nil, driver.ErrBadConn } if len(args) != 0 { - if !mc.cfg.InterpolateParams { + if !mc.cfg.interpolateParams { return nil, driver.ErrSkip } // try to interpolate the parameters to save extra roundtrips for preparing and closing a statement @@ -308,7 +340,7 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro return nil, driver.ErrBadConn } if len(args) != 0 { - if !mc.cfg.InterpolateParams { + if !mc.cfg.interpolateParams { return nil, driver.ErrSkip } // try client-side prepare to reduce roundtrip @@ -354,7 +386,6 @@ func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) { if err == nil { rows := new(textRows) rows.mc = mc - rows.columns = []mysqlField{{fieldType: fieldTypeVarChar}} if resLen > 0 { // Columns diff --git a/vendor/github.com/go-sql-driver/mysql/const.go b/vendor/github.com/go-sql-driver/mysql/const.go index 88cfff3f..dddc1290 100644 --- a/vendor/github.com/go-sql-driver/mysql/const.go +++ b/vendor/github.com/go-sql-driver/mysql/const.go @@ -107,8 +107,7 @@ const ( fieldTypeBit ) const ( - fieldTypeJSON byte = iota + 0xf5 - fieldTypeNewDecimal + fieldTypeNewDecimal byte = iota + 0xf6 fieldTypeEnum fieldTypeSet fieldTypeTinyBLOB diff --git a/vendor/github.com/go-sql-driver/mysql/driver.go b/vendor/github.com/go-sql-driver/mysql/driver.go index 899f955f..d310624a 100644 --- a/vendor/github.com/go-sql-driver/mysql/driver.go +++ b/vendor/github.com/go-sql-driver/mysql/driver.go @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -// Package mysql provides a MySQL driver for Go's database/sql package +// Go MySQL Driver - A MySQL-Driver for Go's database/sql package // // The driver should be used via the database/sql package: // @@ -22,7 +22,7 @@ import ( "net" ) -// MySQLDriver is exported to make the driver directly accessible. +// This struct is exported to make the driver directly accessible. // In general the driver is used via the database/sql package. type MySQLDriver struct{} @@ -53,19 +53,17 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { maxPacketAllowed: maxPacketSize, maxWriteSize: maxPacketSize - 1, } - mc.cfg, err = ParseDSN(dsn) + mc.cfg, err = parseDSN(dsn) if err != nil { return nil, err } - mc.parseTime = mc.cfg.ParseTime - mc.strict = mc.cfg.Strict // Connect to Server - if dial, ok := dials[mc.cfg.Net]; ok { - mc.netConn, err = dial(mc.cfg.Addr) + if dial, ok := dials[mc.cfg.net]; ok { + mc.netConn, err = dial(mc.cfg.addr) } else { - nd := net.Dialer{Timeout: mc.cfg.Timeout} - mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr) + nd := net.Dialer{Timeout: mc.cfg.timeout} + mc.netConn, err = nd.Dial(mc.cfg.net, mc.cfg.addr) } if err != nil { return nil, err @@ -83,30 +81,46 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { mc.buf = newBuffer(mc.netConn) - // Set I/O timeouts - mc.buf.timeout = mc.cfg.ReadTimeout - mc.writeTimeout = mc.cfg.WriteTimeout - // Reading Handshake Initialization Packet cipher, err := mc.readInitPacket() if err != nil { - mc.cleanup() + mc.Close() return nil, err } // Send Client Authentication Packet if err = mc.writeAuthPacket(cipher); err != nil { - mc.cleanup() + mc.Close() return nil, err } - // Handle response to auth packet, switch methods if possible - if err = handleAuthResult(mc, cipher); err != nil { - // Authentication failed and MySQL has already closed the connection - // (https://dev.mysql.com/doc/internals/en/authentication-fails.html). - // Do not send COM_QUIT, just cleanup and return the error. - mc.cleanup() - return nil, err + // Read Result Packet + err = mc.readResultOK() + if err != nil { + // Retry with old authentication method, if allowed + if mc.cfg != nil && mc.cfg.allowOldPasswords && err == ErrOldPassword { + if err = mc.writeOldAuthPacket(cipher); err != nil { + mc.Close() + return nil, err + } + if err = mc.readResultOK(); err != nil { + mc.Close() + return nil, err + } + } else if mc.cfg != nil && mc.cfg.allowCleartextPasswords && err == ErrCleartextPassword { + if err = mc.writeClearAuthPacket(); err != nil { + mc.Close() + return nil, err + } + if err = mc.readResultOK(); err != nil { + mc.Close() + return nil, err + } + } else { + mc.Close() + return nil, err + } + } // Get max allowed packet size @@ -130,38 +144,6 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { return mc, nil } -func handleAuthResult(mc *mysqlConn, cipher []byte) error { - // Read Result Packet - err := mc.readResultOK() - if err == nil { - return nil // auth successful - } - - if mc.cfg == nil { - return err // auth failed and retry not possible - } - - // Retry auth if configured to do so. - if mc.cfg.AllowOldPasswords && err == ErrOldPassword { - // Retry with old authentication method. Note: there are edge cases - // where this should work but doesn't; this is currently "wontfix": - // https://github.com/go-sql-driver/mysql/issues/184 - if err = mc.writeOldAuthPacket(cipher); err != nil { - return err - } - err = mc.readResultOK() - } else if mc.cfg.AllowCleartextPasswords && err == ErrCleartextPassword { - // Retry with clear text password for - // http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html - // http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html - if err = mc.writeClearAuthPacket(); err != nil { - return err - } - err = mc.readResultOK() - } - return err -} - func init() { sql.Register("mysql", &MySQLDriver{}) } diff --git a/vendor/github.com/go-sql-driver/mysql/dsn.go b/vendor/github.com/go-sql-driver/mysql/dsn.go deleted file mode 100644 index 31fd530e..00000000 --- a/vendor/github.com/go-sql-driver/mysql/dsn.go +++ /dev/null @@ -1,314 +0,0 @@ -// Go MySQL Driver - A MySQL-Driver for Go's database/sql package -// -// Copyright 2016 The Go-MySQL-Driver Authors. All rights reserved. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this file, -// You can obtain one at http://mozilla.org/MPL/2.0/. - -package mysql - -import ( - "crypto/tls" - "errors" - "fmt" - "net" - "net/url" - "strings" - "time" -) - -var ( - errInvalidDSNUnescaped = errors.New("invalid DSN: did you forget to escape a param value?") - errInvalidDSNAddr = errors.New("invalid DSN: network address not terminated (missing closing brace)") - errInvalidDSNNoSlash = errors.New("invalid DSN: missing the slash separating the database name") - errInvalidDSNUnsafeCollation = errors.New("invalid DSN: interpolateParams can not be used with unsafe collations") -) - -// Config is a configuration parsed from a DSN string -type Config struct { - User string // Username - Passwd string // Password - Net string // Network type - Addr string // Network address - DBName string // Database name - Params map[string]string // Connection parameters - Loc *time.Location // Location for time.Time values - TLS *tls.Config // TLS configuration - Timeout time.Duration // Dial timeout - ReadTimeout time.Duration // I/O read timeout - WriteTimeout time.Duration // I/O write timeout - Collation uint8 // Connection collation - - AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE - AllowCleartextPasswords bool // Allows the cleartext client side plugin - AllowOldPasswords bool // Allows the old insecure password method - ClientFoundRows bool // Return number of matching rows instead of rows changed - ColumnsWithAlias bool // Prepend table alias to column names - InterpolateParams bool // Interpolate placeholders into query string - ParseTime bool // Parse time values to time.Time - Strict bool // Return warnings as errors -} - -// ParseDSN parses the DSN string to a Config -func ParseDSN(dsn string) (cfg *Config, err error) { - // New config with some default values - cfg = &Config{ - Loc: time.UTC, - Collation: defaultCollation, - } - - // [user[:password]@][net[(addr)]]/dbname[?param1=value1¶mN=valueN] - // Find the last '/' (since the password or the net addr might contain a '/') - foundSlash := false - for i := len(dsn) - 1; i >= 0; i-- { - if dsn[i] == '/' { - foundSlash = true - var j, k int - - // left part is empty if i <= 0 - if i > 0 { - // [username[:password]@][protocol[(address)]] - // Find the last '@' in dsn[:i] - for j = i; j >= 0; j-- { - if dsn[j] == '@' { - // username[:password] - // Find the first ':' in dsn[:j] - for k = 0; k < j; k++ { - if dsn[k] == ':' { - cfg.Passwd = dsn[k+1 : j] - break - } - } - cfg.User = dsn[:k] - - break - } - } - - // [protocol[(address)]] - // Find the first '(' in dsn[j+1:i] - for k = j + 1; k < i; k++ { - if dsn[k] == '(' { - // dsn[i-1] must be == ')' if an address is specified - if dsn[i-1] != ')' { - if strings.ContainsRune(dsn[k+1:i], ')') { - return nil, errInvalidDSNUnescaped - } - return nil, errInvalidDSNAddr - } - cfg.Addr = dsn[k+1 : i-1] - break - } - } - cfg.Net = dsn[j+1 : k] - } - - // dbname[?param1=value1&...¶mN=valueN] - // Find the first '?' in dsn[i+1:] - for j = i + 1; j < len(dsn); j++ { - if dsn[j] == '?' { - if err = parseDSNParams(cfg, dsn[j+1:]); err != nil { - return - } - break - } - } - cfg.DBName = dsn[i+1 : j] - - break - } - } - - if !foundSlash && len(dsn) > 0 { - return nil, errInvalidDSNNoSlash - } - - if cfg.InterpolateParams && unsafeCollations[cfg.Collation] { - return nil, errInvalidDSNUnsafeCollation - } - - // Set default network if empty - if cfg.Net == "" { - cfg.Net = "tcp" - } - - // Set default address if empty - if cfg.Addr == "" { - switch cfg.Net { - case "tcp": - cfg.Addr = "127.0.0.1:3306" - case "unix": - cfg.Addr = "/tmp/mysql.sock" - default: - return nil, errors.New("default addr for network '" + cfg.Net + "' unknown") - } - - } - - return -} - -// parseDSNParams parses the DSN "query string" -// Values must be url.QueryEscape'ed -func parseDSNParams(cfg *Config, params string) (err error) { - for _, v := range strings.Split(params, "&") { - param := strings.SplitN(v, "=", 2) - if len(param) != 2 { - continue - } - - // cfg params - switch value := param[1]; param[0] { - - // Disable INFILE whitelist / enable all files - case "allowAllFiles": - var isBool bool - cfg.AllowAllFiles, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Use cleartext authentication mode (MySQL 5.5.10+) - case "allowCleartextPasswords": - var isBool bool - cfg.AllowCleartextPasswords, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Use old authentication mode (pre MySQL 4.1) - case "allowOldPasswords": - var isBool bool - cfg.AllowOldPasswords, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Switch "rowsAffected" mode - case "clientFoundRows": - var isBool bool - cfg.ClientFoundRows, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Collation - case "collation": - collation, ok := collations[value] - if !ok { - // Note possibility for false negatives: - // could be triggered although the collation is valid if the - // collations map does not contain entries the server supports. - err = errors.New("unknown collation") - return - } - cfg.Collation = collation - break - - case "columnsWithAlias": - var isBool bool - cfg.ColumnsWithAlias, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Compression - case "compress": - return errors.New("compression not implemented yet") - - // Enable client side placeholder substitution - case "interpolateParams": - var isBool bool - cfg.InterpolateParams, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Time Location - case "loc": - if value, err = url.QueryUnescape(value); err != nil { - return - } - cfg.Loc, err = time.LoadLocation(value) - if err != nil { - return - } - - // time.Time parsing - case "parseTime": - var isBool bool - cfg.ParseTime, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // I/O read Timeout - case "readTimeout": - cfg.ReadTimeout, err = time.ParseDuration(value) - if err != nil { - return - } - - // Strict mode - case "strict": - var isBool bool - cfg.Strict, isBool = readBool(value) - if !isBool { - return errors.New("invalid bool value: " + value) - } - - // Dial Timeout - case "timeout": - cfg.Timeout, err = time.ParseDuration(value) - if err != nil { - return - } - - // TLS-Encryption - case "tls": - boolValue, isBool := readBool(value) - if isBool { - if boolValue { - cfg.TLS = &tls.Config{} - } - } else if value, err := url.QueryUnescape(value); err != nil { - return fmt.Errorf("invalid value for TLS config name: %v", err) - } else { - if strings.ToLower(value) == "skip-verify" { - cfg.TLS = &tls.Config{InsecureSkipVerify: true} - } else if tlsConfig, ok := tlsConfigRegister[value]; ok { - if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { - host, _, err := net.SplitHostPort(cfg.Addr) - if err == nil { - tlsConfig.ServerName = host - } - } - - cfg.TLS = tlsConfig - } else { - return errors.New("invalid value / unknown config name: " + value) - } - } - - // I/O write Timeout - case "writeTimeout": - cfg.WriteTimeout, err = time.ParseDuration(value) - if err != nil { - return - } - - default: - // lazy init - if cfg.Params == nil { - cfg.Params = make(map[string]string) - } - - if cfg.Params[param[0]], err = url.QueryUnescape(value); err != nil { - return - } - } - } - - return -} diff --git a/vendor/github.com/go-sql-driver/mysql/errors.go b/vendor/github.com/go-sql-driver/mysql/errors.go index 1543a805..44cf30db 100644 --- a/vendor/github.com/go-sql-driver/mysql/errors.go +++ b/vendor/github.com/go-sql-driver/mysql/errors.go @@ -19,20 +19,20 @@ import ( // Various errors the driver might return. Can change between driver versions. var ( - ErrInvalidConn = errors.New("invalid connection") - ErrMalformPkt = errors.New("malformed packet") - ErrNoTLS = errors.New("TLS requested but server does not support TLS") - ErrOldPassword = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords") - ErrCleartextPassword = errors.New("this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN") - ErrUnknownPlugin = errors.New("this authentication plugin is not supported") - ErrOldProtocol = errors.New("MySQL server does not support required protocol 41+") - ErrPktSync = errors.New("commands out of sync. You can't run this command now") - ErrPktSyncMul = errors.New("commands out of sync. Did you run multiple statements at once?") - ErrPktTooLarge = errors.New("packet for query is too large. Try adjusting the 'max_allowed_packet' variable on the server") - ErrBusyBuffer = errors.New("busy buffer") + ErrInvalidConn = errors.New("Invalid Connection") + ErrMalformPkt = errors.New("Malformed Packet") + ErrNoTLS = errors.New("TLS encryption requested but server does not support TLS") + ErrOldPassword = errors.New("This user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords") + ErrCleartextPassword = errors.New("This user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN.") + ErrUnknownPlugin = errors.New("The authentication plugin is not supported.") + ErrOldProtocol = errors.New("MySQL-Server does not support required Protocol 41+") + ErrPktSync = errors.New("Commands out of sync. You can't run this command now") + ErrPktSyncMul = errors.New("Commands out of sync. Did you run multiple statements at once?") + ErrPktTooLarge = errors.New("Packet for query is too large. You can change this value on the server by adjusting the 'max_allowed_packet' variable.") + ErrBusyBuffer = errors.New("Busy buffer") ) -var errLog = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile)) +var errLog Logger = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile) // Logger is used to log critical error messages. type Logger interface { diff --git a/vendor/github.com/go-sql-driver/mysql/infile.go b/vendor/github.com/go-sql-driver/mysql/infile.go index e3e5e47d..84c53a99 100644 --- a/vendor/github.com/go-sql-driver/mysql/infile.go +++ b/vendor/github.com/go-sql-driver/mysql/infile.go @@ -124,7 +124,7 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) { fileRegisterLock.RLock() fr := fileRegister[name] fileRegisterLock.RUnlock() - if mc.cfg.AllowAllFiles || fr { + if mc.cfg.allowAllFiles || fr { var file *os.File var fi os.FileInfo @@ -139,12 +139,12 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) { } else if fileSize <= mc.maxPacketAllowed { data = make([]byte, 4+mc.maxWriteSize) } else { - err = fmt.Errorf("local file '%s' too large: size: %d, max: %d", name, fileSize, mc.maxPacketAllowed) + err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed) } } } } else { - err = fmt.Errorf("local file '%s' is not registered", name) + err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name) } } @@ -175,8 +175,8 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) { // read OK packet if err == nil { return mc.readResultOK() + } else { + mc.readPacket() } - - mc.readPacket() return err } diff --git a/vendor/github.com/go-sql-driver/mysql/packets.go b/vendor/github.com/go-sql-driver/mysql/packets.go index f5be2172..76cb7c84 100644 --- a/vendor/github.com/go-sql-driver/mysql/packets.go +++ b/vendor/github.com/go-sql-driver/mysql/packets.go @@ -47,8 +47,9 @@ func (mc *mysqlConn) readPacket() ([]byte, error) { if data[3] != mc.sequence { if data[3] > mc.sequence { return nil, ErrPktSyncMul + } else { + return nil, ErrPktSync } - return nil, ErrPktSync } mc.sequence++ @@ -99,12 +100,6 @@ func (mc *mysqlConn) writePacket(data []byte) error { data[3] = mc.sequence // Write packet - if mc.writeTimeout > 0 { - if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.writeTimeout)); err != nil { - return err - } - } - n, err := mc.netConn.Write(data[:4+size]) if err == nil && n == 4+size { mc.sequence++ @@ -145,7 +140,7 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) { // protocol version [1 byte] if data[0] < minProtocolVersion { return nil, fmt.Errorf( - "unsupported protocol version %d. Version %d or higher is required", + "Unsupported MySQL Protocol Version %d. Protocol Version %d or higher is required", data[0], minProtocolVersion, ) @@ -166,7 +161,7 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) { if mc.flags&clientProtocol41 == 0 { return nil, ErrOldProtocol } - if mc.flags&clientSSL == 0 && mc.cfg.TLS != nil { + if mc.flags&clientSSL == 0 && mc.cfg.tls != nil { return nil, ErrNoTLS } pos += 2 @@ -226,22 +221,22 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { clientPluginAuth | mc.flags&clientLongFlag - if mc.cfg.ClientFoundRows { + if mc.cfg.clientFoundRows { clientFlags |= clientFoundRows } // To enable TLS / SSL - if mc.cfg.TLS != nil { + if mc.cfg.tls != nil { clientFlags |= clientSSL } // User Password - scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.Passwd)) + scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.passwd)) - pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + 1 + len(scrambleBuff) + 21 + 1 + pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.user) + 1 + 1 + len(scrambleBuff) + 21 + 1 // To specify a db name - if n := len(mc.cfg.DBName); n > 0 { + if n := len(mc.cfg.dbname); n > 0 { clientFlags |= clientConnectWithDB pktLen += n + 1 } @@ -267,23 +262,23 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { data[11] = 0x00 // Charset [1 byte] - data[12] = mc.cfg.Collation + data[12] = mc.cfg.collation // SSL Connection Request Packet // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest - if mc.cfg.TLS != nil { + if mc.cfg.tls != nil { // Send TLS / SSL request packet if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil { return err } // Switch to TLS - tlsConn := tls.Client(mc.netConn, mc.cfg.TLS) + tlsConn := tls.Client(mc.netConn, mc.cfg.tls) if err := tlsConn.Handshake(); err != nil { return err } mc.netConn = tlsConn - mc.buf.nc = tlsConn + mc.buf.rd = tlsConn } // Filler [23 bytes] (all 0x00) @@ -293,8 +288,8 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { } // User [null terminated string] - if len(mc.cfg.User) > 0 { - pos += copy(data[pos:], mc.cfg.User) + if len(mc.cfg.user) > 0 { + pos += copy(data[pos:], mc.cfg.user) } data[pos] = 0x00 pos++ @@ -304,8 +299,8 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { pos += 1 + copy(data[pos+1:], scrambleBuff) // Databasename [null terminated string] - if len(mc.cfg.DBName) > 0 { - pos += copy(data[pos:], mc.cfg.DBName) + if len(mc.cfg.dbname) > 0 { + pos += copy(data[pos:], mc.cfg.dbname) data[pos] = 0x00 pos++ } @@ -322,7 +317,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error { // User password - scrambleBuff := scrambleOldPassword(cipher, []byte(mc.cfg.Passwd)) + scrambleBuff := scrambleOldPassword(cipher, []byte(mc.cfg.passwd)) // Calculate the packet length and add a tailing 0 pktLen := len(scrambleBuff) + 1 @@ -344,7 +339,7 @@ func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error { // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse func (mc *mysqlConn) writeClearAuthPacket() error { // Calculate the packet length and add a tailing 0 - pktLen := len(mc.cfg.Passwd) + 1 + pktLen := len(mc.cfg.passwd) + 1 data := mc.buf.takeSmallBuffer(4 + pktLen) if data == nil { // can not take the buffer. Something must be wrong with the connection @@ -353,7 +348,7 @@ func (mc *mysqlConn) writeClearAuthPacket() error { } // Add the clear password [null terminated string] - copy(data[4:], mc.cfg.Passwd) + copy(data[4:], mc.cfg.passwd) data[4+pktLen-1] = 0x00 return mc.writePacket(data) @@ -538,13 +533,13 @@ func (mc *mysqlConn) handleOkPacket(data []byte) error { // warning count [2 bytes] if !mc.strict { return nil + } else { + pos := 1 + n + m + 2 + if binary.LittleEndian.Uint16(data[pos:pos+2]) > 0 { + return mc.getWarnings() + } + return nil } - - pos := 1 + n + m + 2 - if binary.LittleEndian.Uint16(data[pos:pos+2]) > 0 { - return mc.getWarnings() - } - return nil } // Read Packets as Field Packets until EOF-Packet or an Error appears @@ -563,7 +558,7 @@ func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) { if i == count { return columns, nil } - return nil, fmt.Errorf("column count mismatch n:%d len:%d", count, len(columns)) + return nil, fmt.Errorf("ColumnsCount mismatch n:%d len:%d", count, len(columns)) } // Catalog @@ -580,7 +575,7 @@ func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) { pos += n // Table [len coded string] - if mc.cfg.ColumnsWithAlias { + if mc.cfg.columnsWithAlias { tableName, _, n, err := readLengthEncodedString(data[pos:]) if err != nil { return nil, err @@ -679,7 +674,7 @@ func (rows *textRows) readRow(dest []driver.Value) error { fieldTypeDate, fieldTypeNewDate: dest[i], err = parseDateTime( string(dest[i].([]byte)), - mc.cfg.Loc, + mc.cfg.loc, ) if err == nil { continue @@ -741,13 +736,13 @@ func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) { // Warning count [16 bit uint] if !stmt.mc.strict { return columnCount, nil + } else { + // Check for warnings count > 0, only available in MySQL > 4.1 + if len(data) >= 12 && binary.LittleEndian.Uint16(data[10:12]) > 0 { + return columnCount, stmt.mc.getWarnings() + } + return columnCount, nil } - - // Check for warnings count > 0, only available in MySQL > 4.1 - if len(data) >= 12 && binary.LittleEndian.Uint16(data[10:12]) > 0 { - return columnCount, stmt.mc.getWarnings() - } - return columnCount, nil } return 0, err } @@ -809,7 +804,7 @@ func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error { func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { if len(args) != stmt.paramCount { return fmt.Errorf( - "argument count mismatch (got: %d; has: %d)", + "Arguments count mismatch (Got: %d Has: %d)", len(args), stmt.paramCount, ) @@ -986,7 +981,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { if v.IsZero() { val = []byte("0000-00-00") } else { - val = []byte(v.In(mc.cfg.Loc).Format(timeFormat)) + val = []byte(v.In(mc.cfg.loc).Format(timeFormat)) } paramValues = appendLengthEncodedInteger(paramValues, @@ -995,7 +990,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { paramValues = append(paramValues, val...) default: - return fmt.Errorf("can not convert type: %T", arg) + return fmt.Errorf("Can't convert type: %T", arg) } } @@ -1106,7 +1101,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar, fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB, fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB, - fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON: + fieldTypeVarString, fieldTypeString, fieldTypeGeometry: var isNull bool var n int dest[i], isNull, n, err = readLengthEncodedString(data[pos:]) @@ -1143,13 +1138,13 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { dstlen = 8 + 1 + decimals default: return fmt.Errorf( - "protocol error, illegal decimals value %d", + "MySQL protocol error, illegal decimals value %d", rows.columns[i].decimals, ) } dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true) case rows.mc.parseTime: - dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc) + dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.loc) default: var dstlen uint8 if rows.columns[i].fieldType == fieldTypeDate { @@ -1162,7 +1157,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { dstlen = 19 + 1 + decimals default: return fmt.Errorf( - "protocol error, illegal decimals value %d", + "MySQL protocol error, illegal decimals value %d", rows.columns[i].decimals, ) } @@ -1179,7 +1174,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { // Please report if this happens! default: - return fmt.Errorf("unknown field type %d", rows.columns[i].fieldType) + return fmt.Errorf("Unknown FieldType %d", rows.columns[i].fieldType) } } diff --git a/vendor/github.com/go-sql-driver/mysql/rows.go b/vendor/github.com/go-sql-driver/mysql/rows.go index 5d21948a..ba606e14 100644 --- a/vendor/github.com/go-sql-driver/mysql/rows.go +++ b/vendor/github.com/go-sql-driver/mysql/rows.go @@ -38,7 +38,7 @@ type emptyRows struct{} func (rows *mysqlRows) Columns() []string { columns := make([]string, len(rows.columns)) - if rows.mc.cfg.ColumnsWithAlias { + if rows.mc.cfg.columnsWithAlias { for i := range columns { if tableName := rows.columns[i].tableName; len(tableName) > 0 { columns[i] = tableName + "." + rows.columns[i].name diff --git a/vendor/github.com/go-sql-driver/mysql/utils.go b/vendor/github.com/go-sql-driver/mysql/utils.go index d523b7ff..6a26ad12 100644 --- a/vendor/github.com/go-sql-driver/mysql/utils.go +++ b/vendor/github.com/go-sql-driver/mysql/utils.go @@ -13,16 +13,28 @@ import ( "crypto/tls" "database/sql/driver" "encoding/binary" + "errors" "fmt" "io" + "net" + "net/url" "strings" "time" ) var ( tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs + + errInvalidDSNUnescaped = errors.New("Invalid DSN: Did you forget to escape a param value?") + errInvalidDSNAddr = errors.New("Invalid DSN: Network Address not terminated (missing closing brace)") + errInvalidDSNNoSlash = errors.New("Invalid DSN: Missing the slash separating the database name") + errInvalidDSNUnsafeCollation = errors.New("Invalid DSN: interpolateParams can be used with ascii, latin1, utf8 and utf8mb4 charset") ) +func init() { + tlsConfigRegister = make(map[string]*tls.Config) +} + // RegisterTLSConfig registers a custom tls.Config to be used with sql.Open. // Use the key as a value in the DSN where tls=value. // @@ -48,11 +60,7 @@ var ( // func RegisterTLSConfig(key string, config *tls.Config) error { if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" { - return fmt.Errorf("key '%s' is reserved", key) - } - - if tlsConfigRegister == nil { - tlsConfigRegister = make(map[string]*tls.Config) + return fmt.Errorf("Key '%s' is reserved", key) } tlsConfigRegister[key] = config @@ -61,9 +69,234 @@ func RegisterTLSConfig(key string, config *tls.Config) error { // DeregisterTLSConfig removes the tls.Config associated with key. func DeregisterTLSConfig(key string) { - if tlsConfigRegister != nil { - delete(tlsConfigRegister, key) + delete(tlsConfigRegister, key) +} + +// parseDSN parses the DSN string to a config +func parseDSN(dsn string) (cfg *config, err error) { + // New config with some default values + cfg = &config{ + loc: time.UTC, + collation: defaultCollation, } + + // [user[:password]@][net[(addr)]]/dbname[?param1=value1¶mN=valueN] + // Find the last '/' (since the password or the net addr might contain a '/') + foundSlash := false + for i := len(dsn) - 1; i >= 0; i-- { + if dsn[i] == '/' { + foundSlash = true + var j, k int + + // left part is empty if i <= 0 + if i > 0 { + // [username[:password]@][protocol[(address)]] + // Find the last '@' in dsn[:i] + for j = i; j >= 0; j-- { + if dsn[j] == '@' { + // username[:password] + // Find the first ':' in dsn[:j] + for k = 0; k < j; k++ { + if dsn[k] == ':' { + cfg.passwd = dsn[k+1 : j] + break + } + } + cfg.user = dsn[:k] + + break + } + } + + // [protocol[(address)]] + // Find the first '(' in dsn[j+1:i] + for k = j + 1; k < i; k++ { + if dsn[k] == '(' { + // dsn[i-1] must be == ')' if an address is specified + if dsn[i-1] != ')' { + if strings.ContainsRune(dsn[k+1:i], ')') { + return nil, errInvalidDSNUnescaped + } + return nil, errInvalidDSNAddr + } + cfg.addr = dsn[k+1 : i-1] + break + } + } + cfg.net = dsn[j+1 : k] + } + + // dbname[?param1=value1&...¶mN=valueN] + // Find the first '?' in dsn[i+1:] + for j = i + 1; j < len(dsn); j++ { + if dsn[j] == '?' { + if err = parseDSNParams(cfg, dsn[j+1:]); err != nil { + return + } + break + } + } + cfg.dbname = dsn[i+1 : j] + + break + } + } + + if !foundSlash && len(dsn) > 0 { + return nil, errInvalidDSNNoSlash + } + + if cfg.interpolateParams && unsafeCollations[cfg.collation] { + return nil, errInvalidDSNUnsafeCollation + } + + // Set default network if empty + if cfg.net == "" { + cfg.net = "tcp" + } + + // Set default address if empty + if cfg.addr == "" { + switch cfg.net { + case "tcp": + cfg.addr = "127.0.0.1:3306" + case "unix": + cfg.addr = "/tmp/mysql.sock" + default: + return nil, errors.New("Default addr for network '" + cfg.net + "' unknown") + } + + } + + return +} + +// parseDSNParams parses the DSN "query string" +// Values must be url.QueryEscape'ed +func parseDSNParams(cfg *config, params string) (err error) { + for _, v := range strings.Split(params, "&") { + param := strings.SplitN(v, "=", 2) + if len(param) != 2 { + continue + } + + // cfg params + switch value := param[1]; param[0] { + + // Enable client side placeholder substitution + case "interpolateParams": + var isBool bool + cfg.interpolateParams, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Disable INFILE whitelist / enable all files + case "allowAllFiles": + var isBool bool + cfg.allowAllFiles, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Use cleartext authentication mode (MySQL 5.5.10+) + case "allowCleartextPasswords": + var isBool bool + cfg.allowCleartextPasswords, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Use old authentication mode (pre MySQL 4.1) + case "allowOldPasswords": + var isBool bool + cfg.allowOldPasswords, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Switch "rowsAffected" mode + case "clientFoundRows": + var isBool bool + cfg.clientFoundRows, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Collation + case "collation": + collation, ok := collations[value] + if !ok { + // Note possibility for false negatives: + // could be triggered although the collation is valid if the + // collations map does not contain entries the server supports. + err = errors.New("unknown collation") + return + } + cfg.collation = collation + break + + case "columnsWithAlias": + var isBool bool + cfg.columnsWithAlias, isBool = readBool(value) + if !isBool { + return fmt.Errorf("Invalid Bool value: %s", value) + } + + // Time Location + case "loc": + if value, err = url.QueryUnescape(value); err != nil { + return + } + cfg.loc, err = time.LoadLocation(value) + if err != nil { + return + } + + // Dial Timeout + case "timeout": + cfg.timeout, err = time.ParseDuration(value) + if err != nil { + return + } + + // TLS-Encryption + case "tls": + boolValue, isBool := readBool(value) + if isBool { + if boolValue { + cfg.tls = &tls.Config{} + } + } else { + if strings.ToLower(value) == "skip-verify" { + cfg.tls = &tls.Config{InsecureSkipVerify: true} + } else if tlsConfig, ok := tlsConfigRegister[value]; ok { + if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { + host, _, err := net.SplitHostPort(cfg.addr) + if err == nil { + tlsConfig.ServerName = host + } + } + + cfg.tls = tlsConfig + } else { + return fmt.Errorf("Invalid value / unknown config name: %s", value) + } + } + + default: + // lazy init + if cfg.params == nil { + cfg.params = make(map[string]string) + } + + if cfg.params[param[0]], err = url.QueryUnescape(value); err != nil { + return + } + } + } + + return } // Returns the bool value of the input. @@ -260,7 +493,7 @@ func parseDateTime(str string, loc *time.Location) (t time.Time, err error) { } t, err = time.Parse(timeFormat[:len(str)], str) default: - err = fmt.Errorf("invalid time string: %s", str) + err = fmt.Errorf("Invalid Time-String: %s", str) return } @@ -309,7 +542,7 @@ func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Va loc, ), nil } - return nil, fmt.Errorf("invalid DATETIME packet length %d", num) + return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num) } // zeroDateTime is used in formatBinaryDateTime to avoid an allocation @@ -344,7 +577,7 @@ func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value switch len(src) { case 8, 12: default: - return nil, fmt.Errorf("invalid TIME packet length %d", len(src)) + return nil, fmt.Errorf("Invalid TIME-packet length %d", len(src)) } // +2 to enable negative time and 100+ hours dst = make([]byte, 0, length+2) @@ -378,7 +611,7 @@ func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value if length > 10 { t += "TIME" } - return nil, fmt.Errorf("illegal %s packet length %d", t, len(src)) + return nil, fmt.Errorf("illegal %s-packet length %d", t, len(src)) } dst = make([]byte, 0, length) // start with the date @@ -644,7 +877,7 @@ func escapeBytesBackslash(buf, v []byte) []byte { pos += 2 default: buf[pos] = c - pos++ + pos += 1 } } @@ -689,7 +922,7 @@ func escapeStringBackslash(buf []byte, v string) []byte { pos += 2 default: buf[pos] = c - pos++ + pos += 1 } } diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go index 0de8f8df..42a58c6f 100644 --- a/vendor/github.com/golang/protobuf/proto/lib.go +++ b/vendor/github.com/golang/protobuf/proto/lib.go @@ -235,7 +235,6 @@ To create and play with a Test object: test := &pb.Test{ Label: proto.String("hello"), Type: proto.Int32(17), - Reps: []int64{1, 2, 3}, Optionalgroup: &pb.Test_OptionalGroup{ RequiredField: proto.String("good bye"), }, diff --git a/vendor/github.com/julienschmidt/httprouter/README.md b/vendor/github.com/julienschmidt/httprouter/README.md index 7b467f56..a24ae1d8 100644 --- a/vendor/github.com/julienschmidt/httprouter/README.md +++ b/vendor/github.com/julienschmidt/httprouter/README.md @@ -1,6 +1,6 @@ -# HttpRouter [![Build Status](https://travis-ci.org/julienschmidt/httprouter.svg?branch=master)](https://travis-ci.org/julienschmidt/httprouter) [![Coverage](http://gocover.io/_badge/github.com/julienschmidt/httprouter?0)](http://gocover.io/github.com/julienschmidt/httprouter) [![GoDoc](https://godoc.org/github.com/julienschmidt/httprouter?status.svg)](http://godoc.org/github.com/julienschmidt/httprouter) +# HttpRouter [![Build Status](https://travis-ci.org/julienschmidt/httprouter.svg?branch=master)](https://travis-ci.org/julienschmidt/httprouter) [![Coverage](http://gocover.io/_badge/github.com/julienschmidt/httprouter?0)](http://gocover.io/github.com/julienschmidt/httprouter) [![GoDoc](http://godoc.org/github.com/julienschmidt/httprouter?status.svg)](http://godoc.org/github.com/julienschmidt/httprouter) -HttpRouter is a lightweight high performance HTTP request router (also called *multiplexer* or just *mux* for short) for [Go](https://golang.org/). +HttpRouter is a lightweight high performance HTTP request router (also called *multiplexer* or just *mux* for short) for [Go](http://golang.org/). In contrast to the [default mux][http.ServeMux] of Go's `net/http` package, this router supports variables in the routing pattern and matches against the request method. It also scales better. @@ -10,7 +10,7 @@ The router is optimized for high performance and a small memory footprint. It sc **Only explicit matches:** With other routers, like [`http.ServeMux`][http.ServeMux], a requested URL path could match multiple patterns. Therefore they have some awkward pattern priority rules, like *longest match* or *first registered, first matched*. By design of this router, a request can only match exactly one or no route. As a result, there are also no unintended matches, which makes it great for SEO and improves the user experience. -**Stop caring about trailing slashes:** Choose the URL style you like, the router automatically redirects the client if a trailing slash is missing or if there is one extra. Of course it only does so, if the new path has a handler. If you don't like it, you can [turn off this behavior](https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash). +**Stop caring about trailing slashes:** Choose the URL style you like, the router automatically redirects the client if a trailing slash is missing or if there is one extra. Of course it only does so, if the new path has a handler. If you don't like it, you can [turn off this behavior](http://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash). **Path auto-correction:** Besides detecting the missing or additional trailing slash at no extra cost, the router can also fix wrong cases and remove superfluous path elements (like `../` or `//`). Is [CAPTAIN CAPS LOCK](http://www.urbandictionary.com/define.php?term=Captain+Caps+Lock) one of your users? HttpRouter can help him by making a case-insensitive look-up and redirecting him to the correct URL. @@ -22,7 +22,7 @@ The router is optimized for high performance and a small memory footprint. It sc **No more server crashes:** You can set a [Panic handler][Router.PanicHandler] to deal with panics occurring during handling a HTTP request. The router then recovers and lets the `PanicHandler` log what happened and deliver a nice error page. -Of course you can also set **custom [`NotFound`][Router.NotFound] and [`MethodNotAllowed`](https://godoc.org/github.com/julienschmidt/httprouter#Router.MethodNotAllowed) handlers** and [**serve static files**][Router.ServeFiles]. +Of course you can also set **custom [`NotFound`][Router.NotFound] and [`MethodNotAllowed`](http://godoc.org/github.com/julienschmidt/httprouter#Router.MethodNotAllowed) handlers** and [**serve static files**][Router.ServeFiles]. ## Usage @@ -88,7 +88,7 @@ Pattern: /src/*filepath ## How does it work? -The router relies on a tree structure which makes heavy use of *common prefixes*, it is basically a *compact* [*prefix tree*](https://en.wikipedia.org/wiki/Trie) (or just [*Radix tree*](https://en.wikipedia.org/wiki/Radix_tree)). Nodes with a common prefix also share a common parent. Here is a short example what the routing tree for the `GET` request method could look like: +The router relies on a tree structure which makes heavy use of *common prefixes*, it is basically a *compact* [*prefix tree*](http://en.wikipedia.org/wiki/Trie) (or just [*Radix tree*](http://en.wikipedia.org/wiki/Radix_tree)). Nodes with a common prefix also share a common parent. Here is a short example what the routing tree for the `GET` request method could look like: ``` Priority Path Handle @@ -131,7 +131,7 @@ Just try it out for yourself, the usage of HttpRouter is very straightforward. T ## Where can I find Middleware *X*? -This package just provides a very efficient request router with a few extra features. The router is just a [`http.Handler`][http.Handler], you can chain any http.Handler compatible middleware before the router, for example the [Gorilla handlers](http://www.gorillatoolkit.org/pkg/handlers). Or you could [just write your own](https://justinas.org/writing-http-middleware-in-go/), it's very easy! +This package just provides a very efficient request router with a few extra features. The router is just a [`http.Handler`][http.Handler], you can chain any http.Handler compatible middleware before the router, for example the [Gorilla handlers](http://www.gorillatoolkit.org/pkg/handlers). Or you could [just write your own](http://justinas.org/writing-http-middleware-in-go/), it's very easy! Alternatively, you could try [a web framework based on HttpRouter](#web-frameworks-based-on-httprouter). @@ -262,12 +262,12 @@ But this approach sidesteps the strict core rules of this router to avoid routin If the HttpRouter is a bit too minimalistic for you, you might try one of the following more high-level 3rd-party web frameworks building upon the HttpRouter package: * [Ace](https://github.com/plimble/ace): Blazing fast Go Web Framework -* [api2go](https://github.com/manyminds/api2go): A JSON API Implementation for Go +* [api2go](https://github.com/univedo/api2go): A JSON API Implementation for Go * [Gin](https://github.com/gin-gonic/gin): Features a martini-like API with much better performance * [Goat](https://github.com/bahlo/goat): A minimalistic REST API server in Go * [Hikaru](https://github.com/najeira/hikaru): Supports standalone and Google AppEngine * [Hitch](https://github.com/nbio/hitch): Hitch ties httprouter, [httpcontext](https://github.com/nbio/httpcontext), and middleware up in a bow -* [httpway](https://github.com/corneldamian/httpway): Simple middleware extension with context for httprouter and a server with gracefully shutdown support +* [httpway](http://github.com/corneldamian/httpway): Simple middleware extension with context for httprouter and a server with gracefully shutdown support * [kami](https://github.com/guregu/kami): A tiny web framework using x/net/context * [Medeina](https://github.com/imdario/medeina): Inspired by Ruby's Roda and Cuba * [Neko](https://github.com/rocwong/neko): A lightweight web application framework for Golang @@ -275,12 +275,12 @@ If the HttpRouter is a bit too minimalistic for you, you might try one of the fo * [siesta](https://github.com/VividCortex/siesta): Composable HTTP handlers with contexts [benchmark]: -[http.Handler]: -[Router.Handle]: -[Router.HandleMethodNotAllowed]: -[Router.Handler]: -[Router.HandlerFunc]: -[Router.NotFound]: -[Router.PanicHandler]: -[Router.ServeFiles]: +[http.Handler]: +[Router.Handle]: +[Router.HandleMethodNotAllowed]: +[Router.Handler]: +[Router.HandlerFunc]: +[Router.NotFound]: +[Router.PanicHandler]: +[Router.ServeFiles]: diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml index c94a8718..6b8eb405 100644 --- a/vendor/github.com/lib/pq/.travis.yml +++ b/vendor/github.com/lib/pq/.travis.yml @@ -47,14 +47,12 @@ env: - PQSSLCERTTEST_PATH=$PWD/certs - PGHOST=127.0.0.1 matrix: - - PGVERSION=9.5 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=9.4 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=9.3 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=9.2 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=9.1 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=9.0 PQTEST_BINARY_PARAMETERS=yes - PGVERSION=8.4 PQTEST_BINARY_PARAMETERS=yes - - PGVERSION=9.5 PQTEST_BINARY_PARAMETERS=no - PGVERSION=9.4 PQTEST_BINARY_PARAMETERS=no - PGVERSION=9.3 PQTEST_BINARY_PARAMETERS=no - PGVERSION=9.2 PQTEST_BINARY_PARAMETERS=no diff --git a/vendor/github.com/lib/pq/README.md b/vendor/github.com/lib/pq/README.md index b4e3f45c..358d644f 100644 --- a/vendor/github.com/lib/pq/README.md +++ b/vendor/github.com/lib/pq/README.md @@ -38,7 +38,6 @@ Optionally, a benchmark suite can be run as part of the tests: * Many libpq compatible environment variables * Unix socket support * Notifications: `LISTEN`/`NOTIFY` -* pgpass support ## Future / Things you can help with @@ -68,7 +67,6 @@ code still exists in here. * Everyone at The Go Team * Evan Shaw (edsrzf) * Ewan Chou (coocood) -* Fazal Majid (fazalmajid) * Federico Romero (federomero) * Fumin (fumin) * Gary Burd (garyburd) diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index 394e659d..4af880fb 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -143,80 +143,6 @@ func (c *conn) handleDriverSettings(o values) (err error) { return nil } -func (c *conn) handlePgpass(o values) { - // if a password was supplied, do not process .pgpass - _, ok := o["password"] - if ok { - return - } - filename := os.Getenv("PGPASSFILE") - if filename == "" { - // XXX this code doesn't work on Windows where the default filename is - // XXX %APPDATA%\postgresql\pgpass.conf - user, err := user.Current() - if err != nil { - return - } - filename = filepath.Join(user.HomeDir, ".pgpass") - } - fileinfo, err := os.Stat(filename) - if err != nil { - return - } - mode := fileinfo.Mode() - if mode & (0x77) != 0 { - // XXX should warn about incorrect .pgpass permissions as psql does - return - } - file, err := os.Open(filename) - if err != nil { - return - } - defer file.Close() - scanner := bufio.NewScanner(io.Reader(file)) - hostname := o.Get("host") - ntw, _ := network(o) - port := o.Get("port") - db := o.Get("dbname") - username := o.Get("user") - // From: https://github.com/tg/pgpass/blob/master/reader.go - getFields := func (s string) []string { - fs := make([]string, 0, 5) - f := make([]rune, 0, len(s)) - - var esc bool - for _, c := range s { - switch { - case esc: - f = append(f, c) - esc = false - case c == '\\': - esc = true - case c == ':': - fs = append(fs, string(f)) - f = f[:0] - default: - f = append(f, c) - } - } - return append(fs, string(f)) - } - for scanner.Scan() { - line := scanner.Text() - if len(line) == 0 || line[0] == '#' { - continue - } - split := getFields(line) - if len(split) != 5 { - continue - } - if (split[0] == "*" || split[0] == hostname || (split[0] == "localhost" && (hostname == "" || ntw == "unix"))) && (split[1] == "*" || split[1] == port) && (split[2] == "*" || split[2] == db) && (split[3] == "*" || split[3] == username) { - o["password"] = split[4] - return - } - } -} - func (c *conn) writeBuf(b byte) *writeBuf { c.scratch[0] = b return &writeBuf{ @@ -308,7 +234,6 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if err != nil { return nil, err } - cn.handlePgpass(o) cn.c, err = dial(d, o) if err != nil { @@ -1796,7 +1721,7 @@ func parseEnviron(env []string) (out map[string]string) { accrue("user") case "PGPASSWORD": accrue("password") - case "PGSERVICE", "PGSERVICEFILE", "PGREALM": + case "PGPASSFILE", "PGSERVICE", "PGSERVICEFILE", "PGREALM": unsupported() case "PGOPTIONS": accrue("options") diff --git a/vendor/github.com/lib/pq/doc.go b/vendor/github.com/lib/pq/doc.go index 19798dfc..f772117d 100644 --- a/vendor/github.com/lib/pq/doc.go +++ b/vendor/github.com/lib/pq/doc.go @@ -86,8 +86,6 @@ variables not supported by pq are set, pq will panic during connection establishment. Environment variables have a lower precedence than explicitly provided connection parameters. -The pgpass mechanism as described in http://www.postgresql.org/docs/current/static/libpq-pgpass.html -is supported, but on Windows PGPASSFILE must be specified explicitly. Queries diff --git a/vendor/github.com/mattn/go-sqlite3/code/sqlite3-binding.c b/vendor/github.com/mattn/go-sqlite3/code/sqlite3-binding.c index c0ab2337..9228d249 100644 --- a/vendor/github.com/mattn/go-sqlite3/code/sqlite3-binding.c +++ b/vendor/github.com/mattn/go-sqlite3/code/sqlite3-binding.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.10.2. By combining all the individual C code files into this +** version 3.8.5. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -22,6 +22,9 @@ #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif +#ifndef SQLITE_API +# define SQLITE_API +#endif /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 @@ -40,92 +43,6 @@ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ -/* -** Include the header file used to customize the compiler options for MSVC. -** This should be done first so that it can successfully prevent spurious -** compiler warnings due to subsequent content in this file and other files -** that are included by this file. -*/ -/************** Include msvc.h in the middle of sqliteInt.h ******************/ -/************** Begin file msvc.h ********************************************/ -/* -** 2015 January 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code that is specific to MSVC. -*/ -#ifndef _MSVC_H_ -#define _MSVC_H_ - -#if defined(_MSC_VER) -#pragma warning(disable : 4054) -#pragma warning(disable : 4055) -#pragma warning(disable : 4100) -#pragma warning(disable : 4127) -#pragma warning(disable : 4130) -#pragma warning(disable : 4152) -#pragma warning(disable : 4189) -#pragma warning(disable : 4206) -#pragma warning(disable : 4210) -#pragma warning(disable : 4232) -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) -#pragma warning(disable : 4306) -#pragma warning(disable : 4702) -#pragma warning(disable : 4706) -#endif /* defined(_MSC_VER) */ - -#endif /* _MSVC_H_ */ - -/************** End of msvc.h ************************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* -** Special setup for VxWorks -*/ -/************** Include vxworks.h in the middle of sqliteInt.h ***************/ -/************** Begin file vxworks.h *****************************************/ -/* -** 2015-03-02 -** -** 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 code that is specific to Wind River's VxWorks -*/ -#if defined(__RTP__) || defined(_WRS_KERNEL) -/* This is VxWorks. Set up things specially for that OS -*/ -#include -#include /* amalgamator: dontcache */ -#define OS_VXWORKS 1 -#define SQLITE_OS_OTHER 0 -#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1 -#define SQLITE_OMIT_LOAD_EXTENSION 1 -#define SQLITE_ENABLE_LOCKING_STYLE 0 -#define HAVE_UTIME 1 -#else -/* This is not VxWorks. */ -#define OS_VXWORKS 0 -#endif /* defined(_WRS_KERNEL) */ - -/************** End of vxworks.h *********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks @@ -158,22 +75,6 @@ # define _LARGEFILE_SOURCE 1 #endif -/* What version of GCC is being used. 0 means GCC is not being used */ -#ifdef __GNUC__ -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif - -/* Needed for various definitions... */ -#if defined(__GNUC__) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE -#endif - -#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) -# define _BSD_SOURCE -#endif - /* ** For MinGW, check to see if we can include the header file containing its ** version information, among other things. Normally, this internal MinGW @@ -237,7 +138,7 @@ ** ** The official C-language API documentation for SQLite is derived ** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are supposed to operate. +** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting @@ -257,25 +158,21 @@ extern "C" { /* -** Provide the ability to override linkage features of the interface. +** Add the ability to override 'extern' */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif + #ifndef SQLITE_API # define SQLITE_API #endif -#ifndef SQLITE_CDECL -# define SQLITE_CDECL -#endif -#ifndef SQLITE_STDCALL -# define SQLITE_STDCALL -#endif + /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications -** should not use deprecated interfaces - they are supported for backwards +** should not use deprecated interfaces - they are support for backwards ** compatibility only. Application writers should be aware that ** experimental interfaces are subject to change in point releases. ** @@ -325,9 +222,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.10.2" -#define SQLITE_VERSION_NUMBER 3010002 -#define SQLITE_SOURCE_ID "2016-01-20 15:27:19 17efb4209f97fb4971656086b138599a91a75ff9" +#define SQLITE_VERSION "3.8.5" +#define SQLITE_VERSION_NUMBER 3008005 +#define SQLITE_SOURCE_ID "2014-06-04 14:06:34 b1ed4f2a34ba66c29b130f8d13e9092758019212" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -338,7 +235,7 @@ extern "C" { ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to ** verify that values returned by these interfaces match the macros in -** the header, and thus ensure that the application is +** the header, and thus insure that the application is ** compiled with matching library and header files. ** **
@@ -360,9 +257,9 @@ extern "C" {
 ** See also: [sqlite_version()] and [sqlite_source_id()].
 */
 SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
-SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void);
-SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void);
-SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void);
+SQLITE_API const char *sqlite3_libversion(void);
+SQLITE_API const char *sqlite3_sourceid(void);
+SQLITE_API int sqlite3_libversion_number(void);
 
 /*
 ** CAPI3REF: Run-Time Library Compilation Options Diagnostics
@@ -387,8 +284,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void);
 ** [sqlite_compileoption_get()] and the [compile_options pragma].
 */
 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName);
-SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N);
+SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
+SQLITE_API const char *sqlite3_compileoption_get(int N);
 #endif
 
 /*
@@ -419,7 +316,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N);
 ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
 ** can be fully or partially disabled using a call to [sqlite3_config()]
 ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
-** or [SQLITE_CONFIG_SERIALIZED].  ^(The return value of the
+** or [SQLITE_CONFIG_MUTEX].  ^(The return value of the
 ** sqlite3_threadsafe() function shows only the compile-time setting of
 ** thread safety, not any run-time changes to that setting made by
 ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
@@ -427,7 +324,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N);
 **
 ** See the [threading mode] documentation for additional information.
 */
-SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void);
+SQLITE_API int sqlite3_threadsafe(void);
 
 /*
 ** CAPI3REF: Database Connection Handle
@@ -484,11 +381,10 @@ typedef sqlite_uint64 sqlite3_uint64;
 
 /*
 ** CAPI3REF: Closing A Database Connection
-** DESTRUCTOR: sqlite3
 **
 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
 ** for the [sqlite3] object.
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
 ** the [sqlite3] object is successfully destroyed and all associated
 ** resources are deallocated.
 **
@@ -496,7 +392,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
 ** will leave the database connection open and return [SQLITE_BUSY].
 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
-** and/or unfinished sqlite3_backups, then the database connection becomes
+** and unfinished sqlite3_backups, then the database connection becomes
 ** an unusable "zombie" which will automatically be deallocated when the
 ** last prepared statement is finalized or the last sqlite3_backup is
 ** finished.  The sqlite3_close_v2() interface is intended for use with
@@ -509,7 +405,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
 ** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
+** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
 ** and [sqlite3_backup] objects are also destroyed.
 **
@@ -524,8 +420,8 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
 ** argument is a harmless no-op.
 */
-SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*);
-SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*);
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
 
 /*
 ** The type for a callback function.
@@ -536,7 +432,6 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 
 /*
 ** CAPI3REF: One-Step Query Execution Interface
-** METHOD: sqlite3
 **
 ** The sqlite3_exec() interface is a convenience wrapper around
 ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
@@ -588,7 +483,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** Restrictions:
 **
 ** 
    -**
  • The application must ensure that the 1st parameter to sqlite3_exec() +**
  • The application must insure that the 1st parameter to sqlite3_exec() ** is a valid and open [database connection]. **
  • The application must not close the [database connection] specified by ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. @@ -596,7 +491,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. **
*/ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3*, /* An open database */ const char *sql, /* SQL to be evaluated */ int (*callback)(void*,int,char**,char**), /* Callback function */ @@ -606,14 +501,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( /* ** CAPI3REF: Result Codes -** KEYWORDS: {result code definitions} +** KEYWORDS: SQLITE_OK {error code} {error codes} +** KEYWORDS: {result code} {result codes} ** ** Many SQLite functions return an integer result code from the set shown ** here in order to indicate success or failure. ** ** New error codes may be added in future versions of SQLite. ** -** See also: [extended result code definitions] +** See also: [SQLITE_IOERR_READ | extended result codes], +** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes]. */ #define SQLITE_OK 0 /* Successful result */ /* beginning-of-error-codes */ @@ -651,19 +548,26 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( /* ** CAPI3REF: Extended Result Codes -** KEYWORDS: {extended result code definitions} +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result code} {extended result codes} ** -** In its default configuration, SQLite API routines return one of 30 integer -** [result codes]. However, experience has shown that many of +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that many of ** these result codes are too coarse-grained. They do not provide as ** much information about problems as programmers might like. In an effort to ** address this, newer versions of SQLite (version 3.3.8 and later) include ** support for additional result codes that provide more detailed information -** about errors. These [extended result codes] are enabled or disabled +** about errors. The extended result codes are enabled or disabled ** on a per database connection basis using the -** [sqlite3_extended_result_codes()] API. Or, the extended code for -** the most recent error can be obtained using -** [sqlite3_extended_errcode()]. +** [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will increase +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. */ #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) @@ -691,8 +595,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) -#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) -#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) @@ -719,7 +621,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) -#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -899,7 +800,7 @@ struct sqlite3_file { ** locking strategy (for example to use dot-file locks), to inquire ** about the status of a lock, or to break stale locks. The SQLite ** core reserves all opcodes less than 100 for its own use. -** A [file control opcodes | list of opcodes] less than 100 is available. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. ** Applications that define a custom xFileControl method should use opcodes ** greater than 100 to avoid conflicts. VFS implementations should ** return [SQLITE_NOTFOUND] for file control opcodes that they do not @@ -972,22 +873,19 @@ struct sqlite3_io_methods { /* ** CAPI3REF: Standard File Control Opcodes -** KEYWORDS: {file control opcodes} {file control opcode} ** ** These integer constants are opcodes for the xFileControl method ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** interface. ** -**
    -**
  • [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) ** into an integer that the pArg argument points to. This capability -** is used during testing and is only available when the SQLITE_TEST -** compile-time option is used. -** +** is used during testing and only needs to be supported when SQLITE_TEST +** is defined. +**
      **
    • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the @@ -1008,13 +906,8 @@ struct sqlite3_io_methods { **
    • [[SQLITE_FCNTL_FILE_POINTER]] ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer ** to the [sqlite3_file] object associated with a particular database -** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER]. -** -**
    • [[SQLITE_FCNTL_JOURNAL_POINTER]] -** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer -** to the [sqlite3_file] object associated with the journal file (either -** the [rollback journal] or the [write-ahead log]) for a particular database -** connection. See also [SQLITE_FCNTL_FILE_POINTER]. +** connection. See the [sqlite3_file_control()] documentation for +** additional information. ** **
    • [[SQLITE_FCNTL_SYNC_OMITTED]] ** No longer in use. @@ -1101,15 +994,6 @@ struct sqlite3_io_methods { ** pointer in case this file-control is not implemented. This file-control ** is intended for diagnostic use only. ** -**
    • [[SQLITE_FCNTL_VFS_POINTER]] -** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level -** [VFSes] currently in use. ^(The argument X in -** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be -** of type "[sqlite3_vfs] **". This opcodes will set *X -** to a pointer to the top-level VFS.)^ -** ^When there are multiple VFS shims in the stack, this opcode finds the -** upper-most shim only. -** **
    • [[SQLITE_FCNTL_PRAGMA]] ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] ** file control is sent to the open [sqlite3_file] object corresponding @@ -1126,9 +1010,7 @@ struct sqlite3_io_methods { ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement if result string is NULL, or that returns a copy -** of the result string if the string is non-NULL. -** ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] @@ -1186,27 +1068,12 @@ 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_WAL_BLOCK]] -** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might -** be advantageous to block on the next WAL lock if the lock is not immediately -** available. The WAL subsystem issues this signal during rare -** circumstances in order to fix a problem with priority inversion. -** Applications should not use this file-control. -** -**
    • [[SQLITE_FCNTL_ZIPVFS]] -** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other -** VFS should return SQLITE_NOTFOUND for this opcode. -** -**
    • [[SQLITE_FCNTL_RBU]] -** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by -** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for -** this opcode. **
    */ #define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 -#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 -#define SQLITE_FCNTL_LAST_ERRNO 4 +#define SQLITE_GET_LOCKPROXYFILE 2 +#define SQLITE_SET_LOCKPROXYFILE 3 +#define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 @@ -1225,17 +1092,6 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 -#define SQLITE_FCNTL_WAL_BLOCK 24 -#define SQLITE_FCNTL_ZIPVFS 25 -#define SQLITE_FCNTL_RBU 26 -#define SQLITE_FCNTL_VFS_POINTER 27 -#define SQLITE_FCNTL_JOURNAL_POINTER 28 - -/* deprecated names */ -#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE -#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE -#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO - /* ** CAPI3REF: Mutex Handle @@ -1487,7 +1343,7 @@ struct sqlite3_vfs { **
** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given on the corresponding lock. +** was given no the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED @@ -1584,10 +1440,10 @@ struct sqlite3_vfs { ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void); -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void); -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library @@ -1598,11 +1454,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** -** The sqlite3_config() interface is not threadsafe. The application -** must ensure that no other SQLite interfaces are invoked by other -** threads while sqlite3_config() is running. -** -** The sqlite3_config() interface +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() ** 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 @@ -1620,11 +1474,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void); ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); +SQLITE_API int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections -** METHOD: sqlite3 ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to @@ -1639,7 +1492,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...); ** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if ** the call is considered successful. */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); /* ** CAPI3REF: Memory Allocation Routines @@ -1773,33 +1626,31 @@ struct sqlite3_mem_methods { ** SQLITE_CONFIG_SERIALIZED configuration option. ** ** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
-**
^(The SQLITE_CONFIG_MALLOC option takes a single argument which is -** a pointer to an instance of the [sqlite3_mem_methods] structure. -** The argument specifies +**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The argument specifies ** alternative low-level memory allocation routines to be used in place of ** the memory allocation routines built into SQLite.)^ ^SQLite makes ** its own private copy of the content of the [sqlite3_mem_methods] structure ** before the [sqlite3_config()] call returns.
** ** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
-**
^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which -** is a pointer to an instance of the [sqlite3_mem_methods] structure. -** The [sqlite3_mem_methods] +**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example.
** ** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
-**
^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, -** interpreted as a boolean, which enables or disables the collection of -** memory allocation statistics. ^(When memory allocation statistics are -** disabled, the following SQLite interfaces become non-operational: +**
^This option takes single argument of type int, interpreted as a +** boolean, which enables or disables the collection of memory allocation +** statistics. ^(When memory allocation statistics are disabled, the +** following SQLite interfaces become non-operational: **
    **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] **
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status64()] +**
  • [sqlite3_status()] **
)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory @@ -1807,72 +1658,53 @@ struct sqlite3_mem_methods { **
** ** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
-**
^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer -** that SQLite can use for scratch memory. ^(There are three arguments -** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte +**
^This option specifies a static memory buffer that SQLite can use for +** scratch memory. There are three arguments: A pointer an 8-byte ** aligned memory buffer from which the scratch allocations will be ** drawn, the size of each scratch allocation (sz), -** and the maximum number of scratch allocations (N).)^ +** and the maximum number of scratch allocations (N). The sz +** argument must be a multiple of 16. ** The first argument must be a pointer to an 8-byte aligned buffer ** of at least sz*N bytes of memory. -** ^SQLite will not use more than one scratch buffers per thread. -** ^SQLite will never request a scratch buffer that is more than 6 -** times the database page size. -** ^If SQLite needs needs additional +** ^SQLite will use no more than two scratch buffers per thread. So +** N should be set to twice the expected maximum number of threads. +** ^SQLite will never require a scratch buffer that is more than 6 +** times the database page size. ^If SQLite needs needs additional ** scratch memory beyond what is provided by this configuration option, then -** [sqlite3_malloc()] will be used to obtain the memory needed.

-** ^When the application provides any amount of scratch memory using -** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large -** [sqlite3_malloc|heap allocations]. -** This can help [Robson proof|prevent memory allocation failures] due to heap -** fragmentation in low-memory embedded systems. -**

+** [sqlite3_malloc()] will be used to obtain the memory needed. ** ** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
-**
^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool -** that SQLite can use for the database page cache with the default page -** cache implementation. -** This configuration option is a no-op if an application-define page -** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. -** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to -** 8-byte aligned memory (pMem), the size of each page cache line (sz), -** and the number of cache lines (N). +**
^This option specifies a static memory buffer that SQLite can use for +** the database page cache with the default page cache implementation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option. +** There are three arguments to this option: A pointer to 8-byte aligned +** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page -** (a power of two between 512 and 65536) plus some extra bytes for each -** page header. ^The number of extra bytes needed by the page header -** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ]. -** ^It is harmless, apart from the wasted memory, -** for the sz parameter to be larger than necessary. The pMem -** argument must be either a NULL pointer or a pointer to an 8-byte -** aligned block of memory of at least sz*N bytes, otherwise -** subsequent behavior is undefined. -** ^When pMem is not NULL, SQLite will strive to use the memory provided -** to satisfy page cache needs, falling back to [sqlite3_malloc()] if -** a page cache line is larger than sz bytes or if all of the pMem buffer -** is exhausted. -** ^If pMem is NULL and N is non-zero, then each database connection -** does an initial bulk allocation for page cache memory -** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or -** of -1024*N bytes if N is negative, . ^If additional -** page cache memory is needed beyond what is provided by the initial -** allocation, then SQLite goes to [sqlite3_malloc()] separately for each -** additional cache line.
+** (a power of two between 512 and 32768) plus a little extra for each +** page header. ^The page header size is 20 to 40 bytes depending on +** the host architecture. ^It is harmless, apart from the wasted memory, +** to make sz a little too large. The first +** argument should point to an allocation of at least sz*N bytes of memory. +** ^SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. ^If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space. +** The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined. ** ** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
-**
^The SQLITE_CONFIG_HEAP option specifies a static memory buffer -** that SQLite will use for all of its dynamic memory allocation needs -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and -** [SQLITE_CONFIG_PAGECACHE]. -** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled -** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns -** [SQLITE_ERROR] if invoked otherwise. -** ^There are three arguments to SQLITE_CONFIG_HEAP: -** An 8-byte aligned pointer to the memory, +**
^This option specifies a static memory buffer that SQLite will use +** for all of its dynamic memory allocation needs beyond those provided +** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** There are three arguments: An 8-byte aligned pointer to the memory, ** the number of bytes in the memory buffer, and the minimum allocation size. ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the -** memory pointer is not NULL then the alternative memory +** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or +** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory ** allocator is engaged to handle all of SQLites memory allocation needs. ** The first pointer (the memory pointer) must be aligned to an 8-byte ** boundary or subsequent behavior of SQLite will be undefined. @@ -1880,11 +1712,11 @@ struct sqlite3_mem_methods { ** for the minimum allocation size are 2**5 through 2**8.
** ** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
-**
^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a -** pointer to an instance of the [sqlite3_mutex_methods] structure. -** The argument specifies alternative low-level mutex routines to be used -** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of -** the content of the [sqlite3_mutex_methods] structure before the call to +**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The argument specifies +** alternative low-level mutex routines to be used in place +** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the +** content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to @@ -1892,8 +1724,8 @@ struct sqlite3_mem_methods { ** return [SQLITE_ERROR].
** ** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
-**
^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which -** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The +**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The ** [sqlite3_mutex_methods] ** structure is filled with the currently defined mutex routines.)^ ** This option can be used to overload the default mutex allocation @@ -1905,25 +1737,25 @@ struct sqlite3_mem_methods { ** return [SQLITE_ERROR].
** ** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
-**
^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine -** the default size of lookaside memory on each [database connection]. -** The first argument is the +**
^(This option takes two arguments that determine the default +** memory allocation for the lookaside memory allocator on each +** [database connection]. The first argument is the ** size of each lookaside buffer slot and the second is the number of -** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE -** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] -** option to [sqlite3_db_config()] can be used to change the lookaside +** slots allocated to each database connection.)^ ^(This option sets the +** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside ** configuration on individual connections.)^
** ** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
-**
^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is -** a pointer to an [sqlite3_pcache_methods2] object. This object specifies -** the interface to a custom page cache implementation.)^ -** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
+**
^(This option takes a single argument which is a pointer to +** an [sqlite3_pcache_methods2] object. This object specifies the interface +** to a custom page cache implementation.)^ ^SQLite makes a copy of the +** object and uses it for page cache memory allocations.
** ** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
-**
^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of -** the current page cache implementation into that object.)^
+**
^(This option takes a single argument which is a pointer to an +** [sqlite3_pcache_methods2] object. SQLite copies of the current +** page cache implementation into that object.)^
** ** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
**
The SQLITE_CONFIG_LOG option is used to configure the SQLite @@ -1946,11 +1778,10 @@ struct sqlite3_mem_methods { ** function must be threadsafe.
** ** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI -**
^(The SQLITE_CONFIG_URI option takes a single argument of type int. -** If non-zero, then URI handling is globally enabled. If the parameter is zero, -** then URI handling is globally disabled.)^ ^If URI handling is globally -** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], -** [sqlite3_open16()] or +**
^(This option takes a single argument of type int. If non-zero, then +** URI handling is globally enabled. If the parameter is zero, then URI handling +** is globally disabled.)^ ^If URI handling is globally enabled, all filenames +** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are @@ -1960,10 +1791,9 @@ struct sqlite3_mem_methods { ** [SQLITE_USE_URI] symbol defined.)^ ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN -**
^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer -** argument which is interpreted as a boolean in order to enable or disable -** the use of covering indices for full table scans in the query optimizer. -** ^The default setting is determined +**
^This option takes a single integer argument which is interpreted as +** a boolean in order to enable or disable the use of covering indices for +** full table scans in the query optimizer. ^The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans @@ -2003,37 +1833,18 @@ struct sqlite3_mem_methods { ** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size -** will be silently truncated if necessary so that it does not exceed the -** compile-time maximum mmap size set by the +** cannot be changed at run-time. Nor may the maximum allowed mmap size +** exceed the compile-time maximum mmap size set by the ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] **
SQLITE_CONFIG_WIN32_HEAPSIZE -**
^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is -** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro -** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value +**
^This option is only available if SQLite is compiled for Windows +** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. +** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. -** -** [[SQLITE_CONFIG_PCACHE_HDRSZ]] -**
SQLITE_CONFIG_PCACHE_HDRSZ -**
^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which -** is a pointer to an integer and writes into that integer the number of extra -** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. -** The amount of extra space required can change depending on the compiler, -** target platform, and SQLite version. -** -** [[SQLITE_CONFIG_PMASZ]] -**
SQLITE_CONFIG_PMASZ -**
^The SQLITE_CONFIG_PMASZ option takes a single parameter which -** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded -** sorter to that integer. The default minimum PMA Size is set by the -** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched -** to help with sort operations when multithreaded sorting -** is enabled (using the [PRAGMA threads] command) and the amount of content -** to be sorted exceeds the page size times the minimum of the -** [PRAGMA cache_size] setting and this value. ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2059,8 +1870,6 @@ struct sqlite3_mem_methods { #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 */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2127,17 +1936,15 @@ struct sqlite3_mem_methods { /* ** CAPI3REF: Enable Or Disable Extended Result Codes -** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff); +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid -** METHOD: sqlite3 ** ** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) ** has a unique 64-bit signed @@ -2185,51 +1992,52 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff) ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified -** METHOD: sqlite3 ** -** ^This function returns the number of rows modified, inserted or -** deleted by the most recently completed INSERT, UPDATE or DELETE -** statement on the database connection specified by the only parameter. -** ^Executing any other type of SQL statement does not modify the value -** returned by this function. +** ^This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the [database connection] specified by the first parameter. +** ^(Only changes that are directly specified by the [INSERT], [UPDATE], +** or [DELETE] statement are counted. Auxiliary changes caused by +** triggers or [foreign key actions] are not counted.)^ Use the +** [sqlite3_total_changes()] function to find the total number of changes +** including changes caused by triggers and foreign key actions. ** -** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are -** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], -** [foreign key actions] or [REPLACE] constraint resolution are not counted. -** -** Changes to a view that are intercepted by -** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value -** returned by sqlite3_changes() immediately after an INSERT, UPDATE or -** DELETE statement run on a view is always zero. Only changes made to real -** tables are counted. +** ^Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. ** -** Things are more complicated if the sqlite3_changes() function is -** executed while a trigger program is running. This may happen if the -** program uses the [changes() SQL function], or if some other callback -** function invokes sqlite3_changes() directly. Essentially: -** -**
    -**
  • ^(Before entering a trigger program the value returned by -** sqlite3_changes() function is saved. After the trigger program -** has finished, the original value is restored.)^ -** -**
  • ^(Within a trigger program each INSERT, UPDATE and DELETE -** statement sets the value returned by sqlite3_changes() -** upon completion as normal. Of course, this value will not include -** any changes performed by sub-triggers, as the sqlite3_changes() -** value will be saved and restored after each sub-trigger has run.)^ -**
-** -** ^This means that if the changes() SQL function (or similar) is used -** by the first INSERT, UPDATE or DELETE statement within a trigger, it -** returns the value as set when the calling statement began executing. -** ^If it is used by the second or subsequent such statement within a trigger -** program, the value returned reflects the number of rows modified by the -** previous INSERT, UPDATE or DELETE statement within the same trigger. +** ^(A "row change" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other +** mechanisms do not count as direct row changes.)^ +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** ^This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** ^Thus, when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. ^(Within the body of a trigger, +** the sqlite3_changes() interface can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include changes +** caused by subtriggers since those have their own context.)^ ** ** See also the [sqlite3_total_changes()] interface, the ** [count_changes pragma], and the [changes() SQL function]. @@ -2238,23 +2046,25 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*); ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); +SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified -** METHOD: sqlite3 ** -** ^This function returns the total number of rows inserted, modified or -** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed -** since the database connection was opened, including those executed as -** part of trigger programs. ^Executing any other type of SQL statement -** does not affect the value returned by sqlite3_total_changes(). -** -** ^Changes made as part of [foreign key actions] are included in the -** count, but those made as part of REPLACE constraint resolution are -** not. ^Changes to a view that are intercepted by INSTEAD OF triggers -** are not counted. -** +** ^This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** ^(The count returned by sqlite3_total_changes() includes all changes +** from all [CREATE TRIGGER | trigger] contexts and changes made by +** [foreign key actions]. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted.)^ +** ^The sqlite3_total_changes() function counts the changes as soon as +** the statement that makes them is completed (when the statement handle +** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). +** ** See also the [sqlite3_changes()] interface, the ** [count_changes pragma], and the [total_changes() SQL function]. ** @@ -2262,11 +2072,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*); ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); +SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query -** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically @@ -2302,7 +2111,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*); ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); +SQLITE_API void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete @@ -2337,41 +2146,33 @@ SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*); ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql); -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors -** KEYWORDS: {busy-handler callback} {busy handler} -** METHOD: sqlite3 ** -** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X -** that might be invoked with argument P whenever -** an attempt is made to access a database table associated with -** [database connection] D when another thread -** or process has the table locked. -** The sqlite3_busy_handler() interface is used to implement -** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. +** ^This routine sets a callback function that might be invoked whenever +** an attempt is made to open a database table that another thread +** or process has locked. ** -** ^If the busy callback is NULL, then [SQLITE_BUSY] +** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] ** is returned immediately upon encountering the lock. ^If the busy callback ** is not NULL, then the callback might be invoked with two arguments. ** ** ^The first argument to the busy handler is a copy of the void* pointer which ** is the third argument to sqlite3_busy_handler(). ^The second argument to ** the busy handler callback is the number of times that the busy handler has -** been invoked previously for the same locking event. ^If the +** been invoked for this locking event. ^If the ** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] is returned -** to the application. +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. ** ^If the callback returns non-zero, then another attempt -** is made to access the database and the cycle repeats. +** is made to open the database for reading and the cycle repeats. ** ** The presence of a busy handler does not guarantee that it will be invoked ** when there is lock contention. ^If SQLite determines that invoking the busy ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] -** to the application instead of invoking the -** busy handler. +** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. ** Consider a scenario where one process is holding a read lock that ** it is trying to promote to a reserved lock and ** a second process is holding a reserved lock that it is trying @@ -2385,48 +2186,57 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql); ** ** ^The default busy callback is NULL. ** +** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. ^If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** ** ^(There can only be a single busy handler defined for each ** [database connection]. Setting a new busy handler clears any ** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] -** or evaluating [PRAGMA busy_timeout=N] will change the -** busy handler and thus clear any previously set busy handler. +** will also set or clear the busy handler. ** ** The busy callback should not take any actions which modify the -** database connection that invoked the busy handler. In other words, -** the busy handler is not reentrant. Any such actions +** database connection that invoked the busy handler. Any such actions ** result in undefined behavior. ** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout -** METHOD: sqlite3 ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler ** will sleep multiple times until at least "ms" milliseconds of sleeping ** have accumulated. ^After at least "ms" milliseconds of sleeping, ** the handler returns 0 which causes [sqlite3_step()] to return -** [SQLITE_BUSY]. +** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. ** ** ^Calling this routine with an argument less than or equal to zero ** turns off all busy handlers. ** ** ^(There can only be a single busy handler for a particular -** [database connection] at any given moment. If another busy handler +** [database connection] any any given moment. If another busy handler ** was defined (using [sqlite3_busy_handler()]) prior to calling ** this routine, that other busy handler is cleared.)^ -** -** See also: [PRAGMA busy_timeout] */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries -** METHOD: sqlite3 ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. @@ -2497,7 +2307,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms); ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ @@ -2505,17 +2315,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); -SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); +SQLITE_API void sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. -** These routines understand most of the common K&R formatting options, -** plus some additional non-standard formats, detailed below. -** Note that some of the more obscure formatting options from recent -** C-library standards are omitted from this implementation. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. @@ -2548,7 +2354,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", "%w" and "%z" options. +** is are "%q", "%Q", and "%z" options. ** ** ^(The %q option works like %s in that it substitutes a nul-terminated ** string from the argument list. But %q also doubles every '\'' character. @@ -2601,20 +2407,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result); ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. ** -** ^(The "%w" formatting option is like "%q" except that it expects to -** be contained within double-quotes instead of single quotes, and it -** escapes the double-quote character instead of the single-quote -** character.)^ The "%w" formatting option is intended for safely inserting -** table and column names into a constructed SQL statement. -** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list); +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem @@ -2631,10 +2431,6 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns ** a NULL pointer. ** -** ^The sqlite3_malloc64(N) routine works just like -** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead -** of a signed 32-bit integer. -** ** ^Calling sqlite3_free() with a pointer previously returned ** by sqlite3_malloc() or sqlite3_realloc() releases that memory so ** that it might be reused. ^The sqlite3_free() routine is @@ -2646,38 +2442,24 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** might result if sqlite3_free() is called with a non-NULL pointer that ** was not obtained from sqlite3_malloc() or sqlite3_realloc(). ** -** ^The sqlite3_realloc(X,N) interface attempts to resize a -** prior memory allocation X to be at least N bytes. -** ^If the X parameter to sqlite3_realloc(X,N) +** ^(The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter.)^ ^ If the first parameter to sqlite3_realloc() ** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N). -** ^If the N parameter to sqlite3_realloc(X,N) is zero or +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** ^If the second parameter to sqlite3_realloc() is zero or ** negative then the behavior is exactly the same as calling -** sqlite3_free(X). -** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation -** of at least N bytes in size or NULL if insufficient memory is available. +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** ^sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. ** ^If M is the size of the prior allocation, then min(N,M) bytes ** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc(X,N) and the prior allocation is freed. -** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the -** prior allocation is not freed. +** by sqlite3_realloc() and the prior allocation is freed. +** ^If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. ** -** ^The sqlite3_realloc64(X,N) interfaces works the same as -** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead -** of a 32-bit signed integer. -** -** ^If X is a memory allocation previously obtained from sqlite3_malloc(), -** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then -** sqlite3_msize(X) returns the size of that memory allocation in bytes. -** ^The value returned by sqlite3_msize(X) might be larger than the number -** of bytes requested when X was allocated. ^If X is a NULL pointer then -** sqlite3_msize(X) returns zero. If X points to something that is not -** the beginning of memory allocation, or if it points to a formerly -** valid memory allocation that has now been freed, then the behavior -** of sqlite3_msize(X) is undefined and possibly harmful. -** -** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), -** sqlite3_malloc64(), and sqlite3_realloc64() +** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. @@ -2704,12 +2486,9 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int); -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int); -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64); -SQLITE_API void SQLITE_STDCALL sqlite3_free(void*); -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); /* ** CAPI3REF: Memory Allocator Statistics @@ -2734,8 +2513,8 @@ SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*); ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator @@ -2747,22 +2526,20 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag); ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. -** ^The P parameter can be a NULL pointer. +** ^If N is less than one, then P can be a NULL pointer. ** ** ^If this routine has not been previously called or if the previous -** call had N less than one or a NULL pointer for P, then the PRNG is -** seeded using randomness obtained from the xRandomness method of -** the default [sqlite3_vfs] object. -** ^If the previous call to this routine had an N of 1 or more and a -** non-NULL P then the pseudo-randomness is generated +** call had N less than one, then the PRNG is seeded using randomness +** obtained from the xRandomness method of the default [sqlite3_vfs] object. +** ^If the previous call to this routine had an N of 1 or more then +** the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); +SQLITE_API void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks -** METHOD: sqlite3 ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. @@ -2841,7 +2618,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P); ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData @@ -2856,8 +2633,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** [sqlite3_set_authorizer | authorizer documentation] for additional ** information. ** -** Note that SQLITE_IGNORE is also used as a [conflict resolution mode] -** returned from the [sqlite3_vtab_on_conflict()] interface. +** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] +** from the [sqlite3_vtab_on_conflict()] interface. */ #define SQLITE_DENY 1 /* Abort the SQL statement with an error */ #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ @@ -2919,7 +2696,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( /* ** CAPI3REF: Tracing And Profiling Functions -** METHOD: sqlite3 ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. @@ -2946,13 +2722,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, +SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: Query Progress Callbacks -** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to @@ -2982,11 +2757,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*, ** database connections for the meaning of "modify" in this paragraph. ** */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection -** CONSTRUCTOR: sqlite3 ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for @@ -3001,9 +2775,9 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** -** ^The default encoding will be UTF-8 for databases created using -** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases -** created using sqlite3_open16() will be UTF-16 in the native byte order. +** ^The default encoding for the database will be UTF-8 if +** sqlite3_open() or sqlite3_open_v2() is called and +** UTF-16 in the native byte order if sqlite3_open16() is used. ** ** Whether or not an error occurs when it is opened, resources ** associated with the [database connection] handle should be released by @@ -3091,14 +2865,13 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. -** ^(On windows, the first component of an absolute path -** is a drive specification (e.g. "C:").)^ +** ^On windows, the first component of an absolute path +** is a drive specification (e.g. "C:"). ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. -** SQLite and its built-in [VFSes] interpret the -** following query parameters: +** SQLite interprets the following three query parameters: ** **
    **
  • vfs: ^The "vfs" parameter may be used to specify the name of @@ -3133,9 +2906,11 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** -**
  • psow: ^The psow parameter indicates whether or not the +**
  • psow: ^The psow parameter may be "true" (or "on" or "yes" or +** "1") or "false" (or "off" or "no" or "0") to indicate that the ** [powersafe overwrite] property does or does not apply to the -** storage media on which the database file resides. +** storage media on which the database file resides. ^The psow query +** parameter only works for the built-in unix and Windows VFSes. ** **
  • nolock: ^The nolock parameter is a boolean query parameter ** which if set disables file locking in rollback journal modes. This @@ -3211,15 +2986,15 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo ** ** See also: [sqlite3_temp_directory] */ -SQLITE_API int SQLITE_STDCALL sqlite3_open( +SQLITE_API int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open16( +SQLITE_API int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( +SQLITE_API int sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ @@ -3265,22 +3040,19 @@ SQLITE_API int SQLITE_STDCALL sqlite3_open_v2( ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages -** METHOD: sqlite3 ** -** ^If the most recent sqlite3_* API call associated with -** [database connection] D failed, then the sqlite3_errcode(D) interface -** returns the numeric [result code] or [extended result code] for that -** API call. -** If the most recent API call was successful, -** then the return value from sqlite3_errcode() is undefined. -** ^The sqlite3_extended_errcode() +** ^The sqlite3_errcode() interface returns the numeric [result code] or +** [extended result code] for the most recent failed sqlite3_* API call +** associated with a [database connection]. If a prior API call failed +** but the most recent API call succeeded, the return value from +** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() ** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. @@ -3311,41 +3083,40 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha ** was invoked incorrectly by the application. In that case, the ** error code and message may or may not be set. */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db); -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int); +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); /* -** CAPI3REF: Prepared Statement Object +** CAPI3REF: SQL Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** -** An instance of this object represents a single SQL statement that -** has been compiled into binary form and is ready to be evaluated. +** An instance of this object represents a single SQL statement. +** This object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". ** -** Think of each SQL statement as a separate computer program. The -** original SQL text is source code. A prepared statement object -** is the compiled object code. All SQL must be converted into a -** prepared statement before it can be run. -** -** The life-cycle of a prepared statement object usually goes like this: +** The life of a statement object goes something like this: ** **
      -**
    1. Create the prepared statement object using [sqlite3_prepare_v2()]. -**
    2. Bind values to [parameters] using the sqlite3_bind_*() +**
    3. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
    4. Bind values to [host parameters] using the sqlite3_bind_*() ** interfaces. **
    5. Run the SQL by calling [sqlite3_step()] one or more times. -**
    6. Reset the prepared statement using [sqlite3_reset()] then go back +**
    7. Reset the statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. **
    8. Destroy the object using [sqlite3_finalize()]. **
    +** +** Refer to documentation on individual methods above for additional +** information. */ typedef struct sqlite3_stmt sqlite3_stmt; /* ** CAPI3REF: Run-time Limits -** METHOD: sqlite3 ** ** ^(This interface allows the size of various constructs to be limited ** on a connection by connection basis. The first parameter is the @@ -3383,7 +3154,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** ** New run-time limit categories may be added in future releases. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Run-Time Limit Categories @@ -3435,10 +3206,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); ** ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
    SQLITE_LIMIT_TRIGGER_DEPTH
    **
    The maximum depth of recursion for triggers.
    )^ -** -** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
    SQLITE_LIMIT_WORKER_THREADS
    -**
    The maximum number of auxiliary worker threads that a single -** [prepared statement] may start.
    )^ ** */ #define SQLITE_LIMIT_LENGTH 0 @@ -3452,13 +3219,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 -#define SQLITE_LIMIT_WORKER_THREADS 11 /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} -** METHOD: sqlite3 -** CONSTRUCTOR: sqlite3_stmt ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. @@ -3472,14 +3236,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() ** 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 -** 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. +** ^If the nByte argument is less than zero, then zSql is read up to the +** first zero terminator. ^If nByte is non-negative, then it is the maximum +** number of bytes read from zSql. ^When nByte is non-negative, the +** zSql string ends at either the first '\000' or '\u0000' character or +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be gained by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes as this saves SQLite from having to +** make a copy of the input string. ** ** ^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 @@ -3535,28 +3301,28 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal); **
  • ** */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ @@ -3566,17 +3332,15 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( /* ** CAPI3REF: Retrieving Statement SQL -** METHOD: sqlite3_stmt ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was ** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database -** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to @@ -3604,16 +3368,14 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt); ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset -** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using -** [sqlite3_step(S)] but has neither run to completion (returned -** [SQLITE_DONE] from [sqlite3_step(S)]) nor +** [sqlite3_step(S)] but has not run to completion and/or has not ** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) ** interface returns false if S is a NULL pointer. If S is not a ** NULL pointer and is not a pointer to a valid [prepared statement] @@ -3625,7 +3387,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt); ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); /* ** CAPI3REF: Dynamically Typed Value Object @@ -3640,9 +3402,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*); ** Some interfaces require a protected sqlite3_value. Other interfaces ** will accept either a protected or an unprotected sqlite3_value. ** Every interface that accepts sqlite3_value arguments specifies -** whether or not it requires a protected sqlite3_value. The -** [sqlite3_value_dup()] interface can be used to construct a new -** protected sqlite3_value from an unprotected sqlite3_value. +** whether or not it requires a protected sqlite3_value. ** ** The terms "protected" and "unprotected" refer to whether or not ** a mutex is held. An internal mutex is held for a protected @@ -3686,7 +3446,6 @@ typedef struct sqlite3_context sqlite3_context; ** CAPI3REF: Binding Values To Prepared Statements ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} -** METHOD: sqlite3_stmt ** ** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, ** literals may be replaced by a [parameter] that matches one of following @@ -3733,18 +3492,18 @@ typedef struct sqlite3_context sqlite3_context; ** If the fourth parameter to sqlite3_bind_blob() is negative, then ** the behavior is undefined. ** If a non-negative fourth parameter is provided to sqlite3_bind_text() -** or sqlite3_bind_text16() or sqlite3_bind_text64() then -** that parameter must be the byte offset +** or sqlite3_bind_text16() then that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** -** ^The fifth argument to the BLOB and string binding interfaces -** is a destructor used to dispose of the BLOB or +** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called -** to dispose of the BLOB or string even if the call to bind API fails. +** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), +** sqlite3_bind_text(), or sqlite3_bind_text16() fails. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. @@ -3752,14 +3511,6 @@ typedef struct sqlite3_context sqlite3_context; ** SQLite makes its own private copy of the data immediately, before ** the sqlite3_bind_*() routine returns. ** -** ^The sixth argument to sqlite3_bind_text64() must be one of -** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] -** to specify the encoding of the text in the third parameter. If -** the sixth argument to sqlite3_bind_text64() is not one of the -** allowed values shown above, or if the text encoding is different -** from the encoding specified by the sixth parameter, then the behavior -** is undefined. -** ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that ** is filled with zeroes. ^A zeroblob uses a fixed amount of memory ** (just an integer to hold its size) while it is being processed. @@ -3780,33 +3531,24 @@ typedef struct sqlite3_context sqlite3_context; ** ** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an ** [error code] if anything goes wrong. -** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB -** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or -** [SQLITE_MAX_LENGTH]. ** ^[SQLITE_RANGE] is returned if the parameter ** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. ** ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, - void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, - void(*)(void*), unsigned char encoding); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters -** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the @@ -3823,11 +3565,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite ** [sqlite3_bind_parameter_name()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter -** METHOD: sqlite3_stmt ** ** ^The sqlite3_bind_parameter_name(P,N) interface returns ** the name of the N-th [SQL parameter] in the [prepared statement] P. @@ -3851,11 +3592,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*); ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name -** METHOD: sqlite3_stmt ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second @@ -3866,23 +3606,21 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and -** [sqlite3_bind_parameter_name()]. +** [sqlite3_bind_parameter_index()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement -** METHOD: sqlite3_stmt ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set -** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL @@ -3890,11 +3628,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*); ** ** See also: [sqlite3_data_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set -** METHOD: sqlite3_stmt ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() @@ -3919,12 +3656,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt); ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N); +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result -** METHOD: sqlite3_stmt ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in @@ -3968,16 +3704,15 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result -** METHOD: sqlite3_stmt ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the @@ -4005,12 +3740,11 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt* ** is associated with individual values, not with the containers ** used to hold those values. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement -** METHOD: sqlite3_stmt ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy @@ -4086,11 +3820,10 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); +SQLITE_API int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set -** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. @@ -4107,7 +3840,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*); ** ** See also: [sqlite3_column_count()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes @@ -4144,7 +3877,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Result Values From A Query ** KEYWORDS: {column access functions} -** METHOD: sqlite3_stmt +** +** These routines form the "result set" interface. ** ** ^These routines return information about a single column of the current ** result row of a query. ^In every case the first argument is a pointer @@ -4205,14 +3939,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** even empty strings, are always zero-terminated. ^The return ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. ** -** Warning: ^The object returned by [sqlite3_column_value()] is an -** [unprotected sqlite3_value] object. In a multithreaded environment, -** an unprotected sqlite3_value object may only be used safely with -** [sqlite3_bind_value()] and [sqlite3_result_value()]. +** ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. ** If the [unprotected sqlite3_value] object returned by ** [sqlite3_column_value()] is used in any other way, including calls ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], -** or [sqlite3_value_bytes()], the behavior is not threadsafe. +** or [sqlite3_value_bytes()], then the behavior is undefined. ** ** These routines attempt to convert the value where appropriate. ^For ** example, if the internal representation is FLOAT and a text result @@ -4243,6 +3976,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** **
)^ ** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** own equivalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** ** Note that when type conversions occur, pointers returned by prior ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or ** sqlite3_column_text16() may be invalidated. @@ -4267,7 +4006,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** of conversion are done in place when it is possible, but sometimes they ** are not possible and in those cases prior pointers are invalidated. ** -** The safest policy is to invoke these routines +** The safest and easiest to remember policy is to invoke these routines ** in one of the following ways: ** **
    @@ -4287,7 +4026,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** ^The pointers returned are valid until a type conversion occurs as ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or ** [sqlite3_finalize()] is called. ^The memory space used to hold strings -** and BLOBs is freed automatically. Do not pass the pointers returned +** and BLOBs is freed automatically. Do not pass the pointers returned ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** @@ -4297,20 +4036,19 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt); ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object -** DESTRUCTOR: sqlite3_stmt ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors @@ -4334,11 +4072,10 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object -** METHOD: sqlite3_stmt ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. @@ -4361,14 +4098,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt); ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} -** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior @@ -4461,7 +4197,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt); ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4471,7 +4207,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -4481,7 +4217,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, @@ -4499,9 +4235,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** These constant define integer codes that represent the various ** text encodings supported by SQLite. */ -#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ -#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ -#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ @@ -4523,26 +4259,25 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid -** the use of these functions. To encourage programmers to avoid -** these functions, we will not explain what they do. +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you what they do. */ #ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif /* -** CAPI3REF: Obtaining SQL Values -** METHOD: sqlite3_value +** CAPI3REF: Obtaining SQL Function Parameter Values ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on -** the function or aggregate. +** the function or aggregate. ** ** The xFunc (for scalar functions) or xStep (for aggregates) parameters ** to [sqlite3_create_function()] and [sqlite3_create_function16()] @@ -4557,7 +4292,7 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** object results in undefined behavior. ** ** ^These routines work just like the corresponding [column access functions] -** except that these routines take a single [protected sqlite3_value] object +** except that these routines take a single [protected sqlite3_value] object ** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. ** ** ^The sqlite3_value_text16() interface extracts a UTF-16 string @@ -4582,55 +4317,21 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*); -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Finding The Subtype Of SQL Values -** METHOD: sqlite3_value -** -** The sqlite3_value_subtype(V) function returns the subtype for -** an [application-defined SQL function] argument V. The subtype -** information can be used to pass a limited amount of context from -** one SQL function to another. Use the [sqlite3_result_subtype()] -** routine to set the subtype for the return value of an SQL function. -** -** SQLite makes no use of subtype itself. It merely passes the subtype -** from the result of one [application-defined SQL function] into the -** input of another. -*/ -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*); - -/* -** CAPI3REF: Copy And Free SQL Values -** METHOD: sqlite3_value -** -** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] -** object D and returns a pointer to that copy. ^The [sqlite3_value] returned -** is a [protected sqlite3_value] object even if the input is not. -** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. -** -** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object -** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer -** then sqlite3_value_free(V) is a harmless no-op. -*/ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context -** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. @@ -4671,11 +4372,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*); ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions -** METHOD: sqlite3_context ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) @@ -4686,11 +4386,10 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int ** This routine must be called from the same thread in which ** the application-defined function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); +SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions -** METHOD: sqlite3_context ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) @@ -4698,11 +4397,10 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*); ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data -** 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 @@ -4751,8 +4449,8 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*); ** These routines must be called from the same thread in which ** the SQL function is running. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); /* @@ -4775,7 +4473,6 @@ typedef void (*sqlite3_destructor_type)(void*); /* ** CAPI3REF: Setting The Result Of An SQL Function -** METHOD: sqlite3_context ** ** These routines are used by the xFunc or xFinal callbacks that ** implement SQL functions and aggregates. See @@ -4791,9 +4488,9 @@ typedef void (*sqlite3_destructor_type)(void*); ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** -** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) -** interfaces set the result of the application-defined function to be -** a BLOB containing all zero bytes and N bytes in size. +** ^The sqlite3_result_zeroblob() interfaces set the result of +** the application-defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. ** ** ^The sqlite3_result_double() interface sets the result from ** an application-defined function to be a floating point value specified @@ -4842,10 +4539,6 @@ typedef void (*sqlite3_destructor_type)(void*); ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64() interface sets the return value of an -** application-defined function to be a text string in an encoding -** specified by the fifth (and last) parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces @@ -4875,7 +4568,7 @@ typedef void (*sqlite3_destructor_type)(void*); ** from [sqlite3_malloc()] before it returns. ** ** ^The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy of the +** the application-defined function to be a copy the ** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that the [sqlite3_value] specified in the parameter may change or @@ -4888,46 +4581,25 @@ typedef void (*sqlite3_destructor_type)(void*); ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*, - sqlite3_uint64,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, - void(*)(void*), unsigned char encoding); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); - - -/* -** CAPI3REF: Setting The Subtype Of An SQL Function -** METHOD: sqlite3_context -** -** The sqlite3_result_subtype(C,T) function causes the subtype of -** the result from the [application-defined SQL function] with -** [sqlite3_context] C to be the value T. Only the lower 8 bits -** of the subtype T are preserved in current versions of SQLite; -** higher order bits are discarded. -** The number of subtype bytes preserved by SQLite might increase -** in future releases of SQLite. -*/ -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int); +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences -** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. @@ -5005,14 +4677,14 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation( +SQLITE_API int sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(*xCompare)(void*,int,const void*,int,const void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, @@ -5020,7 +4692,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( int(*xCompare)(void*,int,const void*,int,const void*), void(*xDestroy)(void*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, @@ -5030,7 +4702,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( /* ** CAPI3REF: Collation Needed Callbacks -** METHOD: sqlite3 ** ** ^To avoid having to register all collation sequences before a database ** can be used, a single callback function may be registered with the @@ -5055,12 +4726,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const char*) ); -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3*, void*, void(*)(void*,sqlite3*,int eTextRep,const void*) @@ -5074,11 +4745,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_key( +SQLITE_API int sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( +SQLITE_API int sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ @@ -5092,11 +4763,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_key_v2( ** The code to implement this API is not available in the public release ** of SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rekey( +SQLITE_API int sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( +SQLITE_API int sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ @@ -5106,7 +4777,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2( ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( +SQLITE_API void sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5116,7 +4787,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_see( ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ -SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( +SQLITE_API void sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif @@ -5138,7 +4809,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod( ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); +SQLITE_API int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files @@ -5150,13 +4821,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); ** is a NULL pointer, then SQLite performs a search for an appropriate ** temporary file directory. ** -** Applications are strongly discouraged from using this global variable. -** It is required to set a temporary folder on Windows Runtime (WinRT). -** But for all other platforms, it is highly recommended that applications -** neither read nor write this variable. This global variable is a relic -** that exists for backwards compatibility of legacy applications and should -** be avoided in new projects. -** ** It is not safe to read or modify this variable in more than one ** thread at a time. It is not safe to read or modify this variable ** if a [database connection] is being used at the same time in a separate @@ -5175,11 +4839,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int); ** Hence, if this variable is modified directly, either it should be ** made NULL or made to point to memory obtained from [sqlite3_malloc] ** or else the use of the [temp_store_directory pragma] should be avoided. -** Except when requested by the [temp_store_directory pragma], SQLite -** does not free the memory that sqlite3_temp_directory points to. If -** the application wants that memory to be freed, it must do -** so itself, taking care to only do so after all [database connection] -** objects have been destroyed. ** ** Note to Windows Runtime users: The temporary directory must be set ** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various @@ -5238,7 +4897,6 @@ SQLITE_API char *sqlite3_data_directory; /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} -** METHOD: sqlite3 ** ** ^The sqlite3_get_autocommit() interface returns non-zero or ** zero if the given database connection is or is not in autocommit mode, @@ -5257,11 +4915,10 @@ SQLITE_API char *sqlite3_data_directory; ** connection while this routine is running, then the return value ** is undefined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); +SQLITE_API int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement -** METHOD: sqlite3_stmt ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] @@ -5270,11 +4927,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*); ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection -** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file @@ -5287,21 +4943,19 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*); ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only -** METHOD: sqlite3 ** ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement -** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL @@ -5313,11 +4967,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks -** METHOD: sqlite3 ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. @@ -5362,12 +5015,11 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ ** ** See also the [sqlite3_update_hook()] interface. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks -** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument @@ -5414,7 +5066,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), ** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] ** interfaces. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite3_int64), void* @@ -5444,17 +5096,12 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** -** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 -** and will always return SQLITE_MISUSE. On those systems, -** shared cache mode should be enabled per-database connection via -** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. -** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); +SQLITE_API int sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory @@ -5470,11 +5117,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int); ** ** See also: [sqlite3_db_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); +SQLITE_API int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection -** METHOD: sqlite3 ** ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap ** memory as possible from database connection D. Unlike the @@ -5484,7 +5130,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int); ** ** See also: [sqlite3_release_memory()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); +SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size @@ -5536,7 +5182,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*); ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface @@ -5547,34 +5193,26 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ -SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table -** METHOD: sqlite3 ** -** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns -** information about column C of table T in database D -** on [database connection] X.)^ ^The sqlite3_table_column_metadata() -** interface returns SQLITE_OK and fills in the non-NULL pointers in -** the final five arguments with appropriate values if the specified -** column exists. ^The sqlite3_table_column_metadata() interface returns -** SQLITE_ERROR and if the specified column does not exist. -** ^If the column-name parameter to sqlite3_table_column_metadata() is a -** NULL pointer, then this routine simply checks for the existance of the -** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it -** does not. +** ^This routine returns metadata about a specific column of a specific +** database table accessible using the [database connection] handle +** passed as the first function argument. ** ** ^The column is identified by the second, third and fourth parameters to -** this function. ^(The second parameter is either the name of the database +** this function. ^The second parameter is either the name of the database ** (i.e. "main", "temp", or an attached database) containing the specified -** table or NULL.)^ ^If it is NULL, then all attached databases are searched +** table or NULL. ^If it is NULL, then all attached databases are searched ** for the table using the same algorithm used by the database engine to ** resolve unqualified table references. ** ** ^The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. +** name of the desired column, respectively. Neither of these parameters +** may be NULL. ** ** ^Metadata is returned by writing to the memory locations passed as the 5th ** and subsequent parameters to this function. ^Any of these arguments may be @@ -5593,17 +5231,16 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N); ** )^ ** ** ^The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid until the next +** declaration type and collation sequence is valid only until the next ** call to any SQLite API function. ** ** ^If the specified table is actually a view, an [error code] is returned. ** -** ^If the specified column is "rowid", "oid" or "_rowid_" and the table -** is not a [WITHOUT ROWID] table and an +** ^If the specified column is "rowid", "oid" or "_rowid_" and an ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output ** parameters are set for the explicitly declared column. ^(If there is no -** [INTEGER PRIMARY KEY] column, then the outputs -** for the [rowid] are set as follows: +** explicitly declared [INTEGER PRIMARY KEY] column, then the output +** parameters are set as follows: ** **
     **     data type: "INTEGER"
    @@ -5613,11 +5250,15 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N);
     **     auto increment: 0
     ** 
    )^ ** -** ^This function causes all database schemas to be read from disk and -** parsed, if that has not already been done, and returns an error if -** any errors are encountered while loading the schema. +** ^(This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an [error code] is returned and an error message left +** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ +** +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -5631,7 +5272,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( /* ** CAPI3REF: Load An Extension -** METHOD: sqlite3 ** ** ^This interface loads an SQLite extension library from the named file. ** @@ -5664,7 +5304,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( ** ** See also the [load_extension() SQL function]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ @@ -5673,7 +5313,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( /* ** CAPI3REF: Enable Or Disable Extension Loading -** METHOD: sqlite3 ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with [extension loading], and as a means of disabling @@ -5685,7 +5324,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions @@ -5723,7 +5362,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int ono ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading @@ -5735,7 +5374,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void)); ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); +SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading @@ -5743,7 +5382,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)( ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void); +SQLITE_API void sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered @@ -5845,17 +5484,6 @@ struct sqlite3_module { ** ^Information about the ORDER BY clause is stored in aOrderBy[]. ** ^Each term of aOrderBy records a column of the ORDER BY clause. ** -** The colUsed field indicates which columns of the virtual table may be -** required by the current scan. Virtual table columns are numbered from -** zero in the order in which they appear within the CREATE TABLE statement -** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), -** the corresponding bit is set within the colUsed mask if the column may be -** required by SQLite. If the table has at least 64 columns and any column -** to the right of the first 63 is required, then bit 63 of colUsed is also -** set. In other words, column iCol may be required if the expression -** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to -** non-zero. -** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated @@ -5881,31 +5509,13 @@ struct sqlite3_module { ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** -** The xBestIndex method may optionally populate the idxFlags field with a -** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - -** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite -** assumes that the strategy may visit at most one row. -** -** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then -** SQLite also assumes that if a call to the xUpdate() method is made as -** part of the same statement to delete or update a virtual table row and the -** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback -** any database changes. In other words, if the xUpdate() returns -** SQLITE_CONSTRAINT, the database contents must be exactly as they were -** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not -** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by -** the xUpdate method are automatically rolled back by SQLite. -** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info ** structure for SQLite version 3.8.2. If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a -** value greater than or equal to 3008002. Similarly, the idxFlags field -** was added for version 3.9.0. It may therefore only be used if -** sqlite3_libversion_number() returns a value greater than or equal to -** 3009000. +** value greater than or equal to 3008002. */ struct sqlite3_index_info { /* Inputs */ @@ -5933,17 +5543,8 @@ struct sqlite3_index_info { double estimatedCost; /* Estimated cost of using this index */ /* Fields below are only available in SQLite 3.8.2 and later */ sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ - /* Fields below are only available in SQLite 3.9.0 and later */ - int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ - /* Fields below are only available in SQLite 3.10.0 and later */ - sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ }; -/* -** CAPI3REF: Virtual Table Scan Flags -*/ -#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ - /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** @@ -5952,19 +5553,15 @@ struct sqlite3_index_info { ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 /* ** CAPI3REF: Register A Virtual Table Implementation -** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before @@ -5988,13 +5585,13 @@ struct sqlite3_index_info { ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ @@ -6022,7 +5619,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* Number of open cursors */ + int nRef; /* NO LONGER USED */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -6057,11 +5654,10 @@ struct sqlite3_vtab_cursor { ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table -** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. @@ -6076,7 +5672,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up @@ -6104,8 +5700,6 @@ typedef struct sqlite3_blob sqlite3_blob; /* ** CAPI3REF: Open A BLOB For Incremental I/O -** METHOD: sqlite3 -** CONSTRUCTOR: sqlite3_blob ** ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; @@ -6115,42 +5709,26 @@ typedef struct sqlite3_blob sqlite3_blob; ** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow; ** )^ ** -** ^(Parameter zDb is not the filename that contains the database, but -** rather the symbolic name of the database. For attached databases, this is -** the name that appears after the AS keyword in the [ATTACH] statement. -** For the main database file, the database name is "main". For TEMP -** tables, the database name is "temp".)^ -** ** ^If the flags parameter is non-zero, then the BLOB is opened for read -** and write access. ^If the flags parameter is zero, the BLOB is opened for -** read-only access. +** and write access. ^If it is zero, the BLOB is opened for read access. +** ^It is not possible to open a column that is part of an index or primary +** key for writing. ^If [foreign key constraints] are enabled, it is +** not possible to open a column that is part of a [child key] for writing. ** -** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored -** in *ppBlob. Otherwise an [error code] is returned and, unless the error -** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided -** the API is not misused, it is always safe to call [sqlite3_blob_close()] -** on *ppBlob after this function it returns. -** -** This function fails with SQLITE_ERROR if any of the following are true: -**
      -**
    • ^(Database zDb does not exist)^, -**
    • ^(Table zTable does not exist within database zDb)^, -**
    • ^(Table zTable is a WITHOUT ROWID table)^, -**
    • ^(Column zColumn does not exist)^, -**
    • ^(Row iRow is not present in the table)^, -**
    • ^(The specified column of row iRow contains a value that is not -** a TEXT or BLOB value)^, -**
    • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE -** constraint and the blob is being opened for read/write access)^, -**
    • ^([foreign key constraints | Foreign key constraints] are enabled, -** column zColumn is part of a [child key] definition and the blob is -** being opened for read/write access)^. -**
    -** -** ^Unless it returns SQLITE_MISUSE, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^Note that the database name is not the filename that contains +** the database but rather the symbolic name of the database that +** appears after the AS keyword when the database is connected using [ATTACH]. +** ^For the main database file, the database name is "main". +** ^For TEMP tables, the database name is "temp". ** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer.)^ +** ^This function sets the [database connection] error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. ^Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. ** ** ^(If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects @@ -6168,14 +5746,18 @@ typedef struct sqlite3_blob sqlite3_blob; ** interface. Use the [UPDATE] SQL command to change the size of a ** blob. ** +** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID] +** table. Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables. +** ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces -** and the built-in [zeroblob] SQL function may be used to create a -** zero-filled blob to read or write using the incremental-blob interface. +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -6187,7 +5769,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( /* ** CAPI3REF: Move a BLOB Handle to a New Row -** METHOD: sqlite3_blob ** ** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified @@ -6208,34 +5789,34 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( ** ** ^This function sets the database handle error code and message. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle -** DESTRUCTOR: sqlite3_blob ** -** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed -** unconditionally. Even if this routine returns an error code, the -** handle is still closed.)^ +** ^Closes an open [BLOB handle]. ** -** ^If the blob handle being closed was opened for read-write access, and if -** the database is in auto-commit mode and there are no other open read-write -** blob handles or active write statements, the current transaction is -** committed. ^If an error occurs while committing the transaction, an error -** code is returned and the transaction rolled back. +** ^Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in [autocommit mode]. +** ^If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. ** -** Calling this function with an argument that is not a NULL pointer or an -** open blob handle results in undefined behaviour. ^Calling this routine -** with a null pointer (such as would be returned by a failed call to -** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function -** is passed a valid open blob handle, the values returned by the -** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. +** ^(Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. Any errors that occur during +** closing are reported as a non-zero return value.)^ +** +** ^(The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed.)^ +** +** ^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. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB -** METHOD: sqlite3_blob ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The @@ -6247,11 +5828,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *); ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally -** METHOD: sqlite3_blob ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z @@ -6276,33 +5856,26 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *); ** ** See also: [sqlite3_blob_write()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally -** METHOD: sqlite3_blob ** -** ^(This function is used to write data into an open [BLOB handle] from a -** caller-supplied buffer. N bytes of data are copied from the buffer Z -** into the open BLOB, starting at offset iOffset.)^ -** -** ^(On success, sqlite3_blob_write() returns SQLITE_OK. -** Otherwise, an [error code] or an [extended error code] is returned.)^ -** ^Unless SQLITE_MISUSE is returned, this function sets the -** [database connection] error code and message accessible via -** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** ^This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. ^N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** -** This function may only modify the contents of the BLOB; it is +** ^This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is written. The size of the -** BLOB (and hence the maximum value of N+iOffset) can be determined -** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less -** than zero [SQLITE_ERROR] is returned and no data is written. +** [SQLITE_ERROR] is returned and no data is written. ^If N is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred @@ -6311,6 +5884,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, ** have been overwritten by the statement that expired the BLOB handle ** or by other independent statements. ** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in @@ -6318,7 +5894,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, ** ** See also: [sqlite3_blob_read()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects @@ -6349,9 +5925,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes @@ -6363,51 +5939,45 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** ** The SQLite source code contains multiple implementations ** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. The following +** is selected automatically at compile-time. ^(The following ** implementations are available in the SQLite core: ** **
      **
    • SQLITE_MUTEX_PTHREADS **
    • SQLITE_MUTEX_W32 **
    • SQLITE_MUTEX_NOOP -**
    +**
)^ ** -** The SQLITE_MUTEX_NOOP implementation is a set of routines +** ^The SQLITE_MUTEX_NOOP implementation is a set of routines ** that does no real locking and is appropriate for use in -** a single-threaded application. The SQLITE_MUTEX_PTHREADS and +** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and ** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix ** and Windows. ** -** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex ** implementation is included with the library. In this case the ** application must supply a custom mutex implementation using the ** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function ** before calling sqlite3_initialize() or any other public sqlite3_ -** function that calls sqlite3_initialize(). +** function that calls sqlite3_initialize().)^ ** ** ^The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc() -** routine returns NULL if it is unable to allocate the requested -** mutex. The argument to sqlite3_mutex_alloc() must one of these -** integer constants: +** mutex and returns a pointer to it. ^If it returns NULL +** that means that a mutex could not be allocated. ^SQLite +** will unwind its stack and return an error. ^(The argument +** to sqlite3_mutex_alloc() is one of these integer constants: ** **
    **
  • SQLITE_MUTEX_FAST **
  • SQLITE_MUTEX_RECURSIVE **
  • SQLITE_MUTEX_STATIC_MASTER **
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 -**
+**
  • SQLITE_MUTEX_STATIC_LRU2 +** )^ ** ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) ** cause sqlite3_mutex_alloc() to create @@ -6415,14 +5985,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. ** The mutex implementation does not need to make a distinction ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. SQLite will only request a recursive mutex in -** cases where it really needs one. If a faster non-recursive mutex +** not want to. ^SQLite will only request a recursive mutex in +** cases where it really needs one. ^If a faster non-recursive mutex ** implementation is available on the host platform, the mutex subsystem ** might return such a mutex in response to SQLITE_MUTEX_FAST. ** ** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other ** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return -** a pointer to a static preexisting mutex. ^Nine static mutexes are +** a pointer to a static preexisting mutex. ^Six static mutexes are ** used by the current version of SQLite. Future versions of SQLite ** may add additional static mutexes. Static mutexes are for internal ** use by SQLite only. Applications that use SQLite mutexes should @@ -6431,13 +6001,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** ** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. ^For the static +** returns a different mutex on every call. ^But for the static ** mutex types, the same mutex is returned on every call that has ** the same type number. ** ** ^The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. Attempting to deallocate a static -** mutex results in undefined behavior. +** allocated dynamic mutex. ^SQLite is careful to deallocate every +** dynamic mutex that it allocates. The dynamic mutexes must not be in +** use when they are deallocated. Attempting to deallocate a static +** mutex results in undefined behavior. ^SQLite never deallocates +** a static mutex. ** ** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt ** to enter a mutex. ^If another thread is already within the mutex, @@ -6445,21 +6018,23 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] ** upon successful entry. ^(Mutexes created using ** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** In such cases, the +** In such cases the, ** mutex must be exited an equal number of times before another thread -** can enter.)^ If the same thread tries to enter any mutex other -** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. +** can enter.)^ ^(If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** SQLite will never exhibit +** such behavior in its own use of mutexes.)^ ** ** ^(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. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ ** ** ^The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. The behavior +** 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. +** calling thread or is not currently allocated. SQLite will +** never do either.)^ ** ** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or ** sqlite3_mutex_leave() is a NULL pointer, then all three routines @@ -6467,11 +6042,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*); ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object @@ -6480,9 +6055,9 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); ** used to allocate and use mutexes. ** ** Usually, the default mutex implementations provided by SQLite are -** sufficient, however the application has the option of substituting a custom +** sufficient, however the user has the option of substituting a custom ** implementation for specialized deployments or systems for which SQLite -** does not provide a suitable implementation. In this case, the application +** does not provide a suitable implementation. In this case, the user ** creates and populates an instance of this structure to pass ** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. ** Additionally, an instance of this structure can be used as an @@ -6523,13 +6098,13 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*); ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** -** The xMutexInit() method must be threadsafe. It must be harmless to +** The xMutexInit() method must be threadsafe. ^It must be harmless to ** invoke xMutexInit() multiple times within the same process and without ** intervening calls to xMutexEnd(). Second and subsequent calls to ** xMutexInit() must be no-ops. ** -** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] -** and its associates). Similarly, xMutexAlloc() must not use SQLite memory +** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory ** allocation for a static mutex. ^However xMutexAlloc() may use SQLite ** memory allocation for a fast or recursive mutex. ** @@ -6555,34 +6130,34 @@ struct sqlite3_mutex_methods { ** CAPI3REF: Mutex Verification Routines ** ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. The SQLite core +** are intended for use inside assert() statements. ^The SQLite core ** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. The SQLite core only +** are advised to follow the lead of the core. ^The SQLite core only ** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. External mutex implementations +** with the SQLITE_DEBUG flag. ^External mutex implementations ** are only required to provide these routines if SQLITE_DEBUG is ** defined and if NDEBUG is not defined. ** -** These routines should return true if the mutex in their argument +** ^These routines should return true if the mutex in their argument ** is held or not held, respectively, by the calling thread. ** -** The implementation is not required to provide versions of these +** ^The implementation is not required to provide versions of these ** routines that actually work. If the implementation does not provide working ** versions of these routines, it should at least provide stubs that always ** return true so that one does not get spurious assertion failures. ** -** If the argument to sqlite3_mutex_held() is a NULL pointer then +** ^If the argument to sqlite3_mutex_held() is a NULL pointer then ** the routine should return 1. This seems counter-intuitive since ** clearly the mutex cannot be held if it does not exist. But ** the reason the mutex does not exist is because the build is not ** using mutexes. And we do not want the assert() containing the ** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. The sqlite3_mutex_notheld() +** the appropriate thing to do. ^The sqlite3_mutex_notheld() ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* @@ -6605,16 +6180,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ #define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ -#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */ -#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ -#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ -#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ -#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ -#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ /* ** CAPI3REF: Retrieve the mutex for a database connection -** METHOD: sqlite3 ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument @@ -6622,11 +6190,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*); ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files -** METHOD: sqlite3 ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated @@ -6657,7 +6224,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*); ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface @@ -6676,7 +6243,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName ** Unlike most of the SQLite API, this function is not guaranteed to ** operate consistently from one release to the next. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); +SQLITE_API int sqlite3_test_control(int op, ...); /* ** CAPI3REF: Testing Interface Operation Codes @@ -6704,19 +6271,16 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 -#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 -#define SQLITE_TESTCTRL_ISINIT 23 -#define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 +#define SQLITE_TESTCTRL_LAST 22 /* ** CAPI3REF: SQLite Runtime Status ** -** ^These interfaces are used to retrieve runtime status information +** ^This interface is used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes @@ -6730,22 +6294,19 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...); ** ^(Other parameters record only the highwater mark and not the current ** value. For these latter parameters nothing is written into *pCurrent.)^ ** -** ^The sqlite3_status() and sqlite3_status64() routines return -** SQLITE_OK on success and a non-zero [error code] on failure. +** ^The sqlite3_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. ** -** If either the current value or the highwater mark is too large to -** be represented by a 32-bit integer, then the values returned by -** sqlite3_status() are undefined. +** This routine is threadsafe but is not atomic. This routine can be +** called while other threads are running the same or different SQLite +** interfaces. However the values returned in *pCurrent and +** *pHighwater reflect the status of SQLite at different points in time +** and it is possible that another thread might change the parameter +** in between the times when *pCurrent and *pHighwater are written. ** ** See also: [sqlite3_db_status()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); -SQLITE_API int SQLITE_STDCALL sqlite3_status64( - int op, - sqlite3_int64 *pCurrent, - sqlite3_int64 *pHighwater, - int resetFlag -); +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); /* @@ -6824,8 +6385,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( ** The value written into the *pCurrent parameter is undefined.)^ ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(
    SQLITE_STATUS_PARSER_STACK
    -**
    The *pHighwater parameter records the deepest parser stack. -** The *pCurrent value is undefined. The *pHighwater value is only +**
    This parameter records the deepest parser stack. It is only ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
    )^ ** ** @@ -6844,7 +6404,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( /* ** CAPI3REF: Database Connection Status -** METHOD: sqlite3 ** ** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the @@ -6865,7 +6424,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64( ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters for database connections @@ -6907,12 +6466,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
    SQLITE_DBSTATUS_CACHE_USED
    -**
    This parameter returns the approximate number of bytes of heap +**
    This parameter returns the approximate number of of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    -**
    This parameter returns the approximate number of bytes of heap +**
    This parameter returns the approximate number of of bytes of heap ** memory used to store the schema for all databases associated ** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the @@ -6921,7 +6480,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. ** ** [[SQLITE_DBSTATUS_STMT_USED]] ^(
    SQLITE_DBSTATUS_STMT_USED
    -**
    This parameter returns the approximate number of bytes of heap +**
    This parameter returns the approximate number of of bytes of heap ** and lookaside memory used by all prepared statements associated with ** the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. @@ -6973,7 +6532,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int /* ** CAPI3REF: Prepared Statement Status -** METHOD: sqlite3_stmt ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number @@ -6995,7 +6553,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); /* ** CAPI3REF: Status Parameters for prepared statements @@ -7322,10 +6880,6 @@ typedef struct sqlite3_backup sqlite3_backup; ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** -** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if -** there is already a read or read-write transaction open on the -** destination database. -** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. @@ -7418,20 +6972,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** is not a permanent error and does not affect the return value of ** sqlite3_backup_finish(). ** -** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] +** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] ** sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** -** ^The sqlite3_backup_remaining() routine returns the number of pages still -** to be backed up at the conclusion of the most recent sqlite3_backup_step(). -** ^The sqlite3_backup_pagecount() routine returns the total number of pages -** in the source database at the conclusion of the most recent -** sqlite3_backup_step(). -** ^(The values returned by these functions are only updated by -** sqlite3_backup_step(). If the source database is modified in a way that -** changes the size of the source database or the number of pages remaining, -** those changes are not reflected in the output of sqlite3_backup_pagecount() -** and sqlite3_backup_remaining() until after the next -** sqlite3_backup_step().)^ +** ^Each call to sqlite3_backup_step() sets two values inside +** the [sqlite3_backup] object: the number of pages still to be backed +** up and the total number of pages in the source database file. +** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces +** retrieve these two values, respectively. +** +** ^The values returned by these functions are only updated by +** sqlite3_backup_step(). ^If the source database is modified during a backup +** operation, then the values are not updated to account for any extra +** pages that need to be updated or the size of the source database file +** changing. ** ** Concurrent Usage of Database Handles ** @@ -7464,20 +7018,19 @@ typedef struct sqlite3_backup sqlite3_backup; ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification -** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or @@ -7590,7 +7143,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p); ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ @@ -7605,48 +7158,23 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *); -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int); +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing * -** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if -** string X matches the [GLOB] pattern P. -** ^The definition of [GLOB] pattern matching used in +** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches +** the glob pattern P, and it returns non-zero if string X does not match +** the glob pattern P. ^The definition of glob pattern matching used in ** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the -** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function -** is case sensitive. +** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case +** sensitive. ** ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. -** -** See also: [sqlite3_strlike()]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr); - -/* -** CAPI3REF: String LIKE Matching -* -** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if -** string X matches the [LIKE] pattern P with escape character E. -** ^The definition of [LIKE] pattern matching used in -** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E" -** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without -** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0. -** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case -** insensitive - equivalent upper and lower case ASCII characters match -** one another. -** -** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though -** only ASCII characters are case folded. -** -** Note that this routine returns zero on a match and non-zero if the strings -** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. -** -** See also: [sqlite3_strglob()]. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: Error Logging Interface @@ -7669,17 +7197,18 @@ SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zGlob, const char *zSt ** a few hundred characters, it will be truncated to the length of the ** buffer. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...); +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook -** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that -** is invoked each time data is committed to a database in wal mode. +** will be invoked each time a database connection commits data to a +** [write-ahead log] (i.e. whenever a transaction is committed in +** [journal_mode | journal_mode=WAL mode]). ** -** ^(The callback is invoked by SQLite after the commit has taken place and -** the associated write-lock on the database released)^, so the implementation +** ^The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released, so the implementation ** may read, write or [checkpoint] the database as required. ** ** ^The first parameter passed to the callback function when it is invoked @@ -7705,7 +7234,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** those overwrite any prior [sqlite3_wal_hook()] settings. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* @@ -7713,7 +7242,6 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( /* ** CAPI3REF: Configure an auto-checkpoint -** METHOD: sqlite3 ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D @@ -7731,132 +7259,103 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface ** from SQL. ** -** ^Checkpoints initiated by this mechanism are -** [sqlite3_wal_checkpoint_v2|PASSIVE]. -** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] ** pages. The use of this interface ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database -** METHOD: sqlite3 ** -** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to -** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ +** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X +** on [database connection] D to be [checkpointed]. ^If X is NULL or an +** empty string, then a checkpoint is run on all databases of +** connection D. ^If the database connection D is not in +** [WAL | write-ahead log mode] then this interface is a harmless no-op. ** -** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the -** [write-ahead log] for database X on [database connection] D to be -** transferred into the database file and for the write-ahead log to -** be reset. See the [checkpointing] documentation for addition -** information. +** ^The [wal_checkpoint pragma] can be used to invoke this interface +** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] can be used to cause this interface to be +** run whenever the WAL reaches a certain size threshold. ** -** This interface used to be the only way to cause a checkpoint to -** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] -** interface was added. This interface is retained for backwards -** compatibility and as a convenience for applications that need to manually -** start a callback but which do not need the full power (and corresponding -** complication) of [sqlite3_wal_checkpoint_v2()]. +** See also: [sqlite3_wal_checkpoint_v2()] */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database -** METHOD: sqlite3 ** -** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint -** operation on database X of [database connection] D in mode M. Status -** information is written back into integers pointed to by L and C.)^ -** ^(The M parameter must be a valid [checkpoint mode]:)^ +** Run a checkpoint operation on WAL database zDb attached to database +** handle db. The specific operation is determined by the value of the +** eMode parameter: ** **
    **
    SQLITE_CHECKPOINT_PASSIVE
    -** ^Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish, then sync the database file if all frames -** in the log were checkpointed. ^The [busy-handler callback] -** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. -** ^On the other hand, passive mode might leave the checkpoint unfinished -** if there are concurrent readers or writers. +** Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish. Sync the db file if all frames in the log +** are checkpointed. This mode is the same as calling +** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. ** **
    SQLITE_CHECKPOINT_FULL
    -** ^This mode blocks (it invokes the -** [sqlite3_busy_handler|busy-handler callback]) until there is no +** This mode blocks (calls the busy-handler callback) until there is no ** database writer and all readers are reading from the most recent database -** snapshot. ^It then checkpoints all frames in the log file and syncs the -** database file. ^This mode blocks new database writers while it is pending, -** but new database readers are allowed to continue unimpeded. +** snapshot. It then checkpoints all frames in the log file and syncs the +** database file. This call blocks database writers while it is running, +** but not database readers. ** **
    SQLITE_CHECKPOINT_RESTART
    -** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition -** that after checkpointing the log file it blocks (calls the -** [busy-handler callback]) -** until all readers are reading from the database file only. ^This ensures -** that the next writer will restart the log file from the beginning. -** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new -** database writer attempts while it is pending, but does not impede readers. -** -**
    SQLITE_CHECKPOINT_TRUNCATE
    -** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the -** addition that it also truncates the log file to zero bytes just prior -** to a successful return. +** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after +** checkpointing the log file it blocks (calls the busy-handler callback) +** until all readers are reading from the database file only. This ensures +** that the next client to write to the database file restarts the log file +** from the beginning. This call blocks database writers while it is running, +** but not database readers. **
    ** -** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in -** the log file or to -1 if the checkpoint could not run because -** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not -** NULL,then *pnCkpt is set to the total number of checkpointed frames in the -** log file (including any that were already checkpointed before the function -** was called) or to -1 if the checkpoint could not run due to an error or -** because the database is not in WAL mode. ^Note that upon successful -** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been -** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. +** If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to +** the total number of checkpointed frames (including any that were already +** checkpointed when this function is called). *pnLog and *pnCkpt may be +** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. +** If no values are available because of an error, they are both set to -1 +** before returning to communicate this to the caller. ** -** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If +** All calls obtain an exclusive "checkpoint" lock on the database file. If ** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a +** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a ** busy-handler configured, it will not be invoked in this case. ** -** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the -** exclusive "writer" lock on the database file. ^If the writer lock cannot be -** obtained immediately, and a busy-handler is configured, it is invoked and -** the writer lock retried until either the busy-handler returns 0 or the lock -** is successfully obtained. ^The busy-handler is also invoked while waiting for -** database readers as described above. ^If the busy-handler returns 0 before +** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive +** "writer" lock on the database file. If the writer lock cannot be obtained +** immediately, and a busy-handler is configured, it is invoked and the writer +** lock retried until either the busy-handler returns 0 or the lock is +** successfully obtained. The busy-handler is also invoked while waiting for +** database readers as described above. If the busy-handler returns 0 before ** the writer lock is obtained or while waiting for database readers, the ** checkpoint operation proceeds from that point in the same way as ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible -** without blocking any further. ^SQLITE_BUSY is returned in this case. +** without blocking any further. SQLITE_BUSY is returned in this case. ** -** ^If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases [attached] to -** [database connection] db. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. ^If +** If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. If ** an SQLITE_BUSY error is encountered when processing one or more of the ** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned at the end. ^If any other +** attached databases and SQLITE_BUSY is returned to the caller. If any other ** error occurs while processing an attached database, processing is abandoned -** and the error code is returned to the caller immediately. ^If no error +** and the error code returned to the caller immediately. If no error ** (SQLITE_BUSY or otherwise) is encountered while processing the attached ** databases, SQLITE_OK is returned. ** -** ^If database zDb is the name of an attached database that is not in WAL -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If +** If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If ** zDb is not NULL (or a zero length string) and is not the name of any ** attached database, SQLITE_ERROR is returned to the caller. -** -** ^Unless it returns SQLITE_MISUSE, -** the sqlite3_wal_checkpoint_v2() interface -** sets the error information that is queried by -** [sqlite3_errcode()] and [sqlite3_errmsg()]. -** -** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface -** from SQL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -7865,18 +7364,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ); /* -** CAPI3REF: Checkpoint Mode Values -** KEYWORDS: {checkpoint mode} +** CAPI3REF: Checkpoint operation parameters ** -** These constants define all valid values for the "checkpoint mode" passed -** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. -** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the -** meaning of each of these checkpoint modes. +** These constants can be used as the 3rd parameter to +** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] +** documentation for additional information about the meaning and use of +** each of these values. */ -#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ -#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ -#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ -#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ +#define SQLITE_CHECKPOINT_PASSIVE 0 +#define SQLITE_CHECKPOINT_FULL 1 +#define SQLITE_CHECKPOINT_RESTART 2 /* ** CAPI3REF: Virtual Table Interface Configuration @@ -7892,7 +7389,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options @@ -7945,11 +7442,10 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...); ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Conflict resolution modes -** KEYWORDS: {conflict resolution mode} ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to ** inform a [virtual table] implementation what the [ON CONFLICT] mode @@ -7965,232 +7461,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *); /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 -/* -** CAPI3REF: Prepared Statement Scan Status Opcodes -** KEYWORDS: {scanstatus options} -** -** The following constants can be used for the T parameter to the -** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a -** different metric for sqlite3_stmt_scanstatus() to return. -** -** When the value returned to V is a string, space to hold that string is -** managed by the prepared statement S and will be automatically freed when -** S is finalized. -** -**
    -** [[SQLITE_SCANSTAT_NLOOP]]
    SQLITE_SCANSTAT_NLOOP
    -**
    ^The [sqlite3_int64] variable pointed to by the T parameter will be -** set to the total number of times that the X-th loop has run.
    -** -** [[SQLITE_SCANSTAT_NVISIT]]
    SQLITE_SCANSTAT_NVISIT
    -**
    ^The [sqlite3_int64] variable pointed to by the T parameter will be set -** to the total number of rows examined by all iterations of the X-th loop.
    -** -** [[SQLITE_SCANSTAT_EST]]
    SQLITE_SCANSTAT_EST
    -**
    ^The "double" variable pointed to by the T parameter will be set to the -** query planner's estimate for the average number of rows output from each -** iteration of the X-th loop. If the query planner's estimates was accurate, -** then this value will approximate the quotient NVISIT/NLOOP and the -** product of this value for all prior loops with the same SELECTID will -** be the NLOOP value for the current loop. -** -** [[SQLITE_SCANSTAT_NAME]]
    SQLITE_SCANSTAT_NAME
    -**
    ^The "const char *" variable pointed to by the T parameter will be set -** to a zero-terminated UTF-8 string containing the name of the index or table -** used for the X-th loop. -** -** [[SQLITE_SCANSTAT_EXPLAIN]]
    SQLITE_SCANSTAT_EXPLAIN
    -**
    ^The "const char *" variable pointed to by the T parameter will be set -** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] -** description for the X-th loop. -** -** [[SQLITE_SCANSTAT_SELECTID]]
    SQLITE_SCANSTAT_SELECT
    -**
    ^The "int" variable pointed to by the T parameter will be set to the -** "select-id" for the X-th loop. The select-id identifies which query or -** subquery the loop is part of. The main query has a select-id of zero. -** The select-id is the same value as is output in the first column -** of an [EXPLAIN QUERY PLAN] query. -**
    -*/ -#define SQLITE_SCANSTAT_NLOOP 0 -#define SQLITE_SCANSTAT_NVISIT 1 -#define SQLITE_SCANSTAT_EST 2 -#define SQLITE_SCANSTAT_NAME 3 -#define SQLITE_SCANSTAT_EXPLAIN 4 -#define SQLITE_SCANSTAT_SELECTID 5 -/* -** CAPI3REF: Prepared Statement Scan Status -** METHOD: sqlite3_stmt -** -** This interface returns information about the predicted and measured -** performance for pStmt. Advanced applications can use this -** interface to compare the predicted and the measured performance and -** issue warnings and/or rerun [ANALYZE] if discrepancies are found. -** -** Since this interface is expected to be rarely used, it is only -** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] -** compile-time option. -** -** The "iScanStatusOp" parameter determines which status information to return. -** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior -** of this interface is undefined. -** ^The requested measurement is written into a variable pointed to by -** the "pOut" parameter. -** Parameter "idx" identifies the specific loop to retrieve statistics for. -** Loops are numbered starting from zero. ^If idx is out of range - less than -** zero or greater than or equal to the total number of loops used to implement -** the statement - a non-zero value is returned and the variable that pOut -** points to is unchanged. -** -** ^Statistics might not be available for all loops in all statements. ^In cases -** where there exist loops with no available statistics, this function behaves -** as if the loop did not exist - it returns non-zero and leave the variable -** that pOut points to unchanged. -** -** See also: [sqlite3_stmt_scanstatus_reset()] -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ - void *pOut /* Result written here */ -); - -/* -** CAPI3REF: Zero Scan-Status Counters -** METHOD: sqlite3_stmt -** -** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. -** -** This API is only available if the library is built with pre-processor -** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. -*/ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); - -/* -** CAPI3REF: Flush caches to disk mid-transaction -** -** ^If a write-transaction is open on [database connection] D when the -** [sqlite3_db_cacheflush(D)] interface invoked, any dirty -** pages in the pager-cache that are not currently in use are written out -** to disk. A dirty page may be in use if a database cursor created by an -** active SQL statement is reading from it, or if it is page 1 of a database -** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)] -** interface flushes caches for all schemas - "main", "temp", and -** any [attached] databases. -** -** ^If this function needs to obtain extra database locks before dirty pages -** can be flushed to disk, it does so. ^If those locks cannot be obtained -** immediately and there is a busy-handler callback configured, it is invoked -** in the usual manner. ^If the required lock still cannot be obtained, then -** the database is skipped and an attempt made to flush any dirty pages -** belonging to the next (if any) database. ^If any databases are skipped -** because locks cannot be obtained, but no other error occurs, this -** function returns SQLITE_BUSY. -** -** ^If any other error occurs while flushing dirty pages to disk (for -** example an IO error or out-of-memory condition), then processing is -** abandoned and an SQLite [error code] is returned to the caller immediately. -** -** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK. -** -** ^This function does not set the database handle error code or message -** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); - -/* -** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} -** EXPERIMENTAL -** -** An instance of the snapshot object records the state of a [WAL mode] -** database for some specific point in history. -** -** In [WAL mode], multiple [database connections] that are open on the -** same database file can each be reading a different historical version -** of the database file. When a [database connection] begins a read -** transaction, that connection sees an unchanging copy of the database -** as it existed for the point in time when the transaction first started. -** Subsequent changes to the database from other connections are not seen -** by the reader until a new read transaction is started. -** -** The sqlite3_snapshot object records state information about an historical -** version of the database file so that it is possible to later open a new read -** transaction that sees that historical version of the database rather than -** the most recent version. -** -** The constructor for this object is [sqlite3_snapshot_get()]. The -** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer -** to an historical snapshot (if possible). The destructor for -** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. -*/ -typedef struct sqlite3_snapshot sqlite3_snapshot; - -/* -** CAPI3REF: Record A Database Snapshot -** EXPERIMENTAL -** -** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a -** new [sqlite3_snapshot] object that records the current state of -** schema S in database connection D. ^On success, the -** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly -** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** ^If schema S of [database connection] D is not a [WAL mode] database -** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)] -** leaves the *P value unchanged and returns an appropriate [error code]. -** -** The [sqlite3_snapshot] object returned from a successful call to -** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] -** to avoid a memory leak. -** -** The [sqlite3_snapshot_get()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_get( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot **ppSnapshot -); - -/* -** CAPI3REF: Start a read transaction on an historical snapshot -** EXPERIMENTAL -** -** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the -** read transaction that is currently open on schema S of -** [database connection] D so that it refers to historical [snapshot] P. -** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success -** or an appropriate [error code] if it fails. -** -** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be -** the first operation, apart from other sqlite3_snapshot_open() calls, -** following the [BEGIN] that starts a new read transaction. -** ^A [snapshot] will fail to open if it has been overwritten by a -** [checkpoint]. -** -** The [sqlite3_snapshot_open()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_snapshot_open( - sqlite3 *db, - const char *zSchema, - sqlite3_snapshot *pSnapshot -); - -/* -** CAPI3REF: Destroy a snapshot -** EXPERIMENTAL -** -** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. -** The application must eventually free every [sqlite3_snapshot] object -** using this routine to avoid a memory leak. -** -** The [sqlite3_snapshot_free()] interface is only available when the -** SQLITE_ENABLE_SNAPSHOT compile-time option is used. -*/ -SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot*); /* ** Undo the hack that converts floating point types to integer for @@ -8244,7 +7515,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; ** ** SELECT ... FROM WHERE MATCH $zGeom(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), @@ -8270,7 +7541,7 @@ struct sqlite3_rtree_geometry { ** ** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), @@ -8304,8 +7575,6 @@ struct sqlite3_rtree_query_info { int eParentWithin; /* Visibility of parent node */ int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ - /* The following fields are only available in 3.8.11 and later */ - sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; /* @@ -8322,526 +7591,6 @@ struct sqlite3_rtree_query_info { #endif /* ifndef _SQLITE3RTREE_H_ */ -/* -** 2014 May 31 -** -** 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. -** -****************************************************************************** -** -** Interfaces to extend FTS5. Using the interfaces defined in this file, -** FTS5 may be extended with: -** -** * custom tokenizers, and -** * custom auxiliary functions. -*/ - - -#ifndef _FTS5_H -#define _FTS5_H - - -#if 0 -extern "C" { -#endif - -/************************************************************************* -** CUSTOM AUXILIARY FUNCTIONS -** -** Virtual table implementations may overload SQL functions by implementing -** the sqlite3_module.xFindFunction() method. -*/ - -typedef struct Fts5ExtensionApi Fts5ExtensionApi; -typedef struct Fts5Context Fts5Context; -typedef struct Fts5PhraseIter Fts5PhraseIter; - -typedef void (*fts5_extension_function)( - const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ - Fts5Context *pFts, /* First arg to pass to pApi functions */ - sqlite3_context *pCtx, /* Context for returning result/error */ - int nVal, /* Number of values in apVal[] array */ - sqlite3_value **apVal /* Array of trailing arguments */ -); - -struct Fts5PhraseIter { - const unsigned char *a; - const unsigned char *b; -}; - -/* -** EXTENSION API FUNCTIONS -** -** xUserData(pFts): -** Return a copy of the context pointer the extension function was -** registered with. -** -** xColumnTotalSize(pFts, iCol, pnToken): -** If parameter iCol is less than zero, set output variable *pnToken -** to the total number of tokens in the FTS5 table. Or, if iCol is -** non-negative but less than the number of columns in the table, return -** the total number of tokens in column iCol, considering all rows in -** the FTS5 table. -** -** If parameter iCol is greater than or equal to the number of columns -** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is -** returned. -** -** xColumnCount(pFts): -** Return the number of columns in the table. -** -** xColumnSize(pFts, iCol, pnToken): -** If parameter iCol is less than zero, set output variable *pnToken -** to the total number of tokens in the current row. Or, if iCol is -** non-negative but less than the number of columns in the table, set -** *pnToken to the number of tokens in column iCol of the current row. -** -** If parameter iCol is greater than or equal to the number of columns -** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -** an OOM condition or IO error), an appropriate SQLite error code is -** returned. -** -** 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 -** containing the text in utf-8 encoding, (*pn) is set to the size in bytes -** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, -** if an error occurs, an SQLite error code is returned and the final values -** of (*pz) and (*pn) are undefined. -** -** xPhraseCount: -** Returns the number of phrases in the current query expression. -** -** xPhraseSize: -** Returns the number of tokens in phrase iPhrase of the query. Phrases -** are numbered starting from zero. -** -** xInstCount: -** Set *pnInst to the total number of occurrences of all phrases within -** the query within the current row. Return SQLITE_OK if successful, or -** an error code (i.e. SQLITE_NOMEM) if an error occurs. -** -** xInst: -** Query for the details of phrase match iIdx within the current row. -** Phrase matches are numbered starting from zero, so the iIdx argument -** should be greater than or equal to zero and smaller than the value -** output by xInstCount(). -** -** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) -** if an error occurs. -** -** xRowid: -** Returns the rowid of the current row. -** -** xTokenize: -** Tokenize text using the tokenizer belonging to the FTS5 table. -** -** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): -** This API function is used to query the FTS table for phrase iPhrase -** of the current query. Specifically, a query equivalent to: -** -** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid -** -** with $p set to a phrase equivalent to the phrase iPhrase of the -** current query is executed. For each row visited, the callback function -** passed as the fourth argument is invoked. The context and API objects -** passed to the callback function may be used to access the properties of -** each matched row. Invoking Api.xUserData() returns a copy of the pointer -** passed as the third argument to pUserData. -** -** If the callback function returns any value other than SQLITE_OK, the -** query is abandoned and the xQueryPhrase function returns immediately. -** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. -** Otherwise, the error code is propagated upwards. -** -** If the query runs to completion without incident, SQLITE_OK is returned. -** Or, if some error occurs before the query completes or is aborted by -** the callback, an SQLite error code is returned. -** -** -** xSetAuxdata(pFts5, pAux, xDelete) -** -** Save the pointer passed as the second argument as the extension functions -** "auxiliary data". The pointer may then be retrieved by the current or any -** future invocation of the same fts5 extension function made as part of -** of the same MATCH query using the xGetAuxdata() API. -** -** Each extension function is allocated a single auxiliary data slot for -** each FTS query (MATCH expression). If the extension function is invoked -** more than once for a single FTS query, then all invocations share a -** single auxiliary data context. -** -** If there is already an auxiliary data pointer when this function is -** invoked, then it is replaced by the new pointer. If an xDelete callback -** was specified along with the original pointer, it is invoked at this -** point. -** -** The xDelete callback, if one is specified, is also invoked on the -** auxiliary data pointer after the FTS5 query has finished. -** -** If an error (e.g. an OOM condition) occurs within this function, an -** the auxiliary data is set to NULL and an error code returned. If the -** xDelete parameter was not NULL, it is invoked on the auxiliary data -** pointer before returning. -** -** -** xGetAuxdata(pFts5, bClear) -** -** Returns the current auxiliary data pointer for the fts5 extension -** function. See the xSetAuxdata() method for details. -** -** If the bClear argument is non-zero, then the auxiliary data is cleared -** (set to NULL) before this function returns. In this case the xDelete, -** if any, is not invoked. -** -** -** xRowCount(pFts5, pnRow) -** -** This function is used to retrieve the total number of rows in the table. -** In other words, the same value that would be returned by: -** -** SELECT count(*) FROM ftstable; -** -** xPhraseFirst() -** This function is used, along with type Fts5PhraseIter and the xPhraseNext -** method, to iterate through all instances of a single query phrase within -** the current row. This is the same information as is accessible via the -** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -** to use, this API may be faster under some circumstances. To iterate -** through instances of phrase iPhrase, use the following code: -** -** Fts5PhraseIter iter; -** int iCol, iOff; -** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); -** iOff>=0; -** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) -** ){ -** // An instance of phrase iPhrase at offset iOff of column iCol -** } -** -** The Fts5PhraseIter structure is defined above. Applications should not -** modify this structure directly - it should only be used as shown above -** with the xPhraseFirst() and xPhraseNext() API methods. -** -** xPhraseNext() -** See xPhraseFirst above. -*/ -struct Fts5ExtensionApi { - int iVersion; /* Currently always set to 1 */ - - void *(*xUserData)(Fts5Context*); - - int (*xColumnCount)(Fts5Context*); - int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); - int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); - - int (*xTokenize)(Fts5Context*, - const char *pText, int nText, /* Text to tokenize */ - void *pCtx, /* Context passed to xToken() */ - int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ - ); - - int (*xPhraseCount)(Fts5Context*); - int (*xPhraseSize)(Fts5Context*, int iPhrase); - - int (*xInstCount)(Fts5Context*, int *pnInst); - int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); - - sqlite3_int64 (*xRowid)(Fts5Context*); - int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); - int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); - - int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, - int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) - ); - int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); - void *(*xGetAuxdata)(Fts5Context*, int bClear); - - void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); - void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); -}; - -/* -** CUSTOM AUXILIARY FUNCTIONS -*************************************************************************/ - -/************************************************************************* -** CUSTOM TOKENIZERS -** -** Applications may also register custom tokenizer types. A tokenizer -** is registered by providing fts5 with a populated instance of the -** following structure. All structure methods must be defined, setting -** any member of the fts5_tokenizer struct to NULL leads to undefined -** behaviour. The structure methods are expected to function as follows: -** -** xCreate: -** This function is used to allocate and inititalize a tokenizer instance. -** A tokenizer instance is required to actually tokenize text. -** -** The first argument passed to this function is a copy of the (void*) -** pointer provided by the application when the fts5_tokenizer object -** was registered with FTS5 (the third argument to xCreateTokenizer()). -** The second and third arguments are an array of nul-terminated strings -** containing the tokenizer arguments, if any, specified following the -** tokenizer name as part of the CREATE VIRTUAL TABLE statement used -** to create the FTS5 table. -** -** The final argument is an output variable. If successful, (*ppOut) -** should be set to point to the new tokenizer handle and SQLITE_OK -** returned. If an error occurs, some value other than SQLITE_OK should -** be returned. In this case, fts5 assumes that the final value of *ppOut -** is undefined. -** -** xDelete: -** This function is invoked to delete a tokenizer handle previously -** allocated using xCreate(). Fts5 guarantees that this function will -** be invoked exactly once for each successful call to xCreate(). -** -** xTokenize: -** This function is expected to tokenize the nText byte string indicated -** by argument pText. pText may or may not be nul-terminated. The first -** argument passed to this function is a pointer to an Fts5Tokenizer object -** returned by an earlier call to xCreate(). -** -** The second argument indicates the reason that FTS5 is requesting -** tokenization of the supplied text. This is always one of the following -** four values: -** -**
    • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into -** or removed from the FTS table. The tokenizer is being invoked to -** determine the set of tokens to add to (or delete from) the -** FTS index. -** -**
    • FTS5_TOKENIZE_QUERY - A MATCH query is being executed -** against the FTS index. The tokenizer is being called to tokenize -** a bareword or quoted string specified as part of the query. -** -**
    • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as -** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is -** followed by a "*" character, indicating that the last token -** returned by the tokenizer will be treated as a token prefix. -** -**
    • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to -** satisfy an fts5_api.xTokenize() request made by an auxiliary -** function. Or an fts5_api.xColumnSize() request made by the same -** on a columnsize=0 database. -**
    -** -** For each token in the input string, the supplied callback xToken() must -** be invoked. The first argument to it should be a copy of the pointer -** passed as the second argument to xTokenize(). The third and fourth -** arguments are a pointer to a buffer containing the token text, and the -** size of the token in bytes. The 4th and 5th arguments are the byte offsets -** of the first byte of and first byte immediately following the text from -** which the token is derived within the input. -** -** The second argument passed to the xToken() callback ("tflags") should -** normally be set to 0. The exception is if the tokenizer supports -** synonyms. In this case see the discussion below for details. -** -** FTS5 assumes the xToken() callback is invoked for each token in the -** order that they occur within the input text. -** -** If an xToken() callback returns any value other than SQLITE_OK, then -** the tokenization should be abandoned and the xTokenize() method should -** immediately return a copy of the xToken() return value. Or, if the -** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, -** if an error occurs with the xTokenize() implementation itself, it -** may abandon the tokenization and return any error code other than -** SQLITE_OK or SQLITE_DONE. -** -** SYNONYM SUPPORT -** -** Custom tokenizers may also support synonyms. Consider a case in which a -** user wishes to query for a phrase such as "first place". Using the -** built-in tokenizers, the FTS5 query 'first + place' will match instances -** of "first place" within the document set, but not alternative forms -** such as "1st place". In some applications, it would be better to match -** all instances of "first place" or "1st place" regardless of which form -** the user specified in the MATCH query text. -** -** There are several ways to approach this in FTS5: -** -**
    1. By mapping all synonyms to a single token. In this case, the -** In the above example, this means that the tokenizer returns the -** same token for inputs "first" and "1st". Say that token is in -** fact "first", so that when the user inserts the document "I won -** 1st place" entries are added to the index for tokens "i", "won", -** "first" and "place". If the user then queries for '1st + place', -** the tokenizer substitutes "first" for "1st" and the query works -** as expected. -** -**
    2. By adding multiple synonyms for a single term to the FTS index. -** In this case, when tokenizing query text, the tokenizer may -** provide multiple synonyms for a single term within the document. -** FTS5 then queries the index for each synonym individually. For -** example, faced with the query: -** -** -** ... MATCH 'first place' -** -** the tokenizer offers both "1st" and "first" as synonyms for the -** first token in the MATCH query and FTS5 effectively runs a query -** similar to: -** -** -** ... MATCH '(first OR 1st) place' -** -** except that, for the purposes of auxiliary functions, the query -** still appears to contain just two phrases - "(first OR 1st)" -** being treated as a single phrase. -** -**
    3. By adding multiple synonyms for a single term to the FTS index. -** Using this method, when tokenizing document text, the tokenizer -** provides multiple synonyms for each token. So that when a -** document such as "I won first place" is tokenized, entries are -** added to the FTS index for "i", "won", "first", "1st" and -** "place". -** -** This way, even if the tokenizer does not provide synonyms -** when tokenizing query text (it should not - to do would be -** inefficient), it doesn't matter if the user queries for -** 'first + place' or '1st + place', as there are entires in the -** FTS index corresponding to both forms of the first token. -**
    -** -** Whether it is parsing document or query text, any call to xToken that -** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit -** is considered to supply a synonym for the previous token. For example, -** when parsing the document "I won first place", a tokenizer that supports -** synonyms would call xToken() 5 times, as follows: -** -** -** xToken(pCtx, 0, "i", 1, 0, 1); -** xToken(pCtx, 0, "won", 3, 2, 5); -** xToken(pCtx, 0, "first", 5, 6, 11); -** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11); -** xToken(pCtx, 0, "place", 5, 12, 17); -** -** -** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time -** xToken() is called. Multiple synonyms may be specified for a single token -** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. -** There is no limit to the number of synonyms that may be provided for a -** single token. -** -** In many cases, method (1) above is the best approach. It does not add -** extra data to the FTS index or require FTS5 to query for multiple terms, -** so it is efficient in terms of disk space and query speed. However, it -** does not support prefix queries very well. If, as suggested above, the -** token "first" is subsituted for "1st" by the tokenizer, then the query: -** -** -** ... MATCH '1s*' -** -** will not match documents that contain the token "1st" (as the tokenizer -** will probably not map "1s" to any prefix of "first"). -** -** For full prefix support, method (3) may be preferred. In this case, -** because the index contains entries for both "first" and "1st", prefix -** queries such as 'fi*' or '1s*' will match correctly. However, because -** extra entries are added to the FTS index, this method uses more space -** within the database. -** -** Method (2) offers a midpoint between (1) and (3). Using this method, -** a query such as '1s*' will match documents that contain the literal -** token "1st", but not "first" (assuming the tokenizer is not able to -** provide synonyms for prefixes). However, a non-prefix query like '1st' -** will match against "1st" and "first". This method does not require -** extra disk space, as no extra entries are added to the FTS index. -** On the other hand, it may require more CPU cycles to run MATCH queries, -** as separate queries of the FTS index are required for each synonym. -** -** When using methods (2) or (3), it is important that the tokenizer only -** provide synonyms when tokenizing document text (method (2)) or query -** text (method (3)), not both. Doing so will not cause any errors, but is -** inefficient. -*/ -typedef struct Fts5Tokenizer Fts5Tokenizer; -typedef struct fts5_tokenizer fts5_tokenizer; -struct fts5_tokenizer { - int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); - void (*xDelete)(Fts5Tokenizer*); - int (*xTokenize)(Fts5Tokenizer*, - void *pCtx, - int flags, /* Mask of FTS5_TOKENIZE_* flags */ - const char *pText, int nText, - int (*xToken)( - void *pCtx, /* Copy of 2nd argument to xTokenize() */ - int tflags, /* Mask of FTS5_TOKEN_* flags */ - const char *pToken, /* Pointer to buffer containing token */ - int nToken, /* Size of token in bytes */ - int iStart, /* Byte offset of token within input text */ - int iEnd /* Byte offset of end of token within input text */ - ) - ); -}; - -/* Flags that may be passed as the third argument to xTokenize() */ -#define FTS5_TOKENIZE_QUERY 0x0001 -#define FTS5_TOKENIZE_PREFIX 0x0002 -#define FTS5_TOKENIZE_DOCUMENT 0x0004 -#define FTS5_TOKENIZE_AUX 0x0008 - -/* Flags that may be passed by the tokenizer implementation back to FTS5 -** as the third argument to the supplied xToken callback. */ -#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */ - -/* -** END OF CUSTOM TOKENIZERS -*************************************************************************/ - -/************************************************************************* -** FTS5 EXTENSION REGISTRATION API -*/ -typedef struct fts5_api fts5_api; -struct fts5_api { - int iVersion; /* Currently always set to 2 */ - - /* Create a new tokenizer */ - int (*xCreateTokenizer)( - fts5_api *pApi, - const char *zName, - void *pContext, - fts5_tokenizer *pTokenizer, - void (*xDestroy)(void*) - ); - - /* Find an existing tokenizer */ - int (*xFindTokenizer)( - fts5_api *pApi, - const char *zName, - void **ppContext, - fts5_tokenizer *pTokenizer - ); - - /* Create a new auxiliary function */ - int (*xCreateFunction)( - fts5_api *pApi, - const char *zName, - void *pContext, - fts5_extension_function xFunction, - void (*xDestroy)(void*) - ); -}; - -/* -** END OF REGISTRATION API -*************************************************************************/ - -#if 0 -} /* end of the 'extern "C"' block */ -#endif - -#endif /* _FTS5_H */ - - /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -8956,17 +7705,15 @@ struct fts5_api { #endif /* -** The suggested maximum number of in-memory pages to use for -** the main database table and for temporary tables. -** -** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size -** is 2000 pages. -** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be -** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE */ #ifndef SQLITE_DEFAULT_CACHE_SIZE # define SQLITE_DEFAULT_CACHE_SIZE 2000 #endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif /* ** The default number of frames to accumulate in the log file before @@ -9079,6 +7826,15 @@ struct fts5_api { #pragma warn -spa /* Suspicious pointer arithmetic */ #endif +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#if defined(__OpenBSD__) && !defined(_BSD_SOURCE) +# define _BSD_SOURCE +#endif + /* ** Include standard header files as necessary */ @@ -9119,51 +7875,6 @@ struct fts5_api { # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif -/* -** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to -** something between S (inclusive) and E (exclusive). -** -** In other words, S is a buffer and E is a pointer to the first byte after -** the end of buffer S. This macro returns true if P points to something -** contained within the buffer S. -*/ -#if defined(HAVE_STDINT_H) -# define SQLITE_WITHIN(P,S,E) \ - ((uintptr_t)(P)>=(uintptr_t)(S) && (uintptr_t)(P)<(uintptr_t)(E)) -#else -# define SQLITE_WITHIN(P,S,E) ((P)>=(S) && (P)<(E)) -#endif - -/* -** A macro to hint to the compiler that a function should not be -** inlined. -*/ -#if defined(__GNUC__) -# define SQLITE_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) && _MSC_VER>=1310 -# define SQLITE_NOINLINE __declspec(noinline) -#else -# define SQLITE_NOINLINE -#endif - -/* -** Make sure that the compiler intrinsics we desire are enabled when -** compiling with an appropriate version of MSVC unless prevented by -** the SQLITE_DISABLE_INTRINSIC define. -*/ -#if !defined(SQLITE_DISABLE_INTRINSIC) -# if defined(_MSC_VER) && _MSC_VER>=1300 -# if !defined(_WIN32_WCE) -# include -# pragma intrinsic(_byteswap_ushort) -# pragma intrinsic(_byteswap_ulong) -# pragma intrinsic(_ReadWriteBarrier) -# else -# include -# endif -# endif -#endif - /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never @@ -9192,9 +7903,10 @@ struct fts5_api { #endif /* -** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by -** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in -** which case memory allocation statistics are disabled by default. +** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. +** It determines whether or not the features related to +** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can +** be overridden at runtime using the sqlite3_config() API. */ #if !defined(SQLITE_DEFAULT_MEMSTATUS) # define SQLITE_DEFAULT_MEMSTATUS 1 @@ -9349,33 +8061,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int); #endif /* -** Declarations used for tracing the operating system interfaces. -*/ -#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \ - (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) - extern int sqlite3OSTrace; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -# define SQLITE_HAVE_OS_TRACE -#else -# define OSTRACE(X) -# undef SQLITE_HAVE_OS_TRACE -#endif - -/* -** Is the sqlite3ErrName() function needed in the build? Currently, -** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when -** OSTRACE is enabled), and by several "test*.c" files (which are -** compiled using SQLITE_TEST). -*/ -#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \ - (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) -# define SQLITE_NEED_ERR_NAME -#else -# undef SQLITE_NEED_ERR_NAME -#endif - -/* -** Return true (non-zero) if the input is an integer that is too large +** Return true (non-zero) if the input is a integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() ** macros to verify that we have tested SQLite for large-file support. */ @@ -9454,15 +8140,15 @@ struct Hash { struct HashElem { HashElem *next, *prev; /* Next and previous elements in the table */ void *data; /* Data associated with this element */ - const char *pKey; /* Key associated with this element */ + const char *pKey; int nKey; /* Key associated with this element */ }; /* ** Access routines. To delete, insert a NULL pointer. */ SQLITE_PRIVATE void sqlite3HashInit(Hash*); -SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, void *pData); -SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); SQLITE_PRIVATE void sqlite3HashClear(Hash*); /* @@ -9643,24 +8329,16 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_TO_REAL 147 #define TK_ISNOT 148 #define TK_END_OF_FILE 149 -#define TK_UNCLOSED_STRING 150 -#define TK_FUNCTION 151 -#define TK_COLUMN 152 -#define TK_AGG_FUNCTION 153 -#define TK_AGG_COLUMN 154 -#define TK_UMINUS 155 -#define TK_UPLUS 156 -#define TK_REGISTER 157 -#define TK_ASTERISK 158 -#define TK_SPACE 159 -#define TK_ILLEGAL 160 - -/* The token codes above must all fit in 8 bits */ -#define TKFLG_MASK 0xff - -/* Flags that can be added to a token code when it is not -** being stored in a u8: */ -#define TKFLG_DONTFOLD 0x100 /* Omit constant folding optimizations */ +#define TK_ILLEGAL 150 +#define TK_SPACE 151 +#define TK_UNCLOSED_STRING 152 +#define TK_FUNCTION 153 +#define TK_COLUMN 154 +#define TK_AGG_FUNCTION 155 +#define TK_AGG_COLUMN 156 +#define TK_UMINUS 157 +#define TK_UPLUS 158 +#define TK_REGISTER 159 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -9729,36 +8407,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ #endif -/* -** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if -** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it -** to zero. -*/ -#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0 -# undef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS 0 -#endif -#ifndef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS 8 -#endif -#ifndef SQLITE_DEFAULT_WORKER_THREADS -# define SQLITE_DEFAULT_WORKER_THREADS 0 -#endif -#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS -# undef SQLITE_MAX_WORKER_THREADS -# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS -#endif - -/* -** The default initial allocation for the pagecache when using separate -** pagecaches for each database connection. A positive number is the -** number of pages. A negative number N translations means that a buffer -** of -1024*N bytes is allocated and used for as many pages as it will hold. -*/ -#ifndef SQLITE_DEFAULT_PCACHE_INITSZ -# define SQLITE_DEFAULT_PCACHE_INITSZ 100 -#endif - /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. @@ -9773,11 +8421,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define MIN(A,B) ((A)<(B)?(A):(B)) #define MAX(A,B) ((A)>(B)?(A):(B)) -/* -** Swap two objects of type TYPE. -*/ -#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} - /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) @@ -9867,7 +8510,7 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ ** gives a possible range of values of approximately 1.0e986 to 1e-986. ** But the allowed values are "grainy". Not every value is representable. ** For example, quantities 16 and 17 are both represented by a LogEst -** of 40. However, since LogEst quantities are suppose to be estimates, +** of 40. However, since LogEst quantaties are suppose to be estimates, ** not exact values, this imprecision is not a problem. ** ** "LogEst" is short for "Logarithmic Estimate". @@ -9886,20 +8529,6 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ */ typedef INT16_TYPE LogEst; -/* -** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer -*/ -#ifndef SQLITE_PTRSIZE -# if defined(__SIZEOF_POINTER__) -# define SQLITE_PTRSIZE __SIZEOF_POINTER__ -# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(_M_ARM) || defined(__arm__) || defined(__x86) -# define SQLITE_PTRSIZE 4 -# else -# define SQLITE_PTRSIZE 8 -# endif -#endif - /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. @@ -9909,6 +8538,11 @@ typedef INT16_TYPE LogEst; ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ +#ifdef SQLITE_AMALGAMATION +SQLITE_PRIVATE const int sqlite3one = 1; +#else +SQLITE_PRIVATE const int sqlite3one; +#endif #if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ @@ -9926,11 +8560,6 @@ typedef INT16_TYPE LogEst; # define SQLITE_UTF16NATIVE SQLITE_UTF16BE #endif #if !defined(SQLITE_BYTEORDER) -# ifdef SQLITE_AMALGAMATION - const int sqlite3one = 1; -# else - extern const int sqlite3one; -# endif # define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) @@ -9962,7 +8591,7 @@ typedef INT16_TYPE LogEst; ** all alignment restrictions correct. ** ** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the -** underlying malloc() implementation might return us 4-byte aligned +** underlying malloc() implemention might return us 4-byte aligned ** pointers. In that case, only verify 4-byte alignment. */ #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC @@ -9993,9 +8622,7 @@ typedef INT16_TYPE LogEst; # if defined(__linux__) \ || defined(_WIN32) \ || (defined(__APPLE__) && defined(__MACH__)) \ - || defined(__sun) \ - || defined(__FreeBSD__) \ - || defined(__DragonFly__) + || defined(__sun) # define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ # else # define SQLITE_MAX_MMAP_SIZE 0 @@ -10031,16 +8658,6 @@ typedef INT16_TYPE LogEst; # undef SQLITE_ENABLE_STAT3_OR_STAT4 #endif -/* -** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not -** the Select query generator tracing logic is turned on. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) -# define SELECTTRACE_ENABLED 1 -#else -# define SELECTTRACE_ENABLED 0 -#endif - /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. @@ -10114,8 +8731,8 @@ struct BusyHandler { #define SQLITE_WSD const #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) -SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J); -SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L); +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); #else #define SQLITE_WSD #define GLOBAL(t,v) v @@ -10173,14 +8790,12 @@ typedef struct PrintfArguments PrintfArguments; typedef struct RowSet RowSet; typedef struct Savepoint Savepoint; typedef struct Select Select; -typedef struct SQLiteThread SQLiteThread; typedef struct SelectDest SelectDest; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; -typedef struct TreeView TreeView; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; @@ -10219,7 +8834,7 @@ typedef struct With With; /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ -#define SQLITE_N_BTREE_META 16 +#define SQLITE_N_BTREE_META 10 /* ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise @@ -10263,7 +8878,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeSetSpillSize(Btree*,int); #if SQLITE_MAX_MMAP_SIZE>0 SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); #endif @@ -10274,15 +8888,17 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); -SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*); +SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); +#endif SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); @@ -10315,7 +8931,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); @@ -10333,11 +8949,6 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); ** For example, the free-page-count field is located at byte offset 36 of ** the database file header. The incr-vacuum-flag field is located at ** byte offset 64 (== 36+4*7). -** -** The BTREE_DATA_VERSION value is not really a value stored in the header. -** It is a read-only number computed by the pager. But we merge it with -** the header value access routines since its access pattern is the same. -** Call it a "virtual meta value". */ #define BTREE_FREE_PAGE_COUNT 0 #define BTREE_SCHEMA_VERSION 1 @@ -10348,68 +8959,12 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 #define BTREE_APPLICATION_ID 8 -#define BTREE_DATA_VERSION 15 /* A virtual meta-value */ /* -** Kinds of hints that can be passed into the sqlite3BtreeCursorHint() -** interface. -** -** BTREE_HINT_RANGE (arguments: Expr*, Mem*) -** -** The first argument is an Expr* (which is guaranteed to be constant for -** the lifetime of the cursor) that defines constraints on which rows -** might be fetched with this cursor. The Expr* tree may contain -** TK_REGISTER nodes that refer to values stored in the array of registers -** passed as the second parameter. In other words, if Expr.op==TK_REGISTER -** then the value of the node is the value in Mem[pExpr.iTable]. Any -** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th -** column of the b-tree of the cursor. The Expr tree will not contain -** any function calls nor subqueries nor references to b-trees other than -** the cursor being hinted. -** -** The design of the _RANGE hint is aid b-tree implementations that try -** to prefetch content from remote machines - to provide those -** implementations with limits on what needs to be prefetched and thereby -** reduce network bandwidth. -** -** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by -** standard SQLite. The other hints are provided for extentions that use -** the SQLite parser and code generator but substitute their own storage -** engine. +** Values that may be OR'd together to form the second argument of an +** sqlite3BtreeCursorHints() call. */ -#define BTREE_HINT_RANGE 0 /* Range constraints on queries */ - -/* -** Values that may be OR'd together to form the argument to the -** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint(): -** -** The BTREE_BULKLOAD flag is set on index cursors when the index is going -** to be filled with content that is already in sorted order. -** -** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or -** OP_SeekLE opcodes for a range search, but where the range of entries -** selected will all have the same key. In other words, the cursor will -** be used only for equality key searches. -** -*/ -#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ -#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ - -/* -** Flags passed as the third argument to sqlite3BtreeCursor(). -** -** For read-only cursors the wrFlag argument is always zero. For read-write -** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or -** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will -** only be used by SQLite for the following: -** -** * to seek to and delete specific entries, and/or -** -** * to read values that will be used to create keys that other -** BTREE_FORDELETE cursors will seek to and delete. -*/ -#define BTREE_WRCSR 0x00000004 /* read-write cursor */ -#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ +#define BTREE_BULKLOAD 0x00000001 SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ @@ -10420,10 +8975,6 @@ SQLITE_PRIVATE int sqlite3BtreeCursor( ); SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); -#ifdef SQLITE_ENABLE_CURSOR_HINTS -SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); -#endif SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( @@ -10433,9 +8984,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( int bias, int *pRes ); -SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, int); +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, int nZero, int bias, int seekResult); @@ -10458,9 +9008,8 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); -SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); +SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); @@ -10572,23 +9121,19 @@ struct VdbeOp { int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ - union p4union { /* fourth parameter */ + union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ void *p; /* Generic pointer */ char *z; /* Pointer to data for string (char array) types */ i64 *pI64; /* Used when p4type is P4_INT64 */ double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ - sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ -#ifdef SQLITE_ENABLE_CURSOR_HINTS - Expr *pExpr; /* Used when p4type is P4_EXPR */ -#endif int (*xAdvance)(BtCursor *, int *); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS @@ -10639,7 +9184,6 @@ typedef struct VdbeOpList VdbeOpList; #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ @@ -10650,7 +9194,6 @@ typedef struct VdbeOpList VdbeOpList; #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ #define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_FUNCCTX (-20) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -10692,82 +9235,82 @@ typedef struct VdbeOpList VdbeOpList; /************** Include opcodes.h in the middle of vdbe.h ********************/ /************** Begin file opcodes.h *****************************************/ /* Automatically generated. Do not edit */ -/* See the tool/mkopcodeh.tcl script for details */ -#define OP_Savepoint 1 -#define OP_AutoCommit 2 -#define OP_Transaction 3 -#define OP_SorterNext 4 -#define OP_PrevIfOpen 5 -#define OP_NextIfOpen 6 -#define OP_Prev 7 -#define OP_Next 8 -#define OP_Checkpoint 9 -#define OP_JournalMode 10 -#define OP_Vacuum 11 -#define OP_VFilter 12 /* synopsis: iplan=r[P3] zplan='P4' */ -#define OP_VUpdate 13 /* synopsis: data=r[P3@P2] */ -#define OP_Goto 14 -#define OP_Gosub 15 -#define OP_Return 16 -#define OP_InitCoroutine 17 -#define OP_EndCoroutine 18 +/* See the mkopcodeh.awk script for details */ +#define OP_Function 1 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Savepoint 2 +#define OP_AutoCommit 3 +#define OP_Transaction 4 +#define OP_SorterNext 5 +#define OP_PrevIfOpen 6 +#define OP_NextIfOpen 7 +#define OP_Prev 8 +#define OP_Next 9 +#define OP_AggStep 10 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_Checkpoint 11 +#define OP_JournalMode 12 +#define OP_Vacuum 13 +#define OP_VFilter 14 /* synopsis: iplan=r[P3] zplan='P4' */ +#define OP_VUpdate 15 /* synopsis: data=r[P3@P2] */ +#define OP_Goto 16 +#define OP_Gosub 17 +#define OP_Return 18 #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_Yield 20 -#define OP_HaltIfNull 21 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 22 -#define OP_Integer 23 /* synopsis: r[P2]=P1 */ -#define OP_Int64 24 /* synopsis: r[P2]=P4 */ -#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 27 /* synopsis: r[P1]=NULL */ -#define OP_Blob 28 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 29 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 30 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 31 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 32 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 33 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 34 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 35 -#define OP_Function0 36 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Function 37 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_AddImm 38 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_MustBeInt 39 -#define OP_RealAffinity 40 -#define OP_Cast 41 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 42 -#define OP_Compare 43 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_Jump 44 -#define OP_Once 45 -#define OP_If 46 -#define OP_IfNot 47 -#define OP_Column 48 /* synopsis: r[P3]=PX */ -#define OP_Affinity 49 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 50 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 51 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 52 -#define OP_SetCookie 53 -#define OP_ReopenIdx 54 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 55 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 56 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenAutoindex 57 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 58 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 59 -#define OP_SequenceTest 60 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 61 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 62 -#define OP_ColumnsUsed 63 -#define OP_SeekLT 64 /* synopsis: key=r[P3@P4] */ -#define OP_SeekLE 65 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGE 66 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGT 67 /* synopsis: key=r[P3@P4] */ -#define OP_Seek 68 /* synopsis: intkey=r[P2] */ -#define OP_NoConflict 69 /* synopsis: key=r[P3@P4] */ -#define OP_NotFound 70 /* synopsis: key=r[P3@P4] */ +#define OP_InitCoroutine 20 +#define OP_EndCoroutine 21 +#define OP_Yield 22 +#define OP_HaltIfNull 23 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 24 +#define OP_Integer 25 /* synopsis: r[P2]=P1 */ +#define OP_Int64 26 /* synopsis: r[P2]=P4 */ +#define OP_String 27 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 28 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 29 /* synopsis: r[P1]=NULL */ +#define OP_Blob 30 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 31 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 32 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 33 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 34 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 35 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 36 +#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_MustBeInt 38 +#define OP_RealAffinity 39 +#define OP_Permutation 40 +#define OP_Compare 41 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_Jump 42 +#define OP_Once 43 +#define OP_If 44 +#define OP_IfNot 45 +#define OP_Column 46 /* synopsis: r[P3]=PX */ +#define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 49 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 50 +#define OP_SetCookie 51 +#define OP_OpenRead 52 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 53 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenAutoindex 54 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 55 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 56 +#define OP_OpenPseudo 57 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 58 +#define OP_SeekLT 59 +#define OP_SeekLE 60 +#define OP_SeekGE 61 +#define OP_SeekGT 62 +#define OP_Seek 63 /* synopsis: intkey=r[P2] */ +#define OP_NoConflict 64 /* synopsis: key=r[P3@P4] */ +#define OP_NotFound 65 /* synopsis: key=r[P3@P4] */ +#define OP_Found 66 /* synopsis: key=r[P3@P4] */ +#define OP_NotExists 67 /* synopsis: intkey=r[P3] */ +#define OP_Sequence 68 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 69 /* synopsis: r[P2]=rowid */ +#define OP_Insert 70 /* synopsis: intkey=r[P3] data=r[P2] */ #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_Found 73 /* synopsis: key=r[P3@P4] */ -#define OP_NotExists 74 /* synopsis: intkey=r[P3] */ -#define OP_Sequence 75 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_InsertInt 73 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 74 +#define OP_ResetCount 75 #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ @@ -10776,7 +9319,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]=r[P3] goto P2 */ -#define OP_NewRowid 84 /* synopsis: r[P2]=rowid */ +#define OP_SorterCompare 84 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */ #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<0 then r[P1]-=P3, goto P2 */ -#define OP_SetIfNotPos 140 /* synopsis: if r[P1]<=0 then r[P2]=P3 */ -#define OP_IfNotZero 141 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ -#define OP_DecrJumpZero 142 /* synopsis: if (--r[P1])==0 goto P2 */ -#define OP_JumpZeroIncr 143 /* synopsis: if (r[P1]++)==0 ) goto P2 */ -#define OP_AggStep0 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 145 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 146 /* synopsis: accum=r[P1] N=P2 */ -#define OP_IncrVacuum 147 -#define OP_Expire 148 -#define OP_TableLock 149 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 150 -#define OP_VCreate 151 -#define OP_VDestroy 152 -#define OP_VOpen 153 -#define OP_VColumn 154 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VNext 155 -#define OP_VRename 156 -#define OP_Pagecount 157 -#define OP_MaxPgcnt 158 -#define OP_Init 159 /* synopsis: Start at P2 */ -#define OP_CursorHint 160 -#define OP_Noop 161 -#define OP_Explain 162 +#define OP_IfPos 134 /* synopsis: if r[P1]>0 goto P2 */ +#define OP_IfNeg 135 /* synopsis: if r[P1]<0 goto P2 */ +#define OP_IfZero 136 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */ +#define OP_AggFinal 137 /* synopsis: accum=r[P1] N=P2 */ +#define OP_IncrVacuum 138 +#define OP_Expire 139 +#define OP_TableLock 140 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 141 +#define OP_VCreate 142 +#define OP_ToText 143 /* same as TK_TO_TEXT */ +#define OP_ToBlob 144 /* same as TK_TO_BLOB */ +#define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */ +#define OP_ToInt 146 /* same as TK_TO_INT */ +#define OP_ToReal 147 /* same as TK_TO_REAL */ +#define OP_VDestroy 148 +#define OP_VOpen 149 +#define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VNext 151 +#define OP_VRename 152 +#define OP_Pagecount 153 +#define OP_MaxPgcnt 154 +#define OP_Init 155 /* synopsis: Start at P2 */ +#define OP_Noop 156 +#define OP_Explain 157 + /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c ** are encoded into bitvectors as follows: */ #define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ -#define OPFLG_IN1 0x0002 /* in1: P1 is an input */ -#define OPFLG_IN2 0x0004 /* in2: P2 is an input */ -#define OPFLG_IN3 0x0008 /* in3: P3 is an input */ -#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */ -#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ +#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ +#define OPFLG_IN1 0x0004 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0008 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0010 /* in3: P3 is an input */ +#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ +#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,\ -/* 8 */ 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01,\ -/* 16 */ 0x02, 0x01, 0x02, 0x12, 0x03, 0x08, 0x00, 0x10,\ -/* 24 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,\ -/* 32 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,\ -/* 40 */ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03,\ -/* 48 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00,\ -/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 64 */ 0x09, 0x09, 0x09, 0x09, 0x04, 0x09, 0x09, 0x26,\ -/* 72 */ 0x26, 0x09, 0x09, 0x10, 0x03, 0x03, 0x0b, 0x0b,\ -/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x10, 0x26, 0x26, 0x26,\ -/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ -/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 104 */ 0x00, 0x10, 0x00, 0x01, 0x01, 0x01, 0x01, 0x04,\ -/* 112 */ 0x04, 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10,\ -/* 120 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ -/* 128 */ 0x00, 0x00, 0x06, 0x23, 0x0b, 0x10, 0x01, 0x10,\ -/* 136 */ 0x00, 0x01, 0x04, 0x03, 0x06, 0x03, 0x03, 0x03,\ -/* 144 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01,\ -/* 160 */ 0x00, 0x00, 0x00,} +/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\ +/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\ +/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\ +/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\ +/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\ +/* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\ +/* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\ +/* 64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\ +/* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\ +/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\ +/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\ +/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\ +/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\ +/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15,\ +/* 128 */ 0x01, 0x02, 0x00, 0x01, 0x08, 0x02, 0x05, 0x05,\ +/* 136 */ 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,\ +/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,\ +/* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -10900,16 +9439,11 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*); SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); -SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe*,int); -SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe*,int,const char*); -SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); -SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); @@ -10947,14 +9481,12 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif -SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int); SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); -typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); +typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int); SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER @@ -11021,12 +9553,6 @@ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); # define VDBE_OFFSET_LINENO(x) 0 #endif -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); -#else -# define sqlite3VdbeScanStatus(a,b,c,d,e) -#endif - #endif /************** End of vdbe.h ************************************************/ @@ -11114,7 +9640,7 @@ typedef struct PgHdr DbPage; #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ /* -** Flags that make up the mask passed to sqlite3PagerGet(). +** Flags that make up the mask passed to sqlite3PagerAcquire(). */ #define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */ #define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */ @@ -11153,12 +9679,8 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); -#ifdef SQLITE_HAS_CODEC -SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); -#endif SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); -SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned); @@ -11168,10 +9690,10 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); -SQLITE_PRIVATE int sqlite3PagerFlush(Pager*); /* Functions used to obtain and release page references. */ -SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); @@ -11203,10 +9725,6 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); -# ifdef SQLITE_ENABLE_SNAPSHOT -SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); -# endif #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -11215,15 +9733,11 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); /* Functions used to query pager state and configuration. */ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); -SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); -#endif +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); -SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); -SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*); SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); @@ -11235,8 +9749,6 @@ SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); /* Functions used to truncate the database file. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); -SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); - #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); #endif @@ -11310,14 +9822,14 @@ struct PgHdr { }; /* Bit values for PgHdr.flags */ -#define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */ -#define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */ -#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */ -#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before - ** writing this page to the database */ -#define PGHDR_NEED_READ 0x010 /* Content is unread */ -#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ -#define PGHDR_MMAP 0x040 /* This is an mmap page object */ +#define PGHDR_DIRTY 0x002 /* Page has changed */ +#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before + ** writing this page to the database */ +#define PGHDR_NEED_READ 0x008 /* Content is unread */ +#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ +#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ + +#define PGHDR_MMAP 0x040 /* This is an mmap page object */ /* Initialize and shutdown the page cache subsystem */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void); @@ -11332,7 +9844,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); ** Under memory stress, invoke xStress to try to make pages clean. ** Only clean and unpinned pages can be reclaimed. */ -SQLITE_PRIVATE int sqlite3PcacheOpen( +SQLITE_PRIVATE void sqlite3PcacheOpen( int szPage, /* Size of every page */ int szExtra, /* Extra space associated with each page */ int bPurgeable, /* True if pages are on backing store */ @@ -11342,7 +9854,7 @@ SQLITE_PRIVATE int sqlite3PcacheOpen( ); /* Modify the page-size after the cache has been created. */ -SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *, int); +SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int); /* Return the size in bytes of a PCache object. Used to preallocate ** storage space. @@ -11352,9 +9864,7 @@ SQLITE_PRIVATE int sqlite3PcacheSize(void); /* One release per successful fetch. Page is pinned until released. ** Reference counted. */ -SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag); -SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**); -SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage); +SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**); SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ @@ -11410,13 +9920,6 @@ SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); #endif -/* Set or get the suggested spill-size for the specified pager-cache. -** -** The spill-size is the minimum number of pages in cache before the cache -** will attempt to spill dirty pages by calling xStress. -*/ -SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *, int); - /* Free up as much memory as possible from the page cache */ SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*); @@ -11431,10 +9934,6 @@ SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); -/* Return the header size */ -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void); -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); - #endif /* _PCACHE_H_ */ /************** End of pcache.h **********************************************/ @@ -11625,7 +10124,7 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void); ** shared locks begins at SHARED_FIRST. ** ** The same locking strategy and -** byte ranges are used for Unix. This leaves open the possibility of having +** byte ranges are used for Unix. This leaves open the possiblity of having ** clients on win95, winNT, and unix all talking to the same shared file ** and all locking correctly. To do so would require that samba (or whatever ** tool is being used for file sharing) implements locks correctly between @@ -11744,7 +10243,7 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); ** Figure out what version of the code to use. The choices are ** ** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The -** mutexes implementation cannot be overridden +** mutexes implemention cannot be overridden ** at start-time. ** ** SQLITE_MUTEX_NOOP For single-threaded applications. No @@ -11833,7 +10332,7 @@ struct Schema { Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ u8 file_format; /* Schema format version for this file */ u8 enc; /* Text encoding used by this database */ - u16 schemaFlags; /* Flags associated with this schema */ + u16 flags; /* Flags associated with this schema */ int cache_size; /* Number of pages to use in the cache */ }; @@ -11841,10 +10340,10 @@ struct Schema { ** These macros can be used to test, set, or clear bits in the ** Db.pSchema->flags field. */ -#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P)) -#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0) -#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P) -#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P) +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) /* ** Allowed values for the DB.pSchema->flags field. @@ -11864,7 +10363,7 @@ struct Schema { ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) +#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used @@ -11911,45 +10410,6 @@ struct FuncDefHash { FuncDef *a[23]; /* Hash table for functions */ }; -#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 - - /* ** Each database connection is an instance of the following structure. */ @@ -11967,7 +10427,6 @@ struct sqlite3 { int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u16 dbOptFlags; /* Flags to enable/disable optimizations */ - u8 enc; /* Text encoding */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ @@ -11981,19 +10440,16 @@ struct sqlite3 { int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ - int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ struct sqlite3InitInfo { /* Information used during initialization */ int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ - u8 imposterTable; /* Building an imposter table */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ int nVdbeWrite; /* Number of active VDBEs that read and write */ int nVdbeExec; /* Number of nested calls to VdbeExec() */ - int nVDestroy; /* Number of active OP_VDestroy operations */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ @@ -12020,7 +10476,8 @@ struct sqlite3 { } u1; Lookaside lookaside; /* Lookaside malloc configuration */ #ifndef SQLITE_OMIT_AUTHORIZATION - sqlite3_xauth xAuth; /* Access authorization function */ + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -12046,6 +10503,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() */ + #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MASTER ** mutex, not by sqlite3.mutex. They are used by code in notify.c. @@ -12063,16 +10521,12 @@ 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 }; /* ** A macro to discover the encoding of a database. */ -#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) -#define ENC(db) ((db)->enc) +#define ENC(db) ((db)->aDb[0].pSchema->enc) /* ** Possible values for the sqlite3.flags. @@ -12107,8 +10561,6 @@ struct sqlite3 { #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ -#define SQLITE_CellSizeCk 0x10000000 /* Check btree cell sizes on load */ /* @@ -12127,8 +10579,8 @@ struct sqlite3 { #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ -#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ -#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */ +#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */ +#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* @@ -12201,24 +10653,20 @@ struct FuncDestructor { /* ** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF -** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And -** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There +** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There ** are assert() statements in the code to verify this. */ -#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ -#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ -#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */ -#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */ -#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ -#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */ -#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */ -#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */ -#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */ -#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ -#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ -#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ -#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a - ** single query - might change over time */ +#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ +#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ +#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ +#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ +#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -12234,12 +10682,6 @@ struct FuncDestructor { ** VFUNCTION(zName, nArg, iArg, bNC, xFunc) ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag. ** -** DFUNCTION(zName, nArg, iArg, bNC, xFunc) -** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and -** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions -** and functions like sqlite_version() that can change, but not during -** a single query. -** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters @@ -12260,14 +10702,11 @@ struct FuncDestructor { #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} -#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ pArg, 0, xFunc, 0, 0, #zName, 0, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ @@ -12275,9 +10714,6 @@ struct FuncDestructor { #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} -#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ - {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ - SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} /* ** All current savepoints are stored in a linked list starting at @@ -12311,7 +10747,6 @@ struct Module { const char *zName; /* Name passed to create_module() */ void *pAux; /* pAux passed to create_module() */ void (*xDestroy)(void *); /* Module destructor function */ - Table *pEpoTab; /* Eponymous table for this module */ }; /* @@ -12326,7 +10761,7 @@ struct Column { char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ - u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ + u8 szEst; /* Estimated size of this column. INT==1 */ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; @@ -12357,7 +10792,6 @@ struct CollSeq { */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in ascending order */ -#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */ /* ** Column affinity types. @@ -12366,18 +10800,18 @@ struct CollSeq { ** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve ** the speed a little by numbering the values consecutively. ** -** But rather than start with 0 or 1, we begin with 'A'. That way, +** But rather than start with 0 or 1, we begin with 'a'. That way, ** when multiple affinity types are concatenated into a string and ** used as the P4 operand, they will be more readable. ** ** Note also that the numeric types are grouped together so that testing -** for a numeric type is a single comparison. And the BLOB type is first. +** for a numeric type is a single comparison. */ -#define SQLITE_AFF_BLOB 'A' -#define SQLITE_AFF_TEXT 'B' -#define SQLITE_AFF_NUMERIC 'C' -#define SQLITE_AFF_INTEGER 'D' -#define SQLITE_AFF_REAL 'E' +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) @@ -12385,7 +10819,7 @@ struct CollSeq { ** The SQLITE_AFF_MASK values masks off the significant bits of an ** affinity value. */ -#define SQLITE_AFF_MASK 0x47 +#define SQLITE_AFF_MASK 0x67 /* ** Additional bit values that can be ORed with an affinity without @@ -12396,10 +10830,10 @@ struct CollSeq { ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ -#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ -#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ -#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */ +#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in @@ -12454,8 +10888,34 @@ struct VTable { }; /* -** The schema for each SQL table and view is represented in memory -** by an instance of the following structure. +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. TF_HasPrimaryKey is set if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If TF_Ephemeral is set +** then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. */ struct Table { char *zName; /* Name of the table or view */ @@ -12464,17 +10924,15 @@ struct Table { Select *pSelect; /* NULL for tables. Points to definition if a view. */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ - /* ... also used as column name list in a VIEW */ - int tnum; /* Root BTree page for this table */ - i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ +#endif + LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ + int tnum; /* Root BTree node for this table (see note above) */ + i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ - LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ -#ifdef SQLITE_ENABLE_COSTMULT - LogEst costMult; /* Cost multiplier for using this table */ -#endif u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE @@ -12482,7 +10940,7 @@ struct Table { #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nModuleArg; /* Number of arguments to the module */ - char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */ + char **azModuleArg; /* Text of all module args. [0] is module name */ VTable *pVTable; /* List of VTable objects. */ #endif Trigger *pTrigger; /* List of triggers stored in pSchema */ @@ -12492,21 +10950,13 @@ struct Table { /* ** Allowed values for Table.tabFlags. -** -** TF_OOOHidden applies to tables or view that have hidden columns that are -** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING -** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, -** the TF_OOOHidden attribute would apply in this case. Such tables require -** special handling during INSERT processing. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ #define TF_HasPrimaryKey 0x04 /* Table has a primary key */ #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ #define TF_Virtual 0x10 /* Is a virtual table */ -#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */ -#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */ -#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */ +#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */ /* @@ -12516,31 +10966,14 @@ struct Table { */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) +# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) #else # define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 #endif -/* -** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() -** only works for non-virtual tables (ordinary tables and views) and is -** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The -** IsHiddenColumn() macro is general purpose. -*/ -#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS) -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -#elif !defined(SQLITE_OMIT_VIRTUALTABLE) -# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0) -# define IsOrdinaryHiddenColumn(X) 0 -#else -# define IsHiddenColumn(X) 0 -# define IsOrdinaryHiddenColumn(X) 0 -#endif - - /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) -#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) /* ** Each foreign key constraint is an instance of the following structure. @@ -12647,8 +11080,9 @@ struct KeyInfo { }; /* -** This object holds a record which has been parsed out into individual -** fields, for the purposes of doing a comparison. +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. ** ** A record is an object that contains one or more fields of data. ** Records are used to store the content of a table row and to store @@ -12656,40 +11090,20 @@ struct KeyInfo { ** the OP_MakeRecord opcode of the VDBE and is disassembled by the ** OP_Column opcode. ** -** An instance of this object serves as a "key" for doing a search on -** an index b+tree. The goal of the search is to find the entry that -** is closed to the key described by this object. This object might hold -** just a prefix of the key. The number of fields is given by -** pKeyInfo->nField. +** This structure holds a record that has already been disassembled +** into its constituent fields. ** -** The r1 and r2 fields are the values to return if this key is less than -** or greater than a key in the btree, respectively. These are normally -** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree -** is in DESC order. -** -** The key comparison functions actually return default_rc when they find -** an equals comparison. default_rc can be -1, 0, or +1. If there are -** multiple entries in the b-tree with the same key (when only looking -** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to -** cause the search to find the last match, or +1 to cause the search to -** find the first match. -** -** The key comparison functions will set eqSeen to true if they ever -** get and equal results when comparing this structure to a b-tree record. -** When default_rc!=0, the search might end up on the record immediately -** before the first match or immediately after the last match. The -** eqSeen field will indicate whether or not an exact match exists in the -** b-tree. +** The r1 and r2 member variables are only used by the optimized comparison +** functions vdbeRecordCompareInt() and vdbeRecordCompareString(). */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ - Mem *aMem; /* Values */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ - u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ - i8 r1; /* Value to return if (lhs > rhs) */ - i8 r2; /* Value to return if (rhs < lhs) */ - u8 eqSeen; /* True if an equality comparison has been seen */ + u8 isCorrupt; /* Corruption detected by xRecordCompare() */ + Mem *aMem; /* Values */ + int r1; /* Value to return if (lhs > rhs) */ + int r2; /* Value to return if (rhs < lhs) */ }; @@ -12718,14 +11132,6 @@ struct UnpackedRecord { ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. -** -** While parsing a CREATE TABLE or CREATE INDEX statement in order to -** generate VDBE code (as opposed to parsing one read from an sqlite_master -** table as part of parsing an existing database schema), transient instances -** of this structure may be created. In this case the Index.tnum variable is -** used to store the address of a VDBE instruction, not a database page -** number (it cannot - the database page is not allocated until the VDBE -** program is executed). See convertToWithoutRowidTable() for details. */ struct Index { char *zName; /* Name of this index */ @@ -12736,9 +11142,9 @@ struct Index { Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ - const char **azColl; /* Array of collation sequence names for index */ + char **azColl; /* Array of collation sequence names for index */ Expr *pPartIdxWhere; /* WHERE clause for partial indices */ - ExprList *aColExpr; /* Column expressions */ + KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */ int tnum; /* DB Page containing root of this index */ LogEst szIdxRow; /* Estimated average row size in bytes */ u16 nKeyCol; /* Number of columns forming the key */ @@ -12749,14 +11155,11 @@ struct Index { unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ - unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ - tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ - tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ #endif }; @@ -12770,15 +11173,6 @@ struct Index { /* Return true if index X is a PRIMARY KEY index */ #define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) -/* Return true if index X is a UNIQUE index */ -#define IsUniqueIndex(X) ((X)->onError!=OE_None) - -/* The Index.aiColumn[] values are normally positive integer. But -** there are some negative values that have special meaning: -*/ -#define XN_ROWID (-1) /* Indexed column is the rowid */ -#define XN_EXPR (-2) /* Indexed column is an expression */ - /* ** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the @@ -12960,7 +11354,7 @@ struct Expr { int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old - ** EP_Unlikely: 134217728 times likelihood */ + ** EP_Unlikely: 1000 times likelihood */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ @@ -12975,7 +11369,7 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags field. */ -#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x000008 /* Expression contains one or more errors */ @@ -12994,15 +11388,7 @@ struct Expr { #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ -#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ -#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ -#define EP_Alias 0x400000 /* Is an alias for a result set column */ - -/* -** Combinations of two or more EP_* flags -*/ -#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ +#define EP_Constant 0x080000 /* Node is a constant */ /* ** These macros can be used to test, set, or clear bits in the @@ -13160,15 +11546,11 @@ struct SrcList { int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ int regResult; /* Registers holding results of a co-routine */ - struct { - u8 jointype; /* Type of join between this able and the previous */ - unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ - unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ - unsigned isTabFunc :1; /* True if table-valued-function syntax */ - unsigned isCorrelated :1; /* True if sub-query is correlated */ - unsigned viaCoroutine :1; /* Implemented as a co-routine */ - unsigned isRecursive :1; /* True for recursive reference in WITH */ - } fg; + u8 jointype; /* Type of join between this able and the previous */ + unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ + unsigned isCorrelated :1; /* True if sub-query is correlated */ + unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ #ifndef SQLITE_OMIT_EXPLAIN u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ #endif @@ -13176,11 +11558,8 @@ struct SrcList { Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<" clause */ - ExprList *pFuncArg; /* Arguments to table-valued-function */ - } u1; - Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ + char *zIndex; /* Identifier from "INDEXED BY " clause */ + Index *pIndex; /* Index structure corresponding to zIndex, if any */ } a[1]; /* One entry for each identifier on the list */ }; @@ -13208,13 +11587,11 @@ struct SrcList { #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ -#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */ +#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */ -#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */ -#define WHERE_ONEPASS_MULTIROW 0x2000 /* ONEPASS is ok with multiple rows */ /* Allowed return values from sqlite3WhereIsDistinct() */ @@ -13252,23 +11629,17 @@ struct NameContext { NameContext *pNext; /* Next outer name context. NULL for outermost */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ - u16 ncFlags; /* Zero or more NC_* flags defined below */ + u8 ncFlags; /* Zero or more NC_* flags defined below */ }; /* ** Allowed values for the NameContext, ncFlags field. -** -** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and -** SQLITE_FUNC_MINMAX. -** */ -#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ -#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */ -#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ -#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ -#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */ -#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ -#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ +#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */ +#define NC_HasAgg 0x02 /* One or more aggregate functions seen */ +#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */ +#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ +#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */ /* ** An instance of the following structure contains all information @@ -13295,9 +11666,6 @@ struct Select { u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u16 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ -#if SELECTTRACE_ENABLED - char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ -#endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ u64 nSelectRow; /* Estimated number of result rows */ SrcList *pSrc; /* The FROM clause */ @@ -13317,21 +11685,18 @@ struct Select { ** "Select Flag". */ #define SF_Distinct 0x0001 /* Output should be DISTINCT */ -#define SF_All 0x0002 /* Includes the ALL keyword */ -#define SF_Resolved 0x0004 /* Identifiers have been resolved */ -#define SF_Aggregate 0x0008 /* Contains aggregate functions */ -#define SF_UsesEphemeral 0x0010 /* Uses the OpenEphemeral opcode */ -#define SF_Expanded 0x0020 /* sqlite3SelectExpand() called on this */ -#define SF_HasTypeInfo 0x0040 /* FROM subqueries have Table metadata */ -#define SF_Compound 0x0080 /* Part of a compound query */ -#define SF_Values 0x0100 /* Synthesized from VALUES clause */ -#define SF_MultiValue 0x0200 /* Single VALUES term with multiple rows */ -#define SF_NestedFrom 0x0400 /* Part of a parenthesized FROM clause */ -#define SF_MaybeConvert 0x0800 /* Need convertCompoundSelectToSubquery() */ -#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ -#define SF_Recursive 0x2000 /* The recursive part of a recursive CTE */ -#define SF_Converted 0x4000 /* By convertCompoundSelectToSubquery() */ -#define SF_IncludeHidden 0x8000 /* Include hidden columns in output */ +#define SF_Resolved 0x0002 /* Identifiers have been resolved */ +#define SF_Aggregate 0x0004 /* Contains aggregate functions */ +#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ +#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ +#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ + /* 0x0040 NOT USED */ +#define SF_Values 0x0080 /* Synthesized from VALUES clause */ + /* 0x0100 NOT USED */ +#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ +#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ +#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */ +#define SF_Compound 0x1000 /* Part of a compound query */ /* @@ -13483,19 +11848,9 @@ struct TriggerPrg { ** The yDbMask datatype for the bitmask of all attached databases. */ #if SQLITE_MAX_ATTACHED>30 - typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8]; -# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0) -# define DbMaskZero(M) memset((M),0,sizeof(M)) -# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7)) -# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M) -# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0) + typedef sqlite3_uint64 yDbMask; #else typedef unsigned int yDbMask; -# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0) -# define DbMaskZero(M) (M)=0 -# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I)) -# define DbMaskAllZero(M) (M)==0 -# define DbMaskNonZero(M) (M)!=0 #endif /* @@ -13536,10 +11891,9 @@ struct Parse { int nSet; /* Number of sets used so far */ int nOnce; /* Number of OP_Once instructions so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ - int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ int ckBase; /* Base register of data during check constraints */ - int iSelfTab; /* Table of an index whose exprs are being coded */ + int iPartIdxTab; /* Table corresponding to a partial index */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ int nLabel; /* Number of labels used */ @@ -13560,10 +11914,6 @@ struct Parse { int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ -#if SELECTTRACE_ENABLED - int nSelect; /* Number of SELECT statements seen */ - int nSelectIndent; /* How far to indent SELECTTRACE() output */ -#endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ @@ -13574,6 +11924,7 @@ struct Parse { Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ + int addrSkipPK; /* Address of instruction to skip PRIMARY KEY index */ 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 */ @@ -13591,6 +11942,7 @@ struct Parse { int nVar; /* Number of '?' variables seen in the SQL so far */ int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ + u8 bFreeWith; /* True if pWith should be freed with parser */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ @@ -13617,7 +11969,6 @@ struct Parse { Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ - With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* @@ -13642,17 +11993,15 @@ struct AuthContext { ** Bitfield flags for P5 value in various opcodes. */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ -#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ +#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ -#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ -#define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */ -#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ +#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ /* @@ -13711,7 +12060,7 @@ struct Trigger { * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * zTarget -> Dequoted name of the table to insert into. + * target -> A token holding the quoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... () VALUES ... @@ -13719,12 +12068,12 @@ struct Trigger { * inserted into. * * (op == TK_DELETE) - * zTarget -> Dequoted name of the table to delete from. + * target -> A token holding the quoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * zTarget -> Dequoted name of the table to update. + * target -> A token holding the quoted name of the table to update rows of. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update @@ -13736,8 +12085,8 @@ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ - Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ - char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ + Token target; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ @@ -13768,11 +12117,11 @@ struct StrAccum { sqlite3 *db; /* Optional database for lookaside. Can be NULL */ char *zBase; /* A base allocation. Not from malloc. */ char *zText; /* The string collected so far */ - u32 nChar; /* Length of the string so far */ - u32 nAlloc; /* Amount of space allocated in zText */ - u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ + int nChar; /* Length of the string so far */ + int nAlloc; /* Amount of space allocated in zText */ + int mxAlloc; /* Maximum allowed string length */ + u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ - u8 bMalloced; /* zText points to allocated space */ }; #define STRACCUM_NOMEM 1 #define STRACCUM_TOOBIG 2 @@ -13819,7 +12168,6 @@ struct Sqlite3Config { int nPage; /* Number of pages in pPage[] */ int mxParserStack; /* maximum depth of the parser stack */ int sharedCacheEnabled; /* true if shared-cache mode enabled */ - u32 szPma; /* Maximum Sorter PMA size */ /* The above might be initialized to non-zero. The following need to always ** initially be zero, however. */ int isInit; /* True after initialization has finished */ @@ -13875,14 +12223,11 @@ struct Walker { void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */ Parse *pParse; /* Parser context. */ int walkerDepth; /* Number of subqueries */ - u8 eCode; /* A small processing code */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ - int n; /* A counter */ - int iCur; /* A cursor number */ + int i; /* Integer value */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ - struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ } u; }; @@ -13892,7 +12237,6 @@ SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); -SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); /* ** Return code from the parse-tree walking primitives and their @@ -13913,21 +12257,10 @@ struct With { char *zName; /* Name of this CTE */ ExprList *pCols; /* List of explicit column names, or NULL */ Select *pSelect; /* The definition of this CTE */ - const char *zCteErr; /* Error message for circular references */ + const char *zErr; /* Error message for circular references */ } a[1]; }; -#ifdef SQLITE_DEBUG -/* -** An instance of the TreeView object is used for printing the content of -** data structures on sqlite3DebugPrintf() using a tree-like view. -*/ -struct TreeView { - int iLevel; /* Which level of the tree we are on */ - u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */ -}; -#endif /* SQLITE_DEBUG */ - /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. @@ -13955,11 +12288,11 @@ SQLITE_PRIVATE int sqlite3CantopenError(int); /* ** FTS4 is really an extension for FTS3. It is enabled using the -** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call -** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3. +** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all +** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. */ #if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) -# define SQLITE_ENABLE_FTS3 1 +# define SQLITE_ENABLE_FTS3 #endif /* @@ -13993,9 +12326,6 @@ SQLITE_PRIVATE int sqlite3CantopenError(int); # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) #endif -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_PRIVATE int sqlite3IsIdChar(u8); -#endif /* ** Internal function prototypes @@ -14006,15 +12336,15 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char*); SQLITE_PRIVATE int sqlite3MallocInit(void); SQLITE_PRIVATE void sqlite3MallocEnd(void); -SQLITE_PRIVATE void *sqlite3Malloc(u64); -SQLITE_PRIVATE void *sqlite3MallocZero(u64); -SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); -SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); +SQLITE_PRIVATE void *sqlite3Malloc(int); +SQLITE_PRIVATE void *sqlite3MallocZero(int); +SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, int); +SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, int); SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); -SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); -SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); -SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); -SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); +SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, int); +SQLITE_PRIVATE void *sqlite3Realloc(void*, int); +SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); +SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, int); SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*); SQLITE_PRIVATE int sqlite3MallocSize(void*); SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*); @@ -14023,9 +12353,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void*); SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); -#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); -#endif SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); /* @@ -14061,20 +12389,10 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int); SQLITE_PRIVATE int sqlite3MutexInit(void); SQLITE_PRIVATE int sqlite3MutexEnd(void); #endif -#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP) -SQLITE_PRIVATE void sqlite3MemoryBarrier(void); -#else -# define sqlite3MemoryBarrier() -#endif -SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int); -SQLITE_PRIVATE void sqlite3StatusUp(int, int); -SQLITE_PRIVATE void sqlite3StatusDown(int, int); -SQLITE_PRIVATE void sqlite3StatusHighwater(int, int); - -/* Access to mutexes used by sqlite3_status() */ -SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); -SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); +SQLITE_PRIVATE int sqlite3StatusValue(int); +SQLITE_PRIVATE void sqlite3StatusAdd(int, int); +SQLITE_PRIVATE void sqlite3StatusSet(int, int); #ifndef SQLITE_OMIT_FLOATING_POINT SQLITE_PRIVATE int sqlite3IsNaN(double); @@ -14098,22 +12416,37 @@ SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...); +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif -#if defined(SQLITE_DEBUG) -SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); -SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); -SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); -SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); +/* Output formatting for SQLITE_TESTCTRL_EXPLAIN */ +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) +SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe*); +SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe*, const char*, ...); +SQLITE_PRIVATE void sqlite3ExplainNL(Vdbe*); +SQLITE_PRIVATE void sqlite3ExplainPush(Vdbe*); +SQLITE_PRIVATE void sqlite3ExplainPop(Vdbe*); +SQLITE_PRIVATE void sqlite3ExplainFinish(Vdbe*); +SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe*, Select*); +SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe*, Expr*); +SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe*, ExprList*); +SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe*); +#else +# define sqlite3ExplainBegin(X) +# define sqlite3ExplainSelect(A,B) +# define sqlite3ExplainExpr(A,B) +# define sqlite3ExplainExprList(A,B) +# define sqlite3ExplainFinish(X) +# define sqlite3VdbeExplanation(X) 0 #endif -SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); +SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3Dequote(char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); @@ -14133,11 +12466,9 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); -SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -14146,18 +12477,11 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); -SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); -SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*); SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16); SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); -#if SQLITE_ENABLE_HIDDEN_COLUMNS -SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*); -#else -# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ -#endif SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*); SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); @@ -14179,14 +12503,11 @@ SQLITE_PRIVATE int sqlite3FaultSim(int); SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); -SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec*, u32); SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); -#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); -#endif SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); @@ -14194,7 +12515,7 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); -SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); +SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*); @@ -14202,9 +12523,6 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*); # define sqlite3ViewGetColumnNames(A,B) 0 #endif -#if SQLITE_MAX_ATTACHED>30 -SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); -#endif SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); @@ -14224,7 +12542,6 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*) SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*, Select*, Expr*, IdList*); SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); -SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*); SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *); SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*); SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); @@ -14255,12 +12572,7 @@ SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*); -#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ -#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ -#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ -SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); -SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); @@ -14270,19 +12582,16 @@ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); -SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); +SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ -#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); -SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *); @@ -14299,10 +12608,8 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); -#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); -#endif SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); @@ -14314,24 +12621,19 @@ SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); -SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); -SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); -#ifdef SQLITE_ENABLE_CURSOR_HINTS -SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); -#endif +SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*); SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); -SQLITE_PRIVATE void sqlite3GenerateRowDelete( - Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); -SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); +SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); +SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); -SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); +SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); @@ -14343,11 +12645,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); -#if SELECTTRACE_ENABLED -SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); -#else -# define sqlite3SelectSetName(A,B) -#endif SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); @@ -14383,7 +12680,6 @@ SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) -# define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) @@ -14393,7 +12689,6 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p -# define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 #endif @@ -14436,41 +12731,54 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c -** file. +** file. Code should use the MACRO forms below, as the Varint32 versions +** are coded to assume the single byte case is already handled (which +** the MACRO form does). */ SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64); +SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char*, u32); SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *); SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *); SQLITE_PRIVATE int sqlite3VarintLen(u64 v); /* -** The common case is for a varint to be a single byte. They following -** macros handle the common case without a procedure call, but then call -** the procedure for larger varints. +** The header of a record consists of a sequence variable-length integers. +** These integers are almost always small and are encoded as a single byte. +** The following macros take advantage this fact to provide a fast encode +** and decode of the integers in a record header. It is faster for the common +** case where the integer is a single byte. It is a little slower when the +** integer is two or more bytes. But overall it is faster. +** +** The following expressions are equivalent: +** +** x = sqlite3GetVarint32( A, &B ); +** x = sqlite3PutVarint32( A, B ); +** +** x = getVarint32( A, B ); +** x = putVarint32( A, B ); +** */ #define getVarint32(A,B) \ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) #define putVarint32(A,B) \ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ - sqlite3PutVarint((A),(B))) + sqlite3PutVarint32((A),(B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*); +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); -SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*); -SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); -SQLITE_PRIVATE void sqlite3Error(sqlite3*,int); +SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...); SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); -#if defined(SQLITE_NEED_ERR_NAME) +#if defined(SQLITE_TEST) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif @@ -14479,7 +12787,7 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); @@ -14494,7 +12802,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); #else # define sqlite3FileSuffix3(X,Y) #endif -SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8); +SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int); SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); @@ -14508,7 +12816,6 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; -SQLITE_PRIVATE const char sqlite3StrBINARY[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; SQLITE_PRIVATE const Token sqlite3IntTokens[]; @@ -14527,10 +12834,8 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); -SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); -SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); @@ -14567,10 +12872,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int); SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); -SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); +SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); @@ -14582,15 +12887,13 @@ SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void); SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*); -SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**); SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*); -SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**); #endif /* ** The interface to the LEMON-generated parser */ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); +SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t)); SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); #ifdef YYTRACKMAXSTACKDEPTH @@ -14639,8 +12942,6 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif -SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); -SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); @@ -14723,21 +13024,11 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); #define sqlite3EndBenignMalloc() #endif -/* -** Allowed return values from sqlite3FindInIndex() -*/ -#define IN_INDEX_ROWID 1 /* Search the rowid of the table */ -#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */ -#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */ -#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */ -#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */ -/* -** Allowed flags for the 3rd parameter to sqlite3FindInIndex(). -*/ -#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */ -#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */ -#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */ -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*); +#define IN_INDEX_ROWID 1 +#define IN_INDEX_EPH 2 +#define IN_INDEX_INDEX_ASC 3 +#define IN_INDEX_INDEX_DESC 4 +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); @@ -14753,11 +13044,12 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); SQLITE_PRIVATE int sqlite3MemJournalSize(void); SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *); -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 +SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p); SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *); SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); #else + #define sqlite3ExprSetHeight(x,y) #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif @@ -14787,7 +13079,7 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); #ifdef SQLITE_ENABLE_IOTRACE # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); -SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); +SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); #else # define IOTRACE(A) # define sqlite3VdbeIOTraceSql(X) @@ -14831,21 +13123,10 @@ SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ -#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ +#define MEMTYPE_LOOKASIDE 0x02 /* Might have been lookaside memory */ #define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ #define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ - -/* -** Threading interface -*/ -#if SQLITE_MAX_WORKER_THREADS>0 -SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); -#endif - -#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) -SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); -#endif +#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */ #endif /* _SQLITEINT_H_ */ @@ -14863,9 +13144,8 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); ** ************************************************************************* ** -** This file contains definitions of global variables and constants. +** This file contains definitions of global variables and contants. */ -/* #include "sqliteInt.h" */ /* An array to map all upper-case characters into their corresponding ** lower-case character. @@ -14899,16 +13179,16 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ - 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */ - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */ + 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */ + 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */ 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ - 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ - 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ + 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */ + 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */ #endif }; @@ -14982,36 +13262,14 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { }; #endif -/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards -** compatibility for legacy applications, the URI filename capability is -** disabled by default. -** -** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled -** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. -** -** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally -** disabled. The default value may be changed by compiling with the -** SQLITE_USE_URI symbol defined. -*/ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif -/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the -** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if -** that compile-time option is omitted. -*/ #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif -/* The minimum PMA size is set to this value multiplied by the database -** page size in bytes. -*/ -#ifndef SQLITE_SORTER_PMASZ -# define SQLITE_SORTER_PMASZ 250 -#endif - /* ** The following singleton contains the global configuration for ** the SQLite library. @@ -15039,10 +13297,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* nScratch */ (void*)0, /* pPage */ 0, /* szPage */ - SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */ + 0, /* nPage */ 0, /* mxParserStack */ 0, /* sharedCacheEnabled */ - SQLITE_SORTER_PMASZ, /* szPma */ /* All the rest should always be initialized to zero */ 0, /* isInit */ 0, /* inProgress */ @@ -15098,14 +13355,13 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = { ** ** IMPORTANT: Changing the pending byte to any value other than ** 0x40000000 results in an incompatible database file format! -** Changing the pending byte during operation will result in undefined -** and incorrect behavior. +** Changing the pending byte during operating results in undefined +** and dileterious behavior. */ #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif -/* #include "opcodes.h" */ /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained @@ -15114,11 +13370,6 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; -/* -** Name of the default collating sequence -*/ -SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; - /************** End of global.c **********************************************/ /************** Begin file ctime.c *******************************************/ /* @@ -15139,7 +13390,6 @@ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -/* #include "sqliteInt.h" */ /* ** An array of names of all compile-time options. This array should @@ -15156,103 +13406,88 @@ static const char * const azCompileOpt[] = { #define CTIMEOPT_VAL_(opt) #opt #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) -#if SQLITE_32BIT_ROWID +#ifdef SQLITE_32BIT_ROWID "32BIT_ROWID", #endif -#if SQLITE_4_BYTE_ALIGNED_MALLOC +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif -#if SQLITE_CASE_SENSITIVE_LIKE +#ifdef SQLITE_CASE_SENSITIVE_LIKE "CASE_SENSITIVE_LIKE", #endif -#if SQLITE_CHECK_PAGES +#ifdef SQLITE_CHECK_PAGES "CHECK_PAGES", #endif -#if SQLITE_COVERAGE_TEST +#ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif -#if SQLITE_DEBUG +#ifdef SQLITE_DEBUG "DEBUG", #endif -#if SQLITE_DEFAULT_LOCKING_MODE +#ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif -#if SQLITE_DISABLE_DIRSYNC +#ifdef SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif -#if SQLITE_DISABLE_LFS +#ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif -#if SQLITE_ENABLE_8_3_NAMES - "ENABLE_8_3_NAMES", -#endif -#if SQLITE_ENABLE_API_ARMOR - "ENABLE_API_ARMOR", -#endif -#if SQLITE_ENABLE_ATOMIC_WRITE +#ifdef SQLITE_ENABLE_ATOMIC_WRITE "ENABLE_ATOMIC_WRITE", #endif -#if SQLITE_ENABLE_CEROD +#ifdef SQLITE_ENABLE_CEROD "ENABLE_CEROD", #endif -#if SQLITE_ENABLE_COLUMN_METADATA +#ifdef SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", #endif -#if SQLITE_ENABLE_DBSTAT_VTAB - "ENABLE_DBSTAT_VTAB", -#endif -#if SQLITE_ENABLE_EXPENSIVE_ASSERT +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT "ENABLE_EXPENSIVE_ASSERT", #endif -#if SQLITE_ENABLE_FTS1 +#ifdef SQLITE_ENABLE_FTS1 "ENABLE_FTS1", #endif -#if SQLITE_ENABLE_FTS2 +#ifdef SQLITE_ENABLE_FTS2 "ENABLE_FTS2", #endif -#if SQLITE_ENABLE_FTS3 +#ifdef SQLITE_ENABLE_FTS3 "ENABLE_FTS3", #endif -#if SQLITE_ENABLE_FTS3_PARENTHESIS +#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS "ENABLE_FTS3_PARENTHESIS", #endif -#if SQLITE_ENABLE_FTS4 +#ifdef SQLITE_ENABLE_FTS4 "ENABLE_FTS4", #endif -#if SQLITE_ENABLE_FTS5 - "ENABLE_FTS5", -#endif -#if SQLITE_ENABLE_ICU +#ifdef SQLITE_ENABLE_ICU "ENABLE_ICU", #endif -#if SQLITE_ENABLE_IOTRACE +#ifdef SQLITE_ENABLE_IOTRACE "ENABLE_IOTRACE", #endif -#if SQLITE_ENABLE_JSON1 - "ENABLE_JSON1", -#endif -#if SQLITE_ENABLE_LOAD_EXTENSION +#ifdef SQLITE_ENABLE_LOAD_EXTENSION "ENABLE_LOAD_EXTENSION", #endif -#if SQLITE_ENABLE_LOCKING_STYLE +#ifdef SQLITE_ENABLE_LOCKING_STYLE "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), #endif -#if SQLITE_ENABLE_MEMORY_MANAGEMENT +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT "ENABLE_MEMORY_MANAGEMENT", #endif -#if SQLITE_ENABLE_MEMSYS3 +#ifdef SQLITE_ENABLE_MEMSYS3 "ENABLE_MEMSYS3", #endif -#if SQLITE_ENABLE_MEMSYS5 +#ifdef SQLITE_ENABLE_MEMSYS5 "ENABLE_MEMSYS5", #endif -#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK +#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif -#if SQLITE_ENABLE_RTREE +#ifdef SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif #if defined(SQLITE_ENABLE_STAT4) @@ -15260,34 +13495,31 @@ static const char * const azCompileOpt[] = { #elif defined(SQLITE_ENABLE_STAT3) "ENABLE_STAT3", #endif -#if SQLITE_ENABLE_UNLOCK_NOTIFY +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY "ENABLE_UNLOCK_NOTIFY", #endif -#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", #endif -#if SQLITE_HAS_CODEC +#ifdef SQLITE_HAS_CODEC "HAS_CODEC", #endif -#if HAVE_ISNAN || SQLITE_HAVE_ISNAN +#ifdef SQLITE_HAVE_ISNAN "HAVE_ISNAN", #endif -#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX "HOMEGROWN_RECURSIVE_MUTEX", #endif -#if SQLITE_IGNORE_AFP_LOCK_ERRORS +#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS "IGNORE_AFP_LOCK_ERRORS", #endif -#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS +#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS "IGNORE_FLOCK_LOCK_ERRORS", #endif #ifdef SQLITE_INT64_TYPE "INT64_TYPE", #endif -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - "LIKE_DOESNT_MATCH_BLOBS", -#endif -#if SQLITE_LOCK_TRACE +#ifdef SQLITE_LOCK_TRACE "LOCK_TRACE", #endif #if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc) @@ -15296,226 +13528,223 @@ static const char * const azCompileOpt[] = { #ifdef SQLITE_MAX_SCHEMA_RETRY "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), #endif -#if SQLITE_MEMDEBUG +#ifdef SQLITE_MEMDEBUG "MEMDEBUG", #endif -#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT "MIXED_ENDIAN_64BIT_FLOAT", #endif -#if SQLITE_NO_SYNC +#ifdef SQLITE_NO_SYNC "NO_SYNC", #endif -#if SQLITE_OMIT_ALTERTABLE +#ifdef SQLITE_OMIT_ALTERTABLE "OMIT_ALTERTABLE", #endif -#if SQLITE_OMIT_ANALYZE +#ifdef SQLITE_OMIT_ANALYZE "OMIT_ANALYZE", #endif -#if SQLITE_OMIT_ATTACH +#ifdef SQLITE_OMIT_ATTACH "OMIT_ATTACH", #endif -#if SQLITE_OMIT_AUTHORIZATION +#ifdef SQLITE_OMIT_AUTHORIZATION "OMIT_AUTHORIZATION", #endif -#if SQLITE_OMIT_AUTOINCREMENT +#ifdef SQLITE_OMIT_AUTOINCREMENT "OMIT_AUTOINCREMENT", #endif -#if SQLITE_OMIT_AUTOINIT +#ifdef SQLITE_OMIT_AUTOINIT "OMIT_AUTOINIT", #endif -#if SQLITE_OMIT_AUTOMATIC_INDEX +#ifdef SQLITE_OMIT_AUTOMATIC_INDEX "OMIT_AUTOMATIC_INDEX", #endif -#if SQLITE_OMIT_AUTORESET +#ifdef SQLITE_OMIT_AUTORESET "OMIT_AUTORESET", #endif -#if SQLITE_OMIT_AUTOVACUUM +#ifdef SQLITE_OMIT_AUTOVACUUM "OMIT_AUTOVACUUM", #endif -#if SQLITE_OMIT_BETWEEN_OPTIMIZATION +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION "OMIT_BETWEEN_OPTIMIZATION", #endif -#if SQLITE_OMIT_BLOB_LITERAL +#ifdef SQLITE_OMIT_BLOB_LITERAL "OMIT_BLOB_LITERAL", #endif -#if SQLITE_OMIT_BTREECOUNT +#ifdef SQLITE_OMIT_BTREECOUNT "OMIT_BTREECOUNT", #endif -#if SQLITE_OMIT_BUILTIN_TEST +#ifdef SQLITE_OMIT_BUILTIN_TEST "OMIT_BUILTIN_TEST", #endif -#if SQLITE_OMIT_CAST +#ifdef SQLITE_OMIT_CAST "OMIT_CAST", #endif -#if SQLITE_OMIT_CHECK +#ifdef SQLITE_OMIT_CHECK "OMIT_CHECK", #endif -#if SQLITE_OMIT_COMPLETE +#ifdef SQLITE_OMIT_COMPLETE "OMIT_COMPLETE", #endif -#if SQLITE_OMIT_COMPOUND_SELECT +#ifdef SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif -#if SQLITE_OMIT_CTE +#ifdef SQLITE_OMIT_CTE "OMIT_CTE", #endif -#if SQLITE_OMIT_DATETIME_FUNCS +#ifdef SQLITE_OMIT_DATETIME_FUNCS "OMIT_DATETIME_FUNCS", #endif -#if SQLITE_OMIT_DECLTYPE +#ifdef SQLITE_OMIT_DECLTYPE "OMIT_DECLTYPE", #endif -#if SQLITE_OMIT_DEPRECATED +#ifdef SQLITE_OMIT_DEPRECATED "OMIT_DEPRECATED", #endif -#if SQLITE_OMIT_DISKIO +#ifdef SQLITE_OMIT_DISKIO "OMIT_DISKIO", #endif -#if SQLITE_OMIT_EXPLAIN +#ifdef SQLITE_OMIT_EXPLAIN "OMIT_EXPLAIN", #endif -#if SQLITE_OMIT_FLAG_PRAGMAS +#ifdef SQLITE_OMIT_FLAG_PRAGMAS "OMIT_FLAG_PRAGMAS", #endif -#if SQLITE_OMIT_FLOATING_POINT +#ifdef SQLITE_OMIT_FLOATING_POINT "OMIT_FLOATING_POINT", #endif -#if SQLITE_OMIT_FOREIGN_KEY +#ifdef SQLITE_OMIT_FOREIGN_KEY "OMIT_FOREIGN_KEY", #endif -#if SQLITE_OMIT_GET_TABLE +#ifdef SQLITE_OMIT_GET_TABLE "OMIT_GET_TABLE", #endif -#if SQLITE_OMIT_INCRBLOB +#ifdef SQLITE_OMIT_INCRBLOB "OMIT_INCRBLOB", #endif -#if SQLITE_OMIT_INTEGRITY_CHECK +#ifdef SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif -#if SQLITE_OMIT_LIKE_OPTIMIZATION +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif -#if SQLITE_OMIT_LOAD_EXTENSION +#ifdef SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif -#if SQLITE_OMIT_LOCALTIME +#ifdef SQLITE_OMIT_LOCALTIME "OMIT_LOCALTIME", #endif -#if SQLITE_OMIT_LOOKASIDE +#ifdef SQLITE_OMIT_LOOKASIDE "OMIT_LOOKASIDE", #endif -#if SQLITE_OMIT_MEMORYDB +#ifdef SQLITE_OMIT_MEMORYDB "OMIT_MEMORYDB", #endif -#if SQLITE_OMIT_OR_OPTIMIZATION +#ifdef SQLITE_OMIT_OR_OPTIMIZATION "OMIT_OR_OPTIMIZATION", #endif -#if SQLITE_OMIT_PAGER_PRAGMAS +#ifdef SQLITE_OMIT_PAGER_PRAGMAS "OMIT_PAGER_PRAGMAS", #endif -#if SQLITE_OMIT_PRAGMA +#ifdef SQLITE_OMIT_PRAGMA "OMIT_PRAGMA", #endif -#if SQLITE_OMIT_PROGRESS_CALLBACK +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK "OMIT_PROGRESS_CALLBACK", #endif -#if SQLITE_OMIT_QUICKBALANCE +#ifdef SQLITE_OMIT_QUICKBALANCE "OMIT_QUICKBALANCE", #endif -#if SQLITE_OMIT_REINDEX +#ifdef SQLITE_OMIT_REINDEX "OMIT_REINDEX", #endif -#if SQLITE_OMIT_SCHEMA_PRAGMAS +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS "OMIT_SCHEMA_PRAGMAS", #endif -#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS "OMIT_SCHEMA_VERSION_PRAGMAS", #endif -#if SQLITE_OMIT_SHARED_CACHE +#ifdef SQLITE_OMIT_SHARED_CACHE "OMIT_SHARED_CACHE", #endif -#if SQLITE_OMIT_SUBQUERY +#ifdef SQLITE_OMIT_SUBQUERY "OMIT_SUBQUERY", #endif -#if SQLITE_OMIT_TCL_VARIABLE +#ifdef SQLITE_OMIT_TCL_VARIABLE "OMIT_TCL_VARIABLE", #endif -#if SQLITE_OMIT_TEMPDB +#ifdef SQLITE_OMIT_TEMPDB "OMIT_TEMPDB", #endif -#if SQLITE_OMIT_TRACE +#ifdef SQLITE_OMIT_TRACE "OMIT_TRACE", #endif -#if SQLITE_OMIT_TRIGGER +#ifdef SQLITE_OMIT_TRIGGER "OMIT_TRIGGER", #endif -#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION +#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION "OMIT_TRUNCATE_OPTIMIZATION", #endif -#if SQLITE_OMIT_UTF16 +#ifdef SQLITE_OMIT_UTF16 "OMIT_UTF16", #endif -#if SQLITE_OMIT_VACUUM +#ifdef SQLITE_OMIT_VACUUM "OMIT_VACUUM", #endif -#if SQLITE_OMIT_VIEW +#ifdef SQLITE_OMIT_VIEW "OMIT_VIEW", #endif -#if SQLITE_OMIT_VIRTUALTABLE +#ifdef SQLITE_OMIT_VIRTUALTABLE "OMIT_VIRTUALTABLE", #endif -#if SQLITE_OMIT_WAL +#ifdef SQLITE_OMIT_WAL "OMIT_WAL", #endif -#if SQLITE_OMIT_WSD +#ifdef SQLITE_OMIT_WSD "OMIT_WSD", #endif -#if SQLITE_OMIT_XFER_OPT +#ifdef SQLITE_OMIT_XFER_OPT "OMIT_XFER_OPT", #endif -#if SQLITE_PERFORMANCE_TRACE +#ifdef SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif -#if SQLITE_PROXY_DEBUG +#ifdef SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif -#if SQLITE_RTREE_INT_ONLY +#ifdef SQLITE_RTREE_INT_ONLY "RTREE_INT_ONLY", #endif -#if SQLITE_SECURE_DELETE +#ifdef SQLITE_SECURE_DELETE "SECURE_DELETE", #endif -#if SQLITE_SMALL_STACK +#ifdef SQLITE_SMALL_STACK "SMALL_STACK", #endif -#if SQLITE_SOUNDEX +#ifdef SQLITE_SOUNDEX "SOUNDEX", #endif -#if SQLITE_SYSTEM_MALLOC +#ifdef SQLITE_SYSTEM_MALLOC "SYSTEM_MALLOC", #endif -#if SQLITE_TCL +#ifdef SQLITE_TCL "TCL", #endif #if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc) "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), #endif -#if SQLITE_TEST +#ifdef SQLITE_TEST "TEST", #endif #if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #endif -#if SQLITE_USE_ALLOCA +#ifdef SQLITE_USE_ALLOCA "USE_ALLOCA", #endif -#if SQLITE_USER_AUTHENTICATION - "USER_AUTHENTICATION", -#endif -#if SQLITE_WIN32_MALLOC +#ifdef SQLITE_WIN32_MALLOC "WIN32_MALLOC", #endif -#if SQLITE_ZERO_MALLOC +#ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC" #endif }; @@ -15527,15 +13756,8 @@ static const char * const azCompileOpt[] = { ** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix ** is not required for a match. */ -SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ int i, n; - -#if SQLITE_ENABLE_API_ARMOR - if( zOptName==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; n = sqlite3Strlen30(zOptName); @@ -15543,7 +13765,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){ ** linear search is adequate. No need for a binary search. */ for(i=0; i=0 && NaDb[] (or -1) */ - u8 nullRow; /* True if pointing to a row with no data */ - u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ - u8 isTable; /* True for rowid tables. False for indexes */ -#ifdef SQLITE_DEBUG - u8 seekOp; /* Most recent seek operation on this cursor */ -#endif - Bool isEphemeral:1; /* True for an ephemeral table */ - Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ - Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ - Pgno pgnoRoot; /* Root page of the open btree cursor */ - i16 nField; /* Number of fields in the header */ - u16 nHdrParsed; /* Number of header fields parsed so far */ - union { - BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ - sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ - int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ - VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ - } uc; + BtCursor *pCursor; /* The cursor structure of the backend */ Btree *pBt; /* Separate file holding temporary table */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int seekResult; /* Result of previous sqlite3BtreeMoveto() */ + int pseudoTableReg; /* Register holding pseudotable content. */ + i16 nField; /* Number of fields in the header */ + u16 nHdrParsed; /* Number of header fields parsed so far */ + i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ + u8 nullRow; /* True if pointing to a row with no data */ + u8 rowidIsValid; /* True if lastRowid is valid */ + u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ + Bool isTable:1; /* True if a table requiring integer keys */ + Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ + sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - u64 maskUsed; /* Mask of columns used by this cursor */ -#endif + i64 lastRowid; /* Rowid being deleted by OP_Delete */ + VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ /* Cached information about the header for the data record that the ** cursor is currently pointing to. Only valid if cacheStatus matches @@ -15704,7 +13903,6 @@ struct VdbeCursor { u32 szRow; /* Byte available in aRow */ u32 iHdrOffset; /* Offset to next unparsed byte of the header */ const u8 *aRow; /* Data for the current row, if all on one page */ - u32 *aOffset; /* Pointer to aType[nField] */ u32 aType[1]; /* Type values for all entries in the record */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for @@ -15738,7 +13936,6 @@ struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ - i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ @@ -15751,8 +13948,7 @@ struct VdbeFrame { int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ - int nChange; /* Statement changes (Vdbe.nChange) */ - int nDbChange; /* Value of db->nChange */ + int nChange; /* Statement changes (Vdbe.nChanges) */ }; #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) @@ -15768,37 +13964,27 @@ struct VdbeFrame { ** integer etc.) of the same value. */ struct Mem { - union MemValue { - double r; /* Real value used when MEM_Real is set in flags */ + sqlite3 *db; /* The associated database connection */ + char *z; /* String or BLOB value */ + double r; /* Real value */ + union { i64 i; /* Integer value used when MEM_Int is set in flags */ int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; + int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ - u8 eSubtype; /* Subtype for this value */ - int n; /* Number of characters in string value, excluding '\0' */ - char *z; /* String or BLOB value */ - /* ShallowCopy only needs to copy the information above */ - char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ - int szMalloc; /* Size of the zMalloc allocation */ - u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ - sqlite3 *db; /* The associated database connection */ - void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ #endif + void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ + char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ }; -/* -** Size of struct Mem not including the Mem.zMalloc member or anything that -** follows. -*/ -#define MEMCELLSIZE offsetof(Mem,zMalloc) - /* One or more of the following flags are set to indicate the validOK ** representations of the value stored in the Mem struct. ** @@ -15855,7 +14041,7 @@ struct Mem { #endif /* -** Each auxiliary data pointer stored by a user defined function +** Each auxilliary data pointer stored by a user defined function ** implementation calling sqlite3_set_auxdata() is stored in an instance ** of this structure. All such structures associated with a single VM ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed @@ -15870,7 +14056,7 @@ struct AuxData { }; /* -** The "context" argument for an installable function. A pointer to an +** The "context" argument for a installable function. A pointer to an ** instance of this structure is the first argument to the routines used ** implement the SQL functions. ** @@ -15883,16 +14069,15 @@ struct AuxData { ** (Mem) which are only defined there. */ struct sqlite3_context { - Mem *pOut; /* The return value is stored here */ - FuncDef *pFunc; /* Pointer to function information */ - Mem *pMem; /* Memory cell used to store aggregate context */ - Vdbe *pVdbe; /* The VM that owns this context */ - int iOp; /* Instruction number of OP_Function */ - int isError; /* Error code returned by the function. */ - u8 skipFlag; /* Skip accumulator loading if true */ - u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ - u8 argc; /* Number of arguments */ - sqlite3_value *argv[1]; /* Argument set */ + FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ + Mem s; /* The return value is stored here */ + Mem *pMem; /* Memory cell used to store aggregate context */ + CollSeq *pColl; /* Collating sequence */ + Vdbe *pVdbe; /* The VM that owns this context */ + int iOp; /* Instruction number of OP_Function */ + int isError; /* Error code returned by the function. */ + u8 skipFlag; /* Skip skip accumulator loading if true */ + u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ }; /* @@ -15912,22 +14097,20 @@ struct Explain { */ typedef unsigned bft; /* Bit Field Type */ -typedef struct ScanStatus ScanStatus; -struct ScanStatus { - int addrExplain; /* OP_Explain for loop */ - int addrLoop; /* Address of "loops" counter */ - int addrVisit; /* Address of "rows visited" counter */ - int iSelectID; /* The "Select-ID" for this loop */ - LogEst nEst; /* Estimated output rows per loop */ - char *zName; /* Name of table or index */ -}; - /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. +** +** The Vdbe.inVtabMethod variable is set to non-zero for the duration of +** any virtual table method invocations made by the vdbe program. It is +** set to 2 for xDestroy method calls and 1 for all other methods. This +** variable is used for two purposes: to allow xDestroy methods to execute +** "DROP TABLE" statements and to prevent some nasty side effects of +** malloc failure when SQLite is invoked recursively by a virtual table +** method function. */ struct Vdbe { sqlite3 *db; /* The database connection that owns this statement */ @@ -15951,13 +14134,11 @@ struct Vdbe { u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ -#ifdef SQLITE_DEBUG - int rcApp; /* errcode set by sqlite3_result_error_code() */ -#endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ + bft inVtabMethod:2; /* See comments above */ bft changeCntOn:1; /* True to update the change-counter */ bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ @@ -15980,6 +14161,10 @@ struct Vdbe { i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ +#ifdef SQLITE_ENABLE_TREE_EXPLAIN + Explain *pExplain; /* The explainer */ + char *zExplain; /* Explanation of data structures */ +#endif VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ int nFrame; /* Number of frames in pFrame list */ @@ -15988,11 +14173,6 @@ struct Vdbe { int nOnceFlag; /* Size of array aOnceFlag[] */ u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - i64 *anExec; /* Number of times each op has been executed */ - int nScan; /* Entries in aScan[] */ - ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ -#endif }; /* @@ -16006,24 +14186,22 @@ struct Vdbe { /* ** Function prototypes */ -SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); -SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); -SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); -SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*); +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); -SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); +SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); +SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); @@ -16040,39 +14218,39 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif -SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); +SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); -SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); +SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p); #define VdbeMemDynamic(X) \ (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) +#define VdbeMemRelease(X) \ + if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); -SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); -SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); +SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); -SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); -SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); +SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *); +SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 @@ -16117,34 +14295,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *); /* ** Variables in which to record status information. */ -#if SQLITE_PTRSIZE>4 -typedef sqlite3_int64 sqlite3StatValueType; -#else -typedef u32 sqlite3StatValueType; -#endif typedef struct sqlite3StatType sqlite3StatType; static SQLITE_WSD struct sqlite3StatType { - sqlite3StatValueType nowValue[10]; /* Current value */ - sqlite3StatValueType mxValue[10]; /* Maximum value */ + int nowValue[10]; /* Current value */ + int mxValue[10]; /* Maximum value */ } sqlite3Stat = { {0,}, {0,} }; -/* -** Elements of sqlite3Stat[] are protected by either the memory allocator -** mutex, or by the pcache1 mutex. The following array determines which. -*/ -static const char statMutex[] = { - 0, /* SQLITE_STATUS_MEMORY_USED */ - 1, /* SQLITE_STATUS_PAGECACHE_USED */ - 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ - 0, /* SQLITE_STATUS_SCRATCH_USED */ - 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ - 0, /* SQLITE_STATUS_MALLOC_SIZE */ - 0, /* SQLITE_STATUS_PARSER_STACK */ - 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ - 0, /* SQLITE_STATUS_SCRATCH_SIZE */ - 0, /* SQLITE_STATUS_MALLOC_COUNT */ -}; - /* The "wsdStat" macro will resolve to the status information ** state vector. If writable static data is unsupported on the target, @@ -16161,118 +14317,63 @@ static const char statMutex[] = { #endif /* -** Return the current value of a status parameter. The caller must -** be holding the appropriate mutex. +** Return the current value of a status parameter. */ -SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){ +SQLITE_PRIVATE int sqlite3StatusValue(int op){ wsdStatInit; assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } } -SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){ - wsdStatInit; - assert( N>=0 ); - assert( op>=0 && op=0 && op=0 ); - newValue = (sqlite3StatValueType)X; assert( op>=0 && op=0 && opwsdStat.mxValue[op] ){ - wsdStat.mxValue[op] = newValue; + wsdStat.nowValue[op] = X; + if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ + wsdStat.mxValue[op] = wsdStat.nowValue[op]; } } /* ** Query status information. +** +** This implementation assumes that reading or writing an aligned +** 32-bit integer is an atomic operation. If that assumption is not true, +** then this routine is not threadsafe. */ -SQLITE_API int SQLITE_STDCALL sqlite3_status64( - int op, - sqlite3_int64 *pCurrent, - sqlite3_int64 *pHighwater, - int resetFlag -){ - sqlite3_mutex *pMutex; +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ wsdStatInit; if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ return SQLITE_MISUSE_BKPT; } -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; -#endif - pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); - sqlite3_mutex_enter(pMutex); *pCurrent = wsdStat.nowValue[op]; *pHighwater = wsdStat.mxValue[op]; if( resetFlag ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } - sqlite3_mutex_leave(pMutex); - (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ - sqlite3_int64 iCur, iHwtr; - int rc; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; -#endif - rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); - if( rc==0 ){ - *pCurrent = (int)iCur; - *pHighwater = (int)iHwtr; - } - return rc; -} /* ** Query status information for a single database connection */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_status( +SQLITE_API int sqlite3_db_status( sqlite3 *db, /* The database connection whose status is desired */ int op, /* Status verb */ int *pCurrent, /* Write current value here */ @@ -16280,11 +14381,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( int resetFlag /* Reset high-water mark if true */ ){ int rc = SQLITE_OK; /* Return code */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif sqlite3_mutex_enter(db->mutex); switch( op ){ case SQLITE_DBSTATUS_LOOKASIDE_USED: { @@ -16356,10 +14452,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( + pSchema->idxHash.count + pSchema->fkeyHash.count ); - nByte += sqlite3_msize(pSchema->tblHash.ht); - nByte += sqlite3_msize(pSchema->trigHash.ht); - nByte += sqlite3_msize(pSchema->idxHash.ht); - nByte += sqlite3_msize(pSchema->fkeyHash.ht); + nByte += sqlite3MallocSize(pSchema->tblHash.ht); + nByte += sqlite3MallocSize(pSchema->trigHash.ht); + nByte += sqlite3MallocSize(pSchema->idxHash.ht); + nByte += sqlite3MallocSize(pSchema->fkeyHash.ht); for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); @@ -16393,7 +14489,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( } db->pnBytesFreed = 0; - *pHighwater = 0; /* IMP: R-64479-57858 */ + *pHighwater = 0; *pCurrent = nByte; break; @@ -16418,9 +14514,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet); } } - *pHighwater = 0; /* IMP: R-42420-56072 */ - /* IMP: R-54100-20147 */ - /* IMP: R-29431-39229 */ + *pHighwater = 0; *pCurrent = nRet; break; } @@ -16430,7 +14524,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( ** have been satisfied. The *pHighwater is always set to zero. */ case SQLITE_DBSTATUS_DEFERRED_FKS: { - *pHighwater = 0; /* IMP: R-11967-56545 */ + *pHighwater = 0; *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; break; } @@ -16463,7 +14557,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** SQLite processes all times and dates as julian day numbers. The +** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. @@ -16471,14 +14565,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( ** 1970-01-01 00:00:00 is JD 2440587.5 ** 2000-01-01 00:00:00 is JD 2451544.5 ** -** This implementation requires years to be expressed as a 4-digit number +** This implemention requires years to be expressed as a 4-digit number ** which means that only dates between 0000-01-01 and 9999-12-31 can ** be represented, even though julian day numbers allow a much wider ** range of dates. ** ** The Gregorian calendar system is used for all dates and times, ** even those that predate the Gregorian calendar. Historians usually -** use the julian calendar for dates prior to 1582-10-15 and for some +** use the Julian calendar for dates prior to 1582-10-15 and for some ** dates afterwards, depending on locale. Beware of this difference. ** ** The conversion algorithms are implemented based on descriptions @@ -16490,7 +14584,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status( ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ -/* #include "sqliteInt.h" */ /* #include */ /* #include */ #include @@ -16512,7 +14605,6 @@ struct DateTime { char validHMS; /* True (1) if h,m,s are valid */ char validJD; /* True (1) if iJD is valid */ char validTZ; /* True (1) if tz is valid */ - char tzSet; /* Timezone was set explicitly */ }; @@ -16606,7 +14698,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; } @@ -16753,7 +14844,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ } /* -** Attempt to parse the given string into a julian day number. Return +** Attempt to parse the given string into a Julian Day Number. Return ** the number of errors. ** ** The following are acceptable forms for the input string: @@ -16804,7 +14895,7 @@ static void computeYMD(DateTime *p){ A = Z + 1 + A - (A/4); B = A + 1524; C = (int)((B - 122.1)/365.25); - D = (36525*(C&32767))/100; + D = (36525*C)/100; E = (int)((B-D)/30.6001); X1 = (int)(30.6001*E); p->D = B - D - X1; @@ -16861,9 +14952,8 @@ static void clearYMD_HMS_TZ(DateTime *p){ ** already, check for an MSVC build environment that provides ** localtime_s(). */ -#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \ - && defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) -#undef HAVE_LOCALTIME_S +#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \ + defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) #define HAVE_LOCALTIME_S 1 #endif @@ -16883,7 +14973,8 @@ static void clearYMD_HMS_TZ(DateTime *p){ */ static int osLocaltime(time_t *t, struct tm *pTm){ int rc; -#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S +#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \ + && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S) struct tm *pX; #if SQLITE_THREADSAFE>0 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); @@ -16900,7 +14991,7 @@ static int osLocaltime(time_t *t, struct tm *pTm){ #ifndef SQLITE_OMIT_BUILTIN_TEST if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif -#if HAVE_LOCALTIME_R +#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; #else rc = localtime_s(pTm, t); @@ -17039,18 +15130,13 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ } #ifndef SQLITE_OMIT_LOCALTIME else if( strcmp(z, "utc")==0 ){ - if( p->tzSet==0 ){ - sqlite3_int64 c1; - computeJD(p); - c1 = localtimeOffset(p, pCtx, &rc); - if( rc==SQLITE_OK ){ - p->iJD -= c1; - clearYMD_HMS_TZ(p); - p->iJD += c1 - localtimeOffset(p, pCtx, &rc); - } - p->tzSet = 1; - }else{ - rc = SQLITE_OK; + sqlite3_int64 c1; + computeJD(p); + c1 = localtimeOffset(p, pCtx, &rc); + if( rc==SQLITE_OK ){ + p->iJD -= c1; + clearYMD_HMS_TZ(p); + p->iJD += c1 - localtimeOffset(p, pCtx, &rc); } } #endif @@ -17329,7 +15415,7 @@ static void dateFunc( ** %f ** fractional seconds SS.SSS ** %H hour 00-24 ** %j day of year 000-366 -** %J ** julian day number +** %J ** Julian day number ** %m month 01-12 ** %M minute 00-59 ** %s seconds since 1970-01-01 @@ -17349,10 +15435,8 @@ static void strftimeFunc( size_t i,j; char *z; sqlite3 *db; - const char *zFmt; + const char *zFmt = (const char*)sqlite3_value_text(argv[0]); char zBuf[100]; - if( argc==0 ) return; - zFmt = (const char*)sqlite3_value_text(argv[0]); if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; db = sqlite3_context_db_handle(context); for(i=0, n=1; zFmt[i]; i++, n++){ @@ -17546,7 +15630,7 @@ static void currentTimeFunc( iT = sqlite3StmtCurrentTime(context); if( iT<=0 ) return; t = iT/1000 - 10000*(sqlite3_int64)21086676; -#if HAVE_GMTIME_R +#ifdef HAVE_GMTIME_R pTm = gmtime_r(&t, &sNow); #else sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); @@ -17569,14 +15653,14 @@ static void currentTimeFunc( SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ static SQLITE_WSD FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS - DFUNCTION(julianday, -1, 0, 0, juliandayFunc ), - DFUNCTION(date, -1, 0, 0, dateFunc ), - DFUNCTION(time, -1, 0, 0, timeFunc ), - DFUNCTION(datetime, -1, 0, 0, datetimeFunc ), - DFUNCTION(strftime, -1, 0, 0, strftimeFunc ), - DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), - DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), - DFUNCTION(current_date, 0, 0, 0, cdateFunc ), + FUNCTION(julianday, -1, 0, 0, juliandayFunc ), + FUNCTION(date, -1, 0, 0, dateFunc ), + FUNCTION(time, -1, 0, 0, timeFunc ), + FUNCTION(datetime, -1, 0, 0, datetimeFunc ), + FUNCTION(strftime, -1, 0, 0, strftimeFunc ), + FUNCTION(current_time, 0, 0, 0, ctimeFunc ), + FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), + FUNCTION(current_date, 0, 0, 0, cdateFunc ), #else STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), @@ -17610,7 +15694,6 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ ** architectures. */ #define _SQLITE_OS_C_ 1 -/* #include "sqliteInt.h" */ #undef _SQLITE_OS_C_ /* @@ -17905,7 +15988,7 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0; ** Locate a VFS by name. If no name is given, simply return the ** first VFS on the list. */ -SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ sqlite3_vfs *pVfs = 0; #if SQLITE_THREADSAFE sqlite3_mutex *mutex; @@ -17951,16 +16034,12 @@ static void vfsUnlink(sqlite3_vfs *pVfs){ ** VFS multiple times. The new VFS becomes the default if makeDflt is ** true. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ MUTEX_LOGIC(sqlite3_mutex *mutex;) #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return rc; #endif -#ifdef SQLITE_ENABLE_API_ARMOR - if( pVfs==0 ) return SQLITE_MISUSE_BKPT; -#endif - MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); @@ -17979,7 +16058,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDf /* ** Unregister a VFS so that it is no longer accessible. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -18017,7 +16096,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ ** during a hash table resize is a benign fault. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_BUILTIN_TEST @@ -18099,7 +16177,6 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ ** are merely placeholders. Real drivers must be substituted using ** sqlite3_config() before SQLite will operate. */ -/* #include "sqliteInt.h" */ /* ** This version of the memory allocator is the default. It is @@ -18186,7 +16263,6 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ ** be necessary when compiling for Delphi, ** for example. */ -/* #include "sqliteInt.h" */ /* ** This version of the memory allocator is the default. It is @@ -18224,9 +16300,9 @@ static malloc_zone_t* _sqliteZone_; ** The malloc.h header file is needed for malloc_usable_size() function ** on some systems (e.g. Linux). */ -#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE -# define SQLITE_USE_MALLOC_H 1 -# define SQLITE_USE_MALLOC_USABLE_SIZE 1 +#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE) +# define SQLITE_USE_MALLOC_H +# define SQLITE_USE_MALLOC_USABLE_SIZE /* ** The MSVCRT has malloc_usable_size(), but it is called _msize(). The ** use of _msize() is automatic, but can be disabled by compiling with @@ -18317,11 +16393,10 @@ static void sqlite3MemFree(void *pPrior){ */ static int sqlite3MemSize(void *pPrior){ #ifdef SQLITE_MALLOCSIZE - assert( pPrior!=0 ); - return (int)SQLITE_MALLOCSIZE(pPrior); + return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0; #else sqlite3_int64 *p; - assert( pPrior!=0 ); + if( pPrior==0 ) return 0; p = (sqlite3_int64*)pPrior; p--; return (int)p[0]; @@ -18334,7 +16409,7 @@ static int sqlite3MemSize(void *pPrior){ ** ** For this low-level interface, we know that pPrior!=0. Cases where ** pPrior==0 while have been intercepted by higher-level routine and -** redirected to xMalloc. Similarly, we know that nByte>0 because +** redirected to xMalloc. Similarly, we know that nByte>0 becauses ** cases where nByte<=0 will have been intercepted by higher-level ** routines and redirected to xFree. */ @@ -18463,7 +16538,6 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. */ -/* #include "sqliteInt.h" */ /* ** This version of the memory allocator is used only if the @@ -18838,7 +16912,7 @@ SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** -** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); +** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); */ SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){ int rc = 1; @@ -18860,7 +16934,7 @@ SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){ ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** -** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); +** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); */ SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){ int rc = 1; @@ -18998,7 +17072,6 @@ SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){ ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS3 is defined. */ -/* #include "sqliteInt.h" */ /* ** This version of the memory allocator is only built into the library @@ -19451,7 +17524,7 @@ static void memsys3FreeUnsafe(void *pOld){ */ static int memsys3Size(void *p){ Mem3Block *pBlock; - assert( p!=0 ); + if( p==0 ) return 0; pBlock = (Mem3Block*)p; assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; @@ -19690,10 +17763,10 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ ** ** This memory allocator uses the following algorithm: ** -** 1. All memory allocation sizes are rounded up to a power of 2. +** 1. All memory allocations sizes are rounded up to a power of 2. ** ** 2. If two adjacent free blocks are the halves of a larger block, -** then the two blocks are coalesced into the single larger block. +** then the two blocks are coalesed into the single larger block. ** ** 3. New memory is allocated from the first available free block. ** @@ -19713,7 +17786,6 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ ** The sqlite3_status() logic tracks the maximum values of n and M so ** that an application can, at any time, verify this constraint. */ -/* #include "sqliteInt.h" */ /* ** This version of the memory allocator is used only when @@ -19782,7 +17854,7 @@ static SQLITE_WSD struct Mem5Global { /* ** Lists of free blocks. aiFreelist[0] is a list of free blocks of ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2. - ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth. + ** and so forth. */ int aiFreelist[LOGMAX+1]; @@ -19848,7 +17920,9 @@ static void memsys5Link(int i, int iLogsize){ } /* -** Obtain or release the mutex needed to access global data structures. +** If the STATIC_MEM mutex is not already held, obtain it now. The mutex +** will already be held (obtained by code in malloc.c) if +** sqlite3GlobalConfig.bMemStat is true. */ static void memsys5Enter(void){ sqlite3_mutex_enter(mem5.mutex); @@ -19858,15 +17932,17 @@ static void memsys5Leave(void){ } /* -** Return the size of an outstanding allocation, in bytes. -** This only works for chunks that are currently checked out. +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. */ static int memsys5Size(void *p){ - int iSize, i; - assert( p!=0 ); - i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom); - assert( i>=0 && i=0 && imem5.maxRequest ){ - /* Abort if the requested allocation size is larger than the largest - ** power of two that we can represent using 32-bit signed integers. */ - if( nByte > 0x40000000 ) return 0; mem5.maxRequest = nByte; } + /* Abort if the requested allocation size is larger than the largest + ** power of two that we can represent using 32-bit signed integers. + */ + if( nByte > 0x40000000 ){ + return 0; + } + /* Round nByte up to the next valid power of two */ - for(iFullSz=mem5.szAtom,iLogsize=0; iFullSzxMutexInit = pFrom->xMutexInit; - pTo->xMutexEnd = pFrom->xMutexEnd; - pTo->xMutexFree = pFrom->xMutexFree; - pTo->xMutexEnter = pFrom->xMutexEnter; - pTo->xMutexTry = pFrom->xMutexTry; - pTo->xMutexLeave = pFrom->xMutexLeave; - pTo->xMutexHeld = pFrom->xMutexHeld; - pTo->xMutexNotheld = pFrom->xMutexNotheld; - sqlite3MemoryBarrier(); + memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc)); + memcpy(&pTo->xMutexFree, &pFrom->xMutexFree, + sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree)); pTo->xMutexAlloc = pFrom->xMutexAlloc; } - assert( sqlite3GlobalConfig.mutex.xMutexInit ); rc = sqlite3GlobalConfig.mutex.xMutexInit(); #ifdef SQLITE_DEBUG @@ -20320,12 +18394,10 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){ /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ #ifndef SQLITE_OMIT_AUTOINIT - if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; - if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; + if( sqlite3_initialize() ) return 0; #endif - assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); return sqlite3GlobalConfig.mutex.xMutexAlloc(id); } @@ -20334,16 +18406,14 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){ return 0; } assert( GLOBAL(int, mutexIsInit) ); - assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); return sqlite3GlobalConfig.mutex.xMutexAlloc(id); } /* ** Free a dynamic mutex. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){ if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexFree ); sqlite3GlobalConfig.mutex.xMutexFree(p); } } @@ -20352,9 +18422,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){ ** Obtain the mutex p. If some other thread already has the mutex, block ** until it can be obtained. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){ if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexEnter ); sqlite3GlobalConfig.mutex.xMutexEnter(p); } } @@ -20363,10 +18432,9 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){ ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){ int rc = SQLITE_OK; if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexTry ); return sqlite3GlobalConfig.mutex.xMutexTry(p); } return rc; @@ -20378,9 +18446,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){ ** is not currently entered. If a NULL pointer is passed as an argument ** this function is a no-op. */ -SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){ if( p ){ - assert( sqlite3GlobalConfig.mutex.xMutexLeave ); sqlite3GlobalConfig.mutex.xMutexLeave(p); } } @@ -20390,12 +18457,10 @@ SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){ ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){ - assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); } -SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ - assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); } #endif @@ -20431,7 +18496,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){ ** that does error checking on mutexes to make sure they are being ** called correctly. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_MUTEX_OMIT @@ -20513,7 +18577,7 @@ static int debugMutexEnd(void){ return SQLITE_OK; } ** that means that a mutex could not be allocated. */ static sqlite3_mutex *debugMutexAlloc(int id){ - static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; + static sqlite3_debug_mutex aStatic[6]; sqlite3_debug_mutex *pNew = 0; switch( id ){ case SQLITE_MUTEX_FAST: @@ -20526,12 +18590,8 @@ static sqlite3_mutex *debugMutexAlloc(int id){ break; } default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( id-2<0 || id-2>=ArraySize(aStatic) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif + assert( id-2 >= 0 ); + assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) ); pNew = &aStatic[id-2]; pNew->id = id; break; @@ -20546,13 +18606,8 @@ static sqlite3_mutex *debugMutexAlloc(int id){ static void debugMutexFree(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( p->cnt==0 ); - if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ - sqlite3_free(p); - }else{ -#ifdef SQLITE_ENABLE_API_ARMOR - (void)SQLITE_MISUSE_BKPT; -#endif - } + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + sqlite3_free(p); } /* @@ -20635,7 +18690,6 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads */ -/* #include "sqliteInt.h" */ /* ** The code in this file is only used if we are compiling threadsafe @@ -20664,19 +18718,15 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - int id; /* Mutex type */ -#endif #if SQLITE_MUTEX_NREF + int id; /* Mutex type */ volatile int nRef; /* Number of entrances */ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ #endif }; #if SQLITE_MUTEX_NREF -#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0} -#elif defined(SQLITE_ENABLE_API_ARMOR) -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 } +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } #else #define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } #endif @@ -20706,19 +18756,6 @@ static int pthreadMutexNotheld(sqlite3_mutex *p){ } #endif -/* -** Try to provide a memory barrier operation, needed for initialization -** and also for the implementation of xShmBarrier in the VFS in cases -** where SQLite is compiled without mutexes. -*/ -SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ -#if defined(SQLITE_MEMORY_BARRIER) - SQLITE_MEMORY_BARRIER; -#elif defined(__GNUC__) && GCC_VERSION>=4001000 - __sync_synchronize(); -#endif -} - /* ** Initialize and deinitialize the mutex subsystem. */ @@ -20737,16 +18774,10 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; } **
  • SQLITE_MUTEX_RECURSIVE **
  • SQLITE_MUTEX_STATIC_MASTER **
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU **
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 ** ** ** The first two constants cause sqlite3_mutex_alloc() to create @@ -20775,12 +18806,6 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; } */ static sqlite3_mutex *pthreadMutexAlloc(int iType){ static sqlite3_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, @@ -20804,6 +18829,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); +#endif +#if SQLITE_MUTEX_NREF + p->id = iType; #endif } break; @@ -20811,24 +18839,23 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ +#if SQLITE_MUTEX_NREF + p->id = iType; +#endif pthread_mutex_init(&p->mutex, 0); } break; } default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif + assert( iType-2 >= 0 ); + assert( iType-2 < ArraySize(staticMutexes) ); p = &staticMutexes[iType-2]; +#if SQLITE_MUTEX_NREF + p->id = iType; +#endif break; } } -#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - if( p ) p->id = iType; -#endif return p; } @@ -20840,18 +18867,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); -#if SQLITE_ENABLE_API_ARMOR - if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) -#endif - { - pthread_mutex_destroy(&p->mutex); - sqlite3_free(p); - } -#ifdef SQLITE_ENABLE_API_ARMOR - else{ - (void)SQLITE_MISUSE_BKPT; - } -#endif + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); } /* @@ -21023,214 +19041,10 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains the C functions that implement mutexes for Win32. +** This file contains the C functions that implement mutexes for win32 */ -/* #include "sqliteInt.h" */ #if SQLITE_OS_WIN -/* -** Include code that is common to all os_*.c files -*/ -/************** Include os_common.h in the middle of mutex_w32.c *************/ -/************** Begin file os_common.h ***************************************/ -/* -** 2004 May 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains macros and a little bit of code that is common to -** all of the platform-specific files (os_*.c) and is #included into those -** files. -** -** This file should be #included by the os_*.c files only. It is not a -** general purpose header file. -*/ -#ifndef _OS_COMMON_H_ -#define _OS_COMMON_H_ - -/* -** At least two bugs have slipped in because we changed the MEMORY_DEBUG -** macro to SQLITE_DEBUG and some older makefiles have not yet made the -** switch. The following code should catch this problem at compile-time. -*/ -#ifdef MEMORY_DEBUG -# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." -#endif - -/* -** Macros for performance tracing. Normally turned off. Only works -** on i486 hardware. -*/ -#ifdef SQLITE_PERFORMANCE_TRACE - -/* -** hwtime.h contains inline assembler code for implementing -** high-performance timing routines. -*/ -/************** Include hwtime.h in the middle of os_common.h ****************/ -/************** Begin file hwtime.h ******************************************/ -/* -** 2008 May 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains inline asm code for retrieving "high-performance" -** counters for x86 class CPUs. -*/ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ - -/* -** The following routine only works on pentium-class (or newer) processors. -** It uses the RDTSC opcode to read the cycle count value out of the -** processor and returns that value. This can be used for high-res -** profiling. -*/ -#if (defined(__GNUC__) || defined(_MSC_VER)) && \ - (defined(i386) || defined(__i386__) || defined(_M_IX86)) - - #if defined(__GNUC__) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - - #elif defined(_MSC_VER) - - __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ - __asm { - rdtsc - ret ; return value at EDX:EAX - } - } - - #endif - -#elif (defined(__GNUC__) && defined(__x86_64__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long val; - __asm__ __volatile__ ("rdtsc" : "=A" (val)); - return val; - } - -#elif (defined(__GNUC__) && defined(__ppc__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long long retval; - unsigned long junk; - __asm__ __volatile__ ("\n\ - 1: mftbu %1\n\ - mftb %L0\n\ - mftbu %0\n\ - cmpw %0,%1\n\ - bne 1b" - : "=r" (retval), "=r" (junk)); - return retval; - } - -#else - - #error Need implementation of sqlite3Hwtime() for your platform. - - /* - ** To compile without implementing sqlite3Hwtime() for your platform, - ** you can remove the above #error and use the following - ** stub function. You will lose timing support for many - ** of the debugging and testing utilities, but it should at - ** least compile and run. - */ -SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } - -#endif - -#endif /* !defined(_HWTIME_H_) */ - -/************** End of hwtime.h **********************************************/ -/************** Continuing where we left off in os_common.h ******************/ - -static sqlite_uint64 g_start; -static sqlite_uint64 g_elapsed; -#define TIMER_START g_start=sqlite3Hwtime() -#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start -#define TIMER_ELAPSED g_elapsed -#else -#define TIMER_START -#define TIMER_END -#define TIMER_ELAPSED ((sqlite_uint64)0) -#endif - -/* -** If we compile with the SQLITE_TEST macro set, then the following block -** of code will give us the ability to simulate a disk I/O error. This -** is used for testing the I/O recovery logic. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ -SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ -SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ -SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ -SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ -SQLITE_API int sqlite3_diskfull_pending = 0; -SQLITE_API int sqlite3_diskfull = 0; -#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) -#define SimulateIOError(CODE) \ - if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ - || sqlite3_io_error_pending-- == 1 ) \ - { local_ioerr(); CODE; } -static void local_ioerr(){ - IOTRACE(("IOERR\n")); - sqlite3_io_error_hit++; - if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; -} -#define SimulateDiskfullError(CODE) \ - if( sqlite3_diskfull_pending ){ \ - if( sqlite3_diskfull_pending == 1 ){ \ - local_ioerr(); \ - sqlite3_diskfull = 1; \ - sqlite3_io_error_hit = 1; \ - CODE; \ - }else{ \ - sqlite3_diskfull_pending--; \ - } \ - } -#else -#define SimulateIOErrorBenign(X) -#define SimulateIOError(A) -#define SimulateDiskfullError(A) -#endif - -/* -** When testing, keep a count of the number of open files. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_open_file_count = 0; -#define OpenCounter(X) sqlite3_open_file_count+=(X) -#else -#define OpenCounter(X) -#endif - -#endif /* !defined(_OS_COMMON_H_) */ - -/************** End of os_common.h *******************************************/ -/************** Continuing where we left off in mutex_w32.c ******************/ - /* ** Include the header file for the Windows VFS. */ @@ -21302,27 +19116,6 @@ SQLITE_API int sqlite3_open_file_count = 0; # define SQLITE_OS_WINRT 0 #endif -/* -** For WinCE, some API function parameters do not appear to be declared as -** volatile. -*/ -#if SQLITE_OS_WINCE -# define SQLITE_WIN32_VOLATILE -#else -# define SQLITE_WIN32_VOLATILE volatile -#endif - -/* -** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() -** functions are not available (e.g. those not using MSVC, Cygwin, etc). -*/ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ - SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) -# define SQLITE_OS_WIN_THREADS 1 -#else -# define SQLITE_OS_WIN_THREADS 0 -#endif - #endif /* _OS_WIN_H_ */ /************** End of os_win.h **********************************************/ @@ -21331,7 +19124,7 @@ SQLITE_API int sqlite3_open_file_count = 0; /* ** The code in this file is only used if we are compiling multithreaded -** on a Win32 system. +** on a win32 system. */ #ifdef SQLITE_MUTEX_W32 @@ -21344,24 +19137,50 @@ struct sqlite3_mutex { #ifdef SQLITE_DEBUG volatile int nRef; /* Number of enterances */ volatile DWORD owner; /* Thread holding this mutex */ - volatile int trace; /* True to trace changes */ + int trace; /* True to trace changes */ #endif }; - -/* -** These are the initializer values used when declaring a "static" mutex -** on Win32. It should be noted that all mutexes require initialization -** on the Win32 platform. -*/ #define SQLITE_W32_MUTEX_INITIALIZER { 0 } - #ifdef SQLITE_DEBUG -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ - 0L, (DWORD)0, 0 } +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } #else #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } #endif +/* +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +** +** mutexIsNT() is only used for the TryEnterCriticalSection() API call, +** which is only available if your application was compiled with +** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only +** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef +** this out as well. +*/ +#if 0 +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT +# define mutexIsNT() (1) +#else + static int mutexIsNT(void){ + static int osType = 0; + if( osType==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return osType==2; + } +#endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */ +#endif + #ifdef SQLITE_DEBUG /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are @@ -21370,45 +19189,20 @@ struct sqlite3_mutex { static int winMutexHeld(sqlite3_mutex *p){ return p->nRef!=0 && p->owner==GetCurrentThreadId(); } - static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ return p->nRef==0 || p->owner!=tid; } - static int winMutexNotheld(sqlite3_mutex *p){ - DWORD tid = GetCurrentThreadId(); + DWORD tid = GetCurrentThreadId(); return winMutexNotheld2(p, tid); } #endif -/* -** Try to provide a memory barrier operation, needed for initialization -** and also for the xShmBarrier method of the VFS in cases when SQLite is -** compiled without mutexes (SQLITE_THREADSAFE=0). -*/ -SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ -#if defined(SQLITE_MEMORY_BARRIER) - SQLITE_MEMORY_BARRIER; -#elif defined(__GNUC__) - __sync_synchronize(); -#elif !defined(SQLITE_DISABLE_INTRINSIC) && \ - defined(_MSC_VER) && _MSC_VER>=1300 - _ReadWriteBarrier(); -#elif defined(MemoryBarrier) - MemoryBarrier(); -#endif -} /* ** Initialize and deinitialize the mutex subsystem. */ -static sqlite3_mutex winMutex_staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, +static sqlite3_mutex winMutex_staticMutexes[6] = { SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, @@ -21416,20 +19210,17 @@ static sqlite3_mutex winMutex_staticMutexes[] = { SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER }; - static int winMutex_isInit = 0; -static int winMutex_isNt = -1; /* <0 means "need to query" */ - -/* As the winMutexInit() and winMutexEnd() functions are called as part -** of the sqlite3_initialize() and sqlite3_shutdown() processing, the -** "interlocked" magic used here is probably not strictly necessary. +/* As winMutexInit() and winMutexEnd() are called as part +** of the sqlite3_initialize and sqlite3_shutdown() +** processing, the "interlocked" magic is probably not +** strictly necessary. */ -static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; +static LONG winMutex_lock = 0; -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ -static int winMutexInit(void){ +static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ int i; @@ -21442,17 +19233,16 @@ static int winMutexInit(void){ } winMutex_isInit = 1; }else{ - /* Another thread is (in the process of) initializing the static - ** mutexes */ + /* Someone else is in the process of initing the static mutexes */ while( !winMutex_isInit ){ sqlite3_win32_sleep(1); } } - return SQLITE_OK; + return SQLITE_OK; } -static int winMutexEnd(void){ - /* The first to decrement to 0 does actual shutdown +static int winMutexEnd(void){ + /* The first to decrement to 0 does actual shutdown ** (which should be the last to shutdown.) */ if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){ if( winMutex_isInit==1 ){ @@ -21463,7 +19253,7 @@ static int winMutexEnd(void){ winMutex_isInit = 0; } } - return SQLITE_OK; + return SQLITE_OK; } /* @@ -21478,16 +19268,10 @@ static int winMutexEnd(void){ **
  • SQLITE_MUTEX_RECURSIVE **
  • SQLITE_MUTEX_STATIC_MASTER **
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_OPEN +**
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU **
  • SQLITE_MUTEX_STATIC_PMEM -**
  • SQLITE_MUTEX_STATIC_APP1 -**
  • SQLITE_MUTEX_STATIC_APP2 -**
  • SQLITE_MUTEX_STATIC_APP3 -**
  • SQLITE_MUTEX_STATIC_VFS1 -**
  • SQLITE_MUTEX_STATIC_VFS2 -**
  • SQLITE_MUTEX_STATIC_VFS3 ** ** ** The first two constants cause sqlite3_mutex_alloc() to create @@ -21510,7 +19294,7 @@ static int winMutexEnd(void){ ** ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. But for the static +** returns a different mutex on every call. But for the static ** mutex types, the same mutex is returned on every call that has ** the same type number. */ @@ -21521,12 +19305,9 @@ static sqlite3_mutex *winMutexAlloc(int iType){ case SQLITE_MUTEX_FAST: case SQLITE_MUTEX_RECURSIVE: { p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ - p->id = iType; + if( p ){ #ifdef SQLITE_DEBUG -#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC - p->trace = 1; -#endif + p->id = iType; #endif #if SQLITE_OS_WINRT InitializeCriticalSectionEx(&p->mutex, 0, 0); @@ -21537,18 +19318,12 @@ static sqlite3_mutex *winMutexAlloc(int iType){ break; } default: { -#ifdef SQLITE_ENABLE_API_ARMOR - if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif + assert( winMutex_isInit==1 ); + assert( iType-2 >= 0 ); + assert( iType-2 < ArraySize(winMutex_staticMutexes) ); p = &winMutex_staticMutexes[iType-2]; - p->id = iType; #ifdef SQLITE_DEBUG -#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC - p->trace = 1; -#endif + p->id = iType; #endif break; } @@ -21565,14 +19340,9 @@ static sqlite3_mutex *winMutexAlloc(int iType){ static void winMutexFree(sqlite3_mutex *p){ assert( p ); assert( p->nRef==0 && p->owner==0 ); - if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ - DeleteCriticalSection(&p->mutex); - sqlite3_free(p); - }else{ -#ifdef SQLITE_ENABLE_API_ARMOR - (void)SQLITE_MISUSE_BKPT; -#endif - } + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); } /* @@ -21587,39 +19357,30 @@ static void winMutexFree(sqlite3_mutex *p){ ** more than once, the behavior is undefined. */ static void winMutexEnter(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - DWORD tid = GetCurrentThreadId(); -#endif #ifdef SQLITE_DEBUG - assert( p ); + DWORD tid = GetCurrentThreadId(); assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); -#else - assert( p ); #endif - assert( winMutex_isInit==1 ); EnterCriticalSection(&p->mutex); #ifdef SQLITE_DEBUG assert( p->nRef>0 || p->owner==0 ); - p->owner = tid; + p->owner = tid; p->nRef++; if( p->trace ){ - OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", - tid, p, p->trace, p->nRef)); + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif } - static int winMutexTry(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - DWORD tid = GetCurrentThreadId(); +#ifndef NDEBUG + DWORD tid = GetCurrentThreadId(); #endif int rc = SQLITE_BUSY; - assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); /* ** The sqlite3_mutex_try() routine is very rarely used, and when it ** is used it is merely an optimization. So it is OK for it to always - ** fail. + ** fail. ** ** The TryEnterCriticalSection() interface is only available on WinNT. ** And some windows compilers complain if you try to use it without @@ -21627,27 +19388,18 @@ static int winMutexTry(sqlite3_mutex *p){ ** For that reason, we will omit this optimization for now. See ** ticket #2685. */ -#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 - assert( winMutex_isInit==1 ); - assert( winMutex_isNt>=-1 && winMutex_isNt<=1 ); - if( winMutex_isNt<0 ){ - winMutex_isNt = sqlite3_win32_is_nt(); - } - assert( winMutex_isNt==0 || winMutex_isNt==1 ); - if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){ -#ifdef SQLITE_DEBUG +#if 0 + if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ p->owner = tid; p->nRef++; -#endif rc = SQLITE_OK; } #else UNUSED_PARAMETER(p); #endif #ifdef SQLITE_DEBUG - if( p->trace ){ - OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", - tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); + if( rc==SQLITE_OK && p->trace ){ + printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif return rc; @@ -21660,23 +19412,18 @@ static int winMutexTry(sqlite3_mutex *p){ ** is not currently allocated. SQLite will never do either. */ static void winMutexLeave(sqlite3_mutex *p){ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +#ifndef NDEBUG DWORD tid = GetCurrentThreadId(); -#endif - assert( p ); -#ifdef SQLITE_DEBUG assert( p->nRef>0 ); assert( p->owner==tid ); p->nRef--; if( p->nRef==0 ) p->owner = 0; assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); #endif - assert( winMutex_isInit==1 ); LeaveCriticalSection(&p->mutex); #ifdef SQLITE_DEBUG if( p->trace ){ - OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", - tid, p, p->trace, p->nRef)); + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif } @@ -21698,9 +19445,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ 0 #endif }; + return &sMutex; } - #endif /* SQLITE_MUTEX_W32 */ /************** End of mutex_w32.c *******************************************/ @@ -21719,7 +19466,6 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** ** Memory allocation functions used throughout sqlite. */ -/* #include "sqliteInt.h" */ /* #include */ /* @@ -21727,7 +19473,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ -SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){ +SQLITE_API int sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT return sqlite3PcacheReleaseMemory(n); #else @@ -21752,7 +19498,16 @@ typedef struct ScratchFreeslot { */ static SQLITE_WSD struct Mem0Global { sqlite3_mutex *mutex; /* Mutex to serialize access */ - sqlite3_int64 alarmThreshold; /* The soft heap limit */ + + /* + ** The alarm callback and its arguments. The mem0.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; /* ** Pointers to the end of sqlite3GlobalConfig.pScratch memory @@ -21769,62 +19524,82 @@ static SQLITE_WSD struct Mem0Global { ** sqlite3_soft_heap_limit() setting. */ int nearlyFull; -} mem0 = { 0, 0, 0, 0, 0, 0 }; +} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; #define mem0 GLOBAL(struct Mem0Global, mem0) /* -** Return the memory allocator mutex. sqlite3_status() needs it. +** This routine runs when the memory allocator sees that the +** total memory allocation is about to exceed the soft heap +** limit. */ -SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){ - return mem0.mutex; +static void softHeapLimitEnforcer( + void *NotUsed, + sqlite3_int64 NotUsed2, + int allocSize +){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + sqlite3_release_memory(allocSize); } -#ifndef SQLITE_OMIT_DEPRECATED /* -** Deprecated external interface. It used to set an alarm callback -** that was invoked when memory usage grew too large. Now it is a -** no-op. +** Change the alarm callback */ -SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm( +static int sqlite3MemoryAlarm( void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, sqlite3_int64 iThreshold ){ - (void)xCallback; - (void)pArg; - (void)iThreshold; + int nUsed; + sqlite3_mutex_enter(mem0.mutex); + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; + mem0.alarmThreshold = iThreshold; + nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed); + sqlite3_mutex_leave(mem0.mutex); return SQLITE_OK; } + +#ifndef SQLITE_OMIT_DEPRECATED +/* +** Deprecated external interface. Internal/core SQLite code +** should call sqlite3MemoryAlarm. +*/ +SQLITE_API int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); +} #endif /* ** Set the soft heap-size limit for the library. Passing a zero or ** negative value indicates no limit. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ sqlite3_int64 priorLimit; sqlite3_int64 excess; - sqlite3_int64 nUsed; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return -1; #endif sqlite3_mutex_enter(mem0.mutex); priorLimit = mem0.alarmThreshold; - if( n<0 ){ - sqlite3_mutex_leave(mem0.mutex); - return priorLimit; - } - mem0.alarmThreshold = n; - nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); - mem0.nearlyFull = (n>0 && n<=nUsed); sqlite3_mutex_leave(mem0.mutex); + if( n<0 ) return priorLimit; + if( n>0 ){ + sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n); + }else{ + sqlite3MemoryAlarm(0, 0, 0); + } excess = sqlite3_memory_used() - n; if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); return priorLimit; } -SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ +SQLITE_API void sqlite3_soft_heap_limit(int n){ if( n<0 ) n = 0; sqlite3_soft_heap_limit64(n); } @@ -21833,12 +19608,13 @@ SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){ ** Initialize the memory allocation subsystem. */ SQLITE_PRIVATE int sqlite3MallocInit(void){ - int rc; if( sqlite3GlobalConfig.m.xMalloc==0 ){ sqlite3MemSetDefault(); } memset(&mem0, 0, sizeof(mem0)); - mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + if( sqlite3GlobalConfig.bCoreMutex ){ + mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 && sqlite3GlobalConfig.nScratch>0 ){ int i, n, sz; @@ -21862,13 +19638,12 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){ sqlite3GlobalConfig.nScratch = 0; } if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 - || sqlite3GlobalConfig.nPage<=0 ){ + || sqlite3GlobalConfig.nPage<1 ){ sqlite3GlobalConfig.pPage = 0; sqlite3GlobalConfig.szPage = 0; + sqlite3GlobalConfig.nPage = 0; } - rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); - if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0)); - return rc; + return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); } /* @@ -21893,9 +19668,11 @@ SQLITE_PRIVATE void sqlite3MallocEnd(void){ /* ** Return the amount of memory currently checked out. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ - sqlite3_int64 res, mx; - sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0); +SQLITE_API sqlite3_int64 sqlite3_memory_used(void){ + int n, mx; + sqlite3_int64 res; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0); + res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */ return res; } @@ -21904,20 +19681,31 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){ - sqlite3_int64 res, mx; - sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag); - return mx; +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + int n, mx; + sqlite3_int64 res; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag); + res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */ + return res; } /* ** Trigger the alarm */ static void sqlite3MallocAlarm(int nByte){ - if( mem0.alarmThreshold<=0 ) return; + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem0.alarmCallback==0 ) return; + xCallback = mem0.alarmCallback; + nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + pArg = mem0.alarmArg; + mem0.alarmCallback = 0; sqlite3_mutex_leave(mem0.mutex); - sqlite3_release_memory(nByte); + xCallback(pArg, nowUsed, nByte); sqlite3_mutex_enter(mem0.mutex); + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; } /* @@ -21929,9 +19717,9 @@ static int mallocWithAlarm(int n, void **pp){ void *p; assert( sqlite3_mutex_held(mem0.mutex) ); nFull = sqlite3GlobalConfig.m.xRoundup(n); - sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); - if( mem0.alarmThreshold>0 ){ - sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); + if( mem0.alarmCallback!=0 ){ + int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); if( nUsed >= mem0.alarmThreshold - nFull ){ mem0.nearlyFull = 1; sqlite3MallocAlarm(nFull); @@ -21941,15 +19729,15 @@ static int mallocWithAlarm(int n, void **pp){ } p = sqlite3GlobalConfig.m.xMalloc(nFull); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - if( p==0 && mem0.alarmThreshold>0 ){ + if( p==0 && mem0.alarmCallback ){ sqlite3MallocAlarm(nFull); p = sqlite3GlobalConfig.m.xMalloc(nFull); } #endif if( p ){ nFull = sqlite3MallocSize(p); - sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); - sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); + sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); } *pp = p; return nFull; @@ -21959,9 +19747,11 @@ static int mallocWithAlarm(int n, void **pp){ ** Allocate memory. This routine is like sqlite3_malloc() except that it ** assumes the memory subsystem has already been initialized. */ -SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ +SQLITE_PRIVATE void *sqlite3Malloc(int n){ void *p; - if( n==0 || n>=0x7fffff00 ){ + if( n<=0 /* IMP: R-65312-04917 */ + || n>=0x7fffff00 + ){ /* A memory allocation of a number of bytes which is near the maximum ** signed integer value might cause an integer overflow inside of the ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving @@ -21970,12 +19760,12 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ p = 0; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - mallocWithAlarm((int)n, &p); + mallocWithAlarm(n, &p); sqlite3_mutex_leave(mem0.mutex); }else{ - p = sqlite3GlobalConfig.m.xMalloc((int)n); + p = sqlite3GlobalConfig.m.xMalloc(n); } - assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */ + assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */ return p; } @@ -21984,13 +19774,7 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){ ** First make sure the memory subsystem is initialized, then do the ** allocation. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - return n<=0 ? 0 : sqlite3Malloc(n); -} -SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){ +SQLITE_API void *sqlite3_malloc(int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -22021,20 +19805,22 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ assert( n>0 ); sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n); if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ p = mem0.pScratchFree; mem0.pScratchFree = mem0.pScratchFree->pNext; mem0.nScratchFree--; - sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); sqlite3_mutex_leave(mem0.mutex); }else{ - sqlite3_mutex_leave(mem0.mutex); - p = sqlite3Malloc(n); - if( sqlite3GlobalConfig.bMemstat && p ){ - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); + if( sqlite3GlobalConfig.bMemstat ){ + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); + n = mallocWithAlarm(n, &p); + if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3_mutex_leave(mem0.mutex); + p = sqlite3GlobalConfig.m.xMalloc(n); } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); } @@ -22042,12 +19828,11 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ #if SQLITE_THREADSAFE==0 && !defined(NDEBUG) - /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch - ** buffers per thread. - ** - ** This can only be checked in single-threaded mode. - */ - assert( scratchAllocOut==0 ); + /* Verify that no more than two scratch allocations per thread + ** are outstanding at one time. (This is only checked in the + ** single-threaded case since checking in the multi-threaded case + ** would be much more complicated.) */ + assert( scratchAllocOut<=1 ); if( p ) scratchAllocOut++; #endif @@ -22065,7 +19850,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ scratchAllocOut--; #endif - if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){ + if( p>=sqlite3GlobalConfig.pScratch && plookaside.pStart, db->lookaside.pEnd); + return p>=db->lookaside.pStart && plookaside.pEnd; } #else #define isLookaside(A,B) 0 @@ -22113,43 +19898,33 @@ static int isLookaside(sqlite3 *db, void *p){ */ SQLITE_PRIVATE int sqlite3MallocSize(void *p){ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); return sqlite3GlobalConfig.m.xSize(p); } SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ - assert( p!=0 ); - if( db==0 || !isLookaside(db,p) ){ -#if SQLITE_DEBUG - if( db==0 ){ - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - }else{ - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - } -#endif - return sqlite3GlobalConfig.m.xSize(p); - }else{ - assert( sqlite3_mutex_held(db->mutex) ); + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db, p) ){ return db->lookaside.sz; + }else{ + assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); + assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); + return sqlite3GlobalConfig.m.xSize(p); } } -SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){ - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); - assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - return p ? sqlite3GlobalConfig.m.xSize(p) : 0; -} /* ** Free memory previously obtained from sqlite3Malloc(). */ -SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ +SQLITE_API void sqlite3_free(void *p){ if( p==0 ) return; /* IMP: R-49053-54554 */ + assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); - sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); + sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); sqlite3GlobalConfig.m.xFree(p); sqlite3_mutex_leave(mem0.mutex); }else{ @@ -22157,14 +19932,6 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){ } } -/* -** Add the size of memory allocation "p" to the count in -** *db->pnBytesFreed. -*/ -static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){ - *db->pnBytesFreed += sqlite3DbMallocSize(db,p); -} - /* ** Free memory that might be associated with a particular database ** connection. @@ -22174,7 +19941,7 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ if( p==0 ) return; if( db ){ if( db->pnBytesFreed ){ - measureAllocationSize(db, p); + *db->pnBytesFreed += sqlite3DbMallocSize(db, p); return; } if( isLookaside(db, p) ){ @@ -22189,8 +19956,8 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ return; } } - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); sqlite3_free(p); @@ -22199,16 +19966,14 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ /* ** Change the size of an existing memory allocation */ -SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ +SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){ int nOld, nNew, nDiff; void *pNew; - assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) ); if( pOld==0 ){ - return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */ + return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */ } - if( nBytes==0 ){ - sqlite3_free(pOld); /* IMP: R-26507-47431 */ + if( nBytes<=0 ){ + sqlite3_free(pOld); /* IMP: R-31593-10574 */ return 0; } if( nBytes>=0x7fffff00 ){ @@ -22219,31 +19984,33 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second ** argument to xRealloc is always a value returned by a prior call to ** xRoundup. */ - nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); + nNew = sqlite3GlobalConfig.m.xRoundup(nBytes); if( nOld==nNew ){ pNew = pOld; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes); nDiff = nNew - nOld; if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= mem0.alarmThreshold-nDiff ){ sqlite3MallocAlarm(nDiff); } + assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); - if( pNew==0 && mem0.alarmThreshold>0 ){ - sqlite3MallocAlarm((int)nBytes); + if( pNew==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm(nBytes); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); } if( pNew ){ nNew = sqlite3MallocSize(pNew); - sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); } sqlite3_mutex_leave(mem0.mutex); }else{ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); } - assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */ + assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */ return pNew; } @@ -22251,14 +20018,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){ ** The public interface to sqlite3Realloc. Make sure that the memory ** subsystem is initialized prior to invoking sqliteRealloc. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){ -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return 0; -#endif - if( n<0 ) n = 0; /* IMP: R-26507-47431 */ - return sqlite3Realloc(pOld, n); -} -SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ +SQLITE_API void *sqlite3_realloc(void *pOld, int n){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif @@ -22269,10 +20029,10 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){ /* ** Allocate and zero memory. */ -SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){ +SQLITE_PRIVATE void *sqlite3MallocZero(int n){ void *p = sqlite3Malloc(n); if( p ){ - memset(p, 0, (size_t)n); + memset(p, 0, n); } return p; } @@ -22281,10 +20041,10 @@ SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){ ** Allocate and zero memory. If the allocation fails, make ** the mallocFailed flag in the connection pointer. */ -SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ +SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){ void *p = sqlite3DbMallocRaw(db, n); if( p ){ - memset(p, 0, (size_t)n); + memset(p, 0, n); } return p; } @@ -22307,7 +20067,7 @@ SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed ** that all prior mallocs (ex: "a") worked too. */ -SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ +SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){ void *p; assert( db==0 || sqlite3_mutex_held(db->mutex) ); assert( db==0 || db->pnBytesFreed==0 ); @@ -22342,8 +20102,8 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ if( !p && db ){ db->mallocFailed = 1; } - sqlite3MemdebugSetType(p, - (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); + sqlite3MemdebugSetType(p, MEMTYPE_DB | + ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); return p; } @@ -22351,7 +20111,7 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ ** Resize the block of memory pointed to by p to n bytes. If the ** resize fails, set the mallocFailed flag in the connection object. */ -SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ +SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ void *pNew = 0; assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); @@ -22369,14 +20129,15 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ sqlite3DbFree(db, p); } }else{ - assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); + assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - pNew = sqlite3_realloc64(p, n); + pNew = sqlite3_realloc(p, n); if( !pNew ){ + sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP); db->mallocFailed = 1; } - sqlite3MemdebugSetType(pNew, + sqlite3MemdebugSetType(pNew, MEMTYPE_DB | (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); } } @@ -22387,7 +20148,7 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ ** Attempt to reallocate p. If the reallocation fails, then free p ** and set the mallocFailed flag in the database connection. */ -SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){ +SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){ void *pNew; pNew = sqlite3DbRealloc(db, p, n); if( !pNew ){ @@ -22417,7 +20178,7 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){ } return zNew; } -SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ +SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){ char *zNew; if( z==0 ){ return 0; @@ -22425,28 +20186,28 @@ SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ assert( (n&0x7fffffff)==n ); zNew = sqlite3DbMallocRaw(db, n+1); if( zNew ){ - memcpy(zNew, z, (size_t)n); + memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } /* -** Free any prior content in *pz and replace it with a copy of zNew. +** Create a string from the zFromat argument and the va_list that follows. +** Store the string in memory obtained from sqliteMalloc() and make *pz +** point to that string. */ -SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ +SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *z; + + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); sqlite3DbFree(db, *pz); - *pz = sqlite3DbStrDup(db, zNew); + *pz = z; } -/* -** Take actions at the end of an API call to indicate an OOM error -*/ -static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ - db->mallocFailed = 0; - sqlite3Error(db, SQLITE_NOMEM); - return SQLITE_NOMEM; -} /* ** This function must be called before exiting any API function (i.e. @@ -22457,36 +20218,40 @@ static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ ** function. However, if a malloc() failure has occurred since the previous ** invocation SQLITE_NOMEM is returned instead. ** -** If an OOM as occurred, then the connection error-code (the value -** returned by sqlite3_errcode()) is set to SQLITE_NOMEM. +** If the first argument, db, is not NULL and a malloc() error has occurred, +** then the connection error-code (the value returned by sqlite3_errcode()) +** is set to SQLITE_NOMEM. */ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ - /* If the db handle must hold the connection handle mutex here. - ** Otherwise the read (and possible write) of db->mallocFailed + /* If the db handle is not NULL, then we must hold the connection handle + ** mutex here. Otherwise the read (and possible write) of db->mallocFailed ** is unsafe, as is the call to sqlite3Error(). */ - assert( db!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ - return apiOomError(db); + assert( !db || sqlite3_mutex_held(db->mutex) ); + if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ + sqlite3Error(db, SQLITE_NOMEM, 0); + db->mallocFailed = 0; + rc = SQLITE_NOMEM; } - return rc & db->errMask; + return rc & (db ? db->errMask : 0xff); } /************** End of malloc.c **********************************************/ /************** Begin file printf.c ******************************************/ /* ** The "printf" code that follows dates from the 1980's. It is in -** the public domain. +** the public domain. The original comments are included here for +** completeness. They are very out-of-date but might be useful as +** an historical reference. Most of the "enhancements" have been backed +** out so that the functionality is now the same as standard printf(). ** ************************************************************************** ** ** This file contains code for a set of "printf"-like routines. These ** routines format strings much like the printf() from the standard C ** library, though the implementation here has enhancements to support -** SQLite. +** SQLlite. */ -/* #include "sqliteInt.h" */ /* ** Conversion types fall into various categories as defined by the @@ -22612,7 +20377,6 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ ** Set the StrAccum object to an error mode. */ static void setStrAccumError(StrAccum *p, u8 eError){ - assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); p->accError = eError; p->nAlloc = 0; } @@ -22676,7 +20440,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( 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 */ + char *zExtra; /* 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 */ @@ -22699,13 +20463,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ bufpt = (char *)fmt; -#if HAVE_STRCHRNUL - fmt = strchrnul(fmt, '%'); -#else - do{ fmt++; }while( *fmt && *fmt != '%' ); -#endif + while( (c=(*++fmt))!='%' && c!=0 ){}; sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); - if( *fmt==0 ) break; + if( c==0 ) break; } if( (c=(*++fmt))==0 ){ sqlite3StrAccumAppend(pAccum, "%", 1); @@ -22727,6 +20487,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } }while( !done && (c=(*++fmt))!=0 ); /* Get the field width */ + width = 0; if( c=='*' ){ if( bArgList ){ width = (int)getIntArg(pArgList); @@ -22735,27 +20496,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } if( width<0 ){ flag_leftjustify = 1; - width = width >= -2147483647 ? -width : 0; + width = -width; } c = *++fmt; }else{ - unsigned wx = 0; while( c>='0' && c<='9' ){ - wx = wx*10 + c - '0'; + width = width*10 + c - '0'; c = *++fmt; } - testcase( wx>0x7fffffff ); - width = wx & 0x7fffffff; } - assert( width>=0 ); -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ - width = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - /* Get the precision */ if( c=='.' ){ + precision = 0; c = *++fmt; if( c=='*' ){ if( bArgList ){ @@ -22763,30 +20515,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ precision = va_arg(ap,int); } + if( precision<0 ) precision = -precision; c = *++fmt; - if( precision<0 ){ - precision = precision >= -2147483647 ? -precision : -1; - } }else{ - unsigned px = 0; while( c>='0' && c<='9' ){ - px = px*10 + c - '0'; + precision = precision*10 + c - '0'; c = *++fmt; } - testcase( px>0x7fffffff ); - precision = px & 0x7fffffff; } }else{ precision = -1; } - assert( precision>=(-1) ); -#ifdef SQLITE_PRINTF_PRECISION_LIMIT - if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){ - precision = SQLITE_PRINTF_PRECISION_LIMIT; - } -#endif - - /* Get the conversion type modifier */ if( c=='l' ){ flag_long = 1; @@ -22814,6 +20553,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( break; } } + zExtra = 0; /* ** At this point, variables are initialized as follows: @@ -22946,8 +20686,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( else prefix = 0; } if( xtype==etGENERIC && precision>0 ) precision--; - testcase( precision>0xfff ); - for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} + for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} if( xtype==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; @@ -22959,16 +20698,21 @@ SQLITE_PRIVATE void sqlite3VXPrintf( 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>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; } + while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; } while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } realvalue /= scale; while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } if( exp>350 ){ - bufpt = buf; - buf[0] = prefix; - memcpy(buf+(prefix!=0),"Inf",4); - length = 3+(prefix!=0); + if( prefix=='-' ){ + bufpt = "-Inf"; + }else if( prefix=='+' ){ + bufpt = "+Inf"; + }else{ + bufpt = "Inf"; + } + length = sqlite3Strlen30(bufpt); break; } } @@ -22997,9 +20741,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ e2 = exp; } - if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ - bufpt = zExtra - = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); + if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ + bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); if( bufpt==0 ){ setStrAccumError(pAccum, STRACCUM_NOMEM); return; @@ -23101,29 +20844,25 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ c = va_arg(ap,int); } - if( precision>1 ){ - width -= precision-1; - if( width>1 && !flag_leftjustify ){ - sqlite3AppendChar(pAccum, width-1, ' '); - width = 0; - } - sqlite3AppendChar(pAccum, precision-1, c); + buf[0] = (char)c; + if( precision>=0 ){ + for(idx=1; idx=0 ){ @@ -23132,9 +20871,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf( length = sqlite3Strlen30(bufpt); } break; - case etSQLESCAPE: /* Escape ' characters */ - case etSQLESCAPE2: /* Escape ' and enclose in '...' */ - case etSQLESCAPE3: { /* Escape " characters */ + case etSQLESCAPE: + case etSQLESCAPE2: + case etSQLESCAPE3: { int i, j, k, n, isnull; int needQuote; char ch; @@ -23153,7 +20892,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( ch==q ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; - n += i + 3; + n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqlite3Malloc( n ); if( bufpt==0 ){ @@ -23212,14 +20951,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( ** the output. */ width -= length; - if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width); sqlite3StrAccumAppend(pAccum, bufpt, length); - if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width); - if( zExtra ){ - sqlite3DbFree(pAccum->db, zExtra); - zExtra = 0; - } + if( zExtra ) sqlite3_free(zExtra); }/* End for loop over the format string */ } /* End of function */ @@ -23232,26 +20968,20 @@ SQLITE_PRIVATE void sqlite3VXPrintf( */ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; - assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ + assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ testcase(p->accError==STRACCUM_TOOBIG); testcase(p->accError==STRACCUM_NOMEM); return 0; } - if( p->mxAlloc==0 ){ + if( !p->useMalloc ){ N = p->nAlloc - p->nChar - 1; setStrAccumError(p, STRACCUM_TOOBIG); return N; }else{ - char *zOld = p->bMalloced ? p->zText : 0; + char *zOld = (p->zText==p->zBase ? 0 : p->zText); i64 szNew = p->nChar; - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); szNew += N + 1; - if( szNew+p->nChar<=p->mxAlloc ){ - /* Force exponential buffer size growth as long as it does not overflow, - ** to avoid having to call this routine too often */ - szNew += p->nChar; - } if( szNew > p->mxAlloc ){ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_TOOBIG); @@ -23259,17 +20989,15 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ }else{ p->nAlloc = (int)szNew; } - if( p->db ){ + if( p->useMalloc==1 ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ - zNew = sqlite3_realloc64(zOld, p->nAlloc); + zNew = sqlite3_realloc(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); - if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); + if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; - p->nAlloc = sqlite3DbMallocSize(p->db, zNew); - p->bMalloced = 1; }else{ sqlite3StrAccumReset(p); setStrAccumError(p, STRACCUM_NOMEM); @@ -23280,15 +21008,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ } /* -** Append N copies of character c to the given string buffer. +** Append N space characters to the given string buffer. */ -SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ - testcase( p->nChar + (i64)N > 0x7fffffff ); - if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ - return; - } - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); - while( (N--)>0 ) p->zText[p->nChar++] = c; +SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *p, int N){ + if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return; + while( (N--)>0 ) p->zText[p->nChar++] = ' '; } /* @@ -23299,13 +21023,12 @@ SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ ** work (enlarging the buffer) using tail recursion, so that the ** sqlite3StrAccumAppend() routine can use fast calling semantics. */ -static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ +static void enlargeAndAppend(StrAccum *p, const char *z, int N){ N = sqlite3StrAccumEnlarge(p, N); if( N>0 ){ memcpy(&p->zText[p->nChar], z, N); p->nChar += N; } - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); } /* @@ -23313,17 +21036,17 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ ** size of the memory allocation for StrAccum if necessary. */ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ - assert( z!=0 || N==0 ); + assert( z!=0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); - }else{ - assert( p->zText ); - p->nChar += N; - memcpy(&p->zText[p->nChar-N], z, N); + return; } + assert( p->zText ); + memcpy(&p->zText[p->nChar], z, N); + p->nChar += N; } /* @@ -23341,13 +21064,15 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ */ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); p->zText[p->nChar] = 0; - if( p->mxAlloc>0 && p->bMalloced==0 ){ - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->useMalloc && p->zText==p->zBase ){ + if( p->useMalloc==1 ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + }else{ + p->zText = sqlite3_malloc(p->nChar+1); + } if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); - p->bMalloced = 1; }else{ setStrAccumError(p, STRACCUM_NOMEM); } @@ -23360,36 +21085,27 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ ** Reset an StrAccum string. Reclaim all malloced memory. */ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); - if( p->bMalloced ){ - sqlite3DbFree(p->db, p->zText); - p->bMalloced = 0; + if( p->zText!=p->zBase ){ + if( p->useMalloc==1 ){ + sqlite3DbFree(p->db, p->zText); + }else{ + sqlite3_free(p->zText); + } } p->zText = 0; } /* -** Initialize a string accumulator. -** -** p: The accumulator to be initialized. -** db: Pointer to a database connection. May be NULL. Lookaside -** memory is used if not NULL. db->mallocFailed is set appropriately -** when not NULL. -** zBase: An initial buffer. May be NULL in which case the initial buffer -** is malloced. -** n: Size of zBase in bytes. If total space requirements never exceed -** n then no memory allocations ever occur. -** mx: Maximum number of bytes to accumulate. If mx==0 then no memory -** allocations will ever occur. +** Initialize a string accumulator */ -SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ +SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ p->zText = p->zBase = zBase; - p->db = db; + p->db = 0; p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; + p->useMalloc = 1; p->accError = 0; - p->bMalloced = 0; } /* @@ -23401,8 +21117,9 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; assert( db!=0 ); - sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); + acc.db = db; sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ @@ -23424,25 +21141,37 @@ SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ return z; } +/* +** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting +** the string and before returnning. This routine is intended to be used +** to modify an existing string. For example: +** +** x = sqlite3MPrintf(db, x, "prefix %s suffix", x); +** +*/ +SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3DbFree(db, zStr); + return z; +} + /* ** Print into memory obtained from sqlite3_malloc(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zFormat==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif - sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); + acc.useMalloc = 2; sqlite3VXPrintf(&acc, 0, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; @@ -23452,7 +21181,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap ** Print into memory obtained from sqlite3_malloc()(). Omit the internal ** %-conversion extensions. */ -SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ +SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; #ifndef SQLITE_OMIT_AUTOINIT @@ -23477,21 +21206,15 @@ SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){ ** ** sqlite3_vsnprintf() is the varargs version. */ -SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ +SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ StrAccum acc; 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); + sqlite3StrAccumInit(&acc, zBuf, n, 0); + acc.useMalloc = 0; sqlite3VXPrintf(&acc, 0, zFormat, ap); return sqlite3StrAccumFinish(&acc); } -SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ +SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); @@ -23508,17 +21231,13 @@ SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zF ** sqlite3_log() must render into a static buffer. It cannot dynamically ** allocate memory because it might be called while the memory allocator ** mutex is held. -** -** sqlite3VXPrintf() might ask for *temporary* memory allocations for -** certain format characters (%q) or for very large precisions or widths. -** Care must be taken that any sqlite3_log() calls that occur while the -** memory mutex is held do not use these mechanisms. */ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ - sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); + sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); + acc.useMalloc = 0; sqlite3VXPrintf(&acc, 0, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); @@ -23527,7 +21246,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ /* ** Format and write a message to the log if logging is enabled. */ -SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){ va_list ap; /* Vararg list */ if( sqlite3GlobalConfig.xLog ){ va_start(ap, zFormat); @@ -23536,7 +21255,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...) } } -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +#if defined(SQLITE_DEBUG) /* ** A version of printf() that understands %lld. Used for debugging. ** The printf() built into some versions of windows does not understand %lld @@ -23546,7 +21265,8 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ va_list ap; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); + acc.useMalloc = 0; va_start(ap,zFormat); sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); @@ -23556,10 +21276,8 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ } #endif - /* -** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument -** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. +** variable-argument wrapper around sqlite3VXPrintf(). */ SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ va_list ap; @@ -23569,495 +21287,6 @@ SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, } /************** End of printf.c **********************************************/ -/************** Begin file treeview.c ****************************************/ -/* -** 2015-06-08 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains C code to implement the TreeView debugging routines. -** These routines print a parse tree to standard output for debugging and -** analysis. -** -** The interfaces in this file is only available when compiling -** with SQLITE_DEBUG. -*/ -/* #include "sqliteInt.h" */ -#ifdef SQLITE_DEBUG - -/* -** Add a new subitem to the tree. The moreToFollow flag indicates that this -** is not the last item in the tree. -*/ -static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ - if( p==0 ){ - p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return 0; - memset(p, 0, sizeof(*p)); - }else{ - p->iLevel++; - } - assert( moreToFollow==0 || moreToFollow==1 ); - if( p->iLevelbLine) ) p->bLine[p->iLevel] = moreToFollow; - return p; -} - -/* -** Finished with one layer of the tree -*/ -static void sqlite3TreeViewPop(TreeView *p){ - if( p==0 ) return; - p->iLevel--; - if( p->iLevel<0 ) sqlite3_free(p); -} - -/* -** Generate a single line of output for the tree, with a prefix that contains -** all the appropriate tree lines -*/ -static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ - va_list ap; - int i; - StrAccum acc; - char zBuf[500]; - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - if( p ){ - for(i=0; iiLevel && ibLine)-1; i++){ - sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); - } - sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); - } - va_start(ap, zFormat); - sqlite3VXPrintf(&acc, 0, zFormat, ap); - va_end(ap); - if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); - sqlite3StrAccumFinish(&acc); - fprintf(stdout,"%s", zBuf); - fflush(stdout); -} - -/* -** Shorthand for starting a new tree item that consists of a single label -*/ -static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ - p = sqlite3TreeViewPush(p, moreFollows); - sqlite3TreeViewLine(p, "%s", zLabel); -} - -/* -** Generate a human-readable description of a WITH clause. -*/ -SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){ - int i; - if( pWith==0 ) return; - if( pWith->nCte==0 ) return; - if( pWith->pOuter ){ - sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter); - }else{ - sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith); - } - if( pWith->nCte>0 ){ - pView = sqlite3TreeViewPush(pView, 1); - for(i=0; inCte; i++){ - StrAccum x; - char zLine[1000]; - const struct Cte *pCte = &pWith->a[i]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, 0, "%s", pCte->zName); - if( pCte->pCols && pCte->pCols->nExpr>0 ){ - char cSep = '('; - int j; - for(j=0; jpCols->nExpr; j++){ - sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); - cSep = ','; - } - sqlite3XPrintf(&x, 0, ")"); - } - sqlite3XPrintf(&x, 0, " AS"); - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, inCte-1); - sqlite3TreeViewSelect(pView, pCte->pSelect, 0); - sqlite3TreeViewPop(pView); - } - sqlite3TreeViewPop(pView); - } -} - - -/* -** Generate a human-readable description of a the Select object. -*/ -SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ - int n = 0; - int cnt = 0; - pView = sqlite3TreeViewPush(pView, moreToFollow); - if( p->pWith ){ - sqlite3TreeViewWith(pView, p->pWith, 1); - cnt = 1; - sqlite3TreeViewPush(pView, 1); - } - do{ - sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", - ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags - ); - if( cnt++ ) sqlite3TreeViewPop(pView); - if( p->pPrior ){ - n = 1000; - }else{ - n = 0; - if( p->pSrc && p->pSrc->nSrc ) n++; - if( p->pWhere ) n++; - if( p->pGroupBy ) n++; - if( p->pHaving ) n++; - if( p->pOrderBy ) n++; - if( p->pLimit ) n++; - if( p->pOffset ) n++; - } - sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); - if( p->pSrc && p->pSrc->nSrc ){ - int i; - pView = sqlite3TreeViewPush(pView, (n--)>0); - sqlite3TreeViewLine(pView, "FROM"); - for(i=0; ipSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - StrAccum x; - char zLine[100]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); - if( pItem->zDatabase ){ - sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); - }else if( pItem->zName ){ - sqlite3XPrintf(&x, 0, " %s", pItem->zName); - } - if( pItem->pTab ){ - sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); - } - if( pItem->zAlias ){ - sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); - } - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3XPrintf(&x, 0, " LEFT-JOIN"); - } - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1); - if( pItem->pSelect ){ - sqlite3TreeViewSelect(pView, pItem->pSelect, 0); - } - if( pItem->fg.isTabFunc ){ - sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); - } - sqlite3TreeViewPop(pView); - } - sqlite3TreeViewPop(pView); - } - if( p->pWhere ){ - sqlite3TreeViewItem(pView, "WHERE", (n--)>0); - sqlite3TreeViewExpr(pView, p->pWhere, 0); - sqlite3TreeViewPop(pView); - } - if( p->pGroupBy ){ - sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); - } - if( p->pHaving ){ - sqlite3TreeViewItem(pView, "HAVING", (n--)>0); - sqlite3TreeViewExpr(pView, p->pHaving, 0); - sqlite3TreeViewPop(pView); - } - if( p->pOrderBy ){ - sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); - } - if( p->pLimit ){ - sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); - sqlite3TreeViewExpr(pView, p->pLimit, 0); - sqlite3TreeViewPop(pView); - } - if( p->pOffset ){ - sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); - sqlite3TreeViewExpr(pView, p->pOffset, 0); - sqlite3TreeViewPop(pView); - } - if( p->pPrior ){ - const char *zOp = "UNION"; - switch( p->op ){ - case TK_ALL: zOp = "UNION ALL"; break; - case TK_INTERSECT: zOp = "INTERSECT"; break; - case TK_EXCEPT: zOp = "EXCEPT"; break; - } - sqlite3TreeViewItem(pView, zOp, 1); - } - p = p->pPrior; - }while( p!=0 ); - sqlite3TreeViewPop(pView); -} - -/* -** Generate a human-readable explanation of an expression tree. -*/ -SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ - const char *zBinOp = 0; /* Binary operator */ - const char *zUniOp = 0; /* Unary operator */ - char zFlgs[30]; - pView = sqlite3TreeViewPush(pView, moreToFollow); - if( pExpr==0 ){ - sqlite3TreeViewLine(pView, "nil"); - sqlite3TreeViewPop(pView); - return; - } - if( pExpr->flags ){ - sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags); - }else{ - zFlgs[0] = 0; - } - switch( pExpr->op ){ - case TK_AGG_COLUMN: { - sqlite3TreeViewLine(pView, "AGG{%d:%d}%s", - pExpr->iTable, pExpr->iColumn, zFlgs); - break; - } - case TK_COLUMN: { - if( pExpr->iTable<0 ){ - /* This only happens when coding check constraints */ - sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs); - }else{ - sqlite3TreeViewLine(pView, "{%d:%d}%s", - pExpr->iTable, pExpr->iColumn, zFlgs); - } - break; - } - case TK_INTEGER: { - if( pExpr->flags & EP_IntValue ){ - sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue); - }else{ - sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken); - } - break; - } -#ifndef SQLITE_OMIT_FLOATING_POINT - case TK_FLOAT: { - sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_STRING: { - sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken); - break; - } - case TK_NULL: { - sqlite3TreeViewLine(pView,"NULL"); - break; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: { - sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_VARIABLE: { - sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)", - pExpr->u.zToken, pExpr->iColumn); - break; - } - case TK_REGISTER: { - sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable); - break; - } - case TK_ID: { - sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken); - break; - } -#ifndef SQLITE_OMIT_CAST - case TK_CAST: { - /* Expressions of the form: CAST(pLeft AS token) */ - sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } -#endif /* SQLITE_OMIT_CAST */ - case TK_LT: zBinOp = "LT"; break; - case TK_LE: zBinOp = "LE"; break; - case TK_GT: zBinOp = "GT"; break; - case TK_GE: zBinOp = "GE"; break; - case TK_NE: zBinOp = "NE"; break; - case TK_EQ: zBinOp = "EQ"; break; - case TK_IS: zBinOp = "IS"; break; - case TK_ISNOT: zBinOp = "ISNOT"; break; - case TK_AND: zBinOp = "AND"; break; - case TK_OR: zBinOp = "OR"; break; - case TK_PLUS: zBinOp = "ADD"; break; - case TK_STAR: zBinOp = "MUL"; break; - case TK_MINUS: zBinOp = "SUB"; break; - case TK_REM: zBinOp = "REM"; break; - case TK_BITAND: zBinOp = "BITAND"; break; - case TK_BITOR: zBinOp = "BITOR"; break; - case TK_SLASH: zBinOp = "DIV"; break; - case TK_LSHIFT: zBinOp = "LSHIFT"; break; - case TK_RSHIFT: zBinOp = "RSHIFT"; break; - case TK_CONCAT: zBinOp = "CONCAT"; break; - case TK_DOT: zBinOp = "DOT"; break; - - case TK_UMINUS: zUniOp = "UMINUS"; break; - case TK_UPLUS: zUniOp = "UPLUS"; break; - case TK_BITNOT: zUniOp = "BITNOT"; break; - case TK_NOT: zUniOp = "NOT"; break; - case TK_ISNULL: zUniOp = "ISNULL"; break; - case TK_NOTNULL: zUniOp = "NOTNULL"; break; - - case TK_COLLATE: { - sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - break; - } - - case TK_AGG_FUNCTION: - case TK_FUNCTION: { - ExprList *pFarg; /* List of function arguments */ - if( ExprHasProperty(pExpr, EP_TokenOnly) ){ - pFarg = 0; - }else{ - pFarg = pExpr->x.pList; - } - if( pExpr->op==TK_AGG_FUNCTION ){ - sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", - pExpr->op2, pExpr->u.zToken); - }else{ - sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); - } - if( pFarg ){ - sqlite3TreeViewExprList(pView, pFarg, 0, 0); - } - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: { - sqlite3TreeViewLine(pView, "EXISTS-expr"); - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - break; - } - case TK_SELECT: { - sqlite3TreeViewLine(pView, "SELECT-expr"); - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - break; - } - case TK_IN: { - sqlite3TreeViewLine(pView, "IN"); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); - }else{ - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); - } - break; - } -#endif /* SQLITE_OMIT_SUBQUERY */ - - /* - ** x BETWEEN y AND z - ** - ** This is equivalent to - ** - ** x>=y AND x<=z - ** - ** X is stored in pExpr->pLeft. - ** Y is stored in pExpr->pList->a[0].pExpr. - ** Z is stored in pExpr->pList->a[1].pExpr. - */ - case TK_BETWEEN: { - Expr *pX = pExpr->pLeft; - Expr *pY = pExpr->x.pList->a[0].pExpr; - Expr *pZ = pExpr->x.pList->a[1].pExpr; - sqlite3TreeViewLine(pView, "BETWEEN"); - sqlite3TreeViewExpr(pView, pX, 1); - sqlite3TreeViewExpr(pView, pY, 1); - sqlite3TreeViewExpr(pView, pZ, 0); - break; - } - case TK_TRIGGER: { - /* If the opcode is TK_TRIGGER, then the expression is a reference - ** to a column in the new.* or old.* pseudo-tables available to - ** trigger programs. In this case Expr.iTable is set to 1 for the - ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn - ** is set to the column of the pseudo-table to read, or to -1 to - ** read the rowid field. - */ - sqlite3TreeViewLine(pView, "%s(%d)", - pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); - break; - } - case TK_CASE: { - sqlite3TreeViewLine(pView, "CASE"); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); - break; - } -#ifndef SQLITE_OMIT_TRIGGER - case TK_RAISE: { - const char *zType = "unk"; - switch( pExpr->affinity ){ - case OE_Rollback: zType = "rollback"; break; - case OE_Abort: zType = "abort"; break; - case OE_Fail: zType = "fail"; break; - case OE_Ignore: zType = "ignore"; break; - } - sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken); - break; - } -#endif - default: { - sqlite3TreeViewLine(pView, "op=%d", pExpr->op); - break; - } - } - if( zBinOp ){ - sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); - sqlite3TreeViewExpr(pView, pExpr->pRight, 0); - }else if( zUniOp ){ - sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); - sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); - } - sqlite3TreeViewPop(pView); -} - -/* -** Generate a human-readable explanation of an expression list. -*/ -SQLITE_PRIVATE void sqlite3TreeViewExprList( - TreeView *pView, - const ExprList *pList, - u8 moreToFollow, - const char *zLabel -){ - int i; - pView = sqlite3TreeViewPush(pView, moreToFollow); - if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; - if( pList==0 ){ - sqlite3TreeViewLine(pView, "%s (empty)", zLabel); - }else{ - sqlite3TreeViewLine(pView, "%s", zLabel); - for(i=0; inExpr; i++){ - int j = pList->a[i].u.x.iOrderByCol; - if( j ){ - sqlite3TreeViewPush(pView, 0); - sqlite3TreeViewLine(pView, "iOrderByCol=%d", j); - } - sqlite3TreeViewExpr(pView, pList->a[i].pExpr, inExpr-1); - if( j ) sqlite3TreeViewPop(pView); - } - } - sqlite3TreeViewPop(pView); -} - -#endif /* SQLITE_DEBUG */ - -/************** End of treeview.c ********************************************/ /************** Begin file random.c ******************************************/ /* ** 2001 September 15 @@ -24076,7 +21305,6 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList( ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. */ -/* #include "sqliteInt.h" */ /* All threads share a single random number generator. @@ -24091,7 +21319,7 @@ static SQLITE_WSD struct sqlite3PrngType { /* ** Return N random bytes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ +SQLITE_API void sqlite3_randomness(int N, void *pBuf){ unsigned char t; unsigned char *zBuf = pBuf; @@ -24109,19 +21337,11 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){ #endif #if SQLITE_THREADSAFE - sqlite3_mutex *mutex; -#endif - -#ifndef SQLITE_OMIT_AUTOINIT - if( sqlite3_initialize() ) return; -#endif - -#if SQLITE_THREADSAFE - mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); -#endif - + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); sqlite3_mutex_enter(mutex); - if( N<=0 || pBuf==0 ){ +#endif + + if( N<=0 ){ wsdPrng.isInit = 0; sqlite3_mutex_leave(mutex); return; @@ -24195,283 +21415,6 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ #endif /* SQLITE_OMIT_BUILTIN_TEST */ /************** End of random.c **********************************************/ -/************** Begin file threads.c *****************************************/ -/* -** 2012 July 21 -** -** 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 presents a simple cross-platform threading interface for -** use internally by SQLite. -** -** A "thread" can be created using sqlite3ThreadCreate(). This thread -** runs independently of its creator until it is joined using -** sqlite3ThreadJoin(), at which point it terminates. -** -** Threads do not have to be real. It could be that the work of the -** "thread" is done by the main thread at either the sqlite3ThreadCreate() -** or sqlite3ThreadJoin() call. This is, in fact, what happens in -** single threaded systems. Nothing in SQLite requires multiple threads. -** This interface exists so that applications that want to take advantage -** of multiple cores can do so, while also allowing applications to stay -** single-threaded if desired. -*/ -/* #include "sqliteInt.h" */ -#if SQLITE_OS_WIN -/* # include "os_win.h" */ -#endif - -#if SQLITE_MAX_WORKER_THREADS>0 - -/********************************* Unix Pthreads ****************************/ -#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 - -#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ -/* #include */ - -/* A running thread */ -struct SQLiteThread { - pthread_t tid; /* Thread ID */ - int done; /* Set to true when thread finishes */ - void *pOut; /* Result returned by the thread */ - void *(*xTask)(void*); /* The thread routine */ - void *pIn; /* Argument to the thread */ -}; - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - int rc; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - /* This routine is never used in single-threaded mode */ - assert( sqlite3GlobalConfig.bCoreMutex!=0 ); - - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; - memset(p, 0, sizeof(*p)); - p->xTask = xTask; - p->pIn = pIn; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a - ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically - ** for testing purposes. */ - if( sqlite3FaultSim(200) ){ - rc = 1; - }else{ - rc = pthread_create(&p->tid, 0, xTask, pIn); - } - if( rc ){ - p->done = 1; - p->pOut = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - int rc; - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; - if( p->done ){ - *ppOut = p->pOut; - rc = SQLITE_OK; - }else{ - rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK; - } - sqlite3_free(p); - return rc; -} - -#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ -/******************************** End Unix Pthreads *************************/ - - -/********************************* Win32 Threads ****************************/ -#if SQLITE_OS_WIN_THREADS - -#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ -#include - -/* A running thread */ -struct SQLiteThread { - void *tid; /* The thread handle */ - unsigned id; /* The thread identifier */ - void *(*xTask)(void*); /* The routine to run as a thread */ - void *pIn; /* Argument to xTask */ - void *pResult; /* Result of xTask */ -}; - -/* Thread procedure Win32 compatibility shim */ -static unsigned __stdcall sqlite3ThreadProc( - void *pArg /* IN: Pointer to the SQLiteThread structure */ -){ - SQLiteThread *p = (SQLiteThread *)pArg; - - assert( p!=0 ); -#if 0 - /* - ** This assert appears to trigger spuriously on certain - ** versions of Windows, possibly due to _beginthreadex() - ** and/or CreateThread() not fully setting their thread - ** ID parameter before starting the thread. - */ - assert( p->id==GetCurrentThreadId() ); -#endif - assert( p->xTask!=0 ); - p->pResult = p->xTask(p->pIn); - - _endthreadex(0); - return 0; /* NOT REACHED */ -} - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; - /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a - ** function that returns SQLITE_ERROR when passed the argument 200, that - ** forces worker threads to run sequentially and deterministically - ** (via the sqlite3FaultSim() term of the conditional) for testing - ** purposes. */ - if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){ - memset(p, 0, sizeof(*p)); - }else{ - p->xTask = xTask; - p->pIn = pIn; - p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id); - if( p->tid==0 ){ - memset(p, 0, sizeof(*p)); - } - } - if( p->xTask==0 ){ - p->id = GetCurrentThreadId(); - p->pResult = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */ - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - DWORD rc; - BOOL bRc; - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; - if( p->xTask==0 ){ - /* assert( p->id==GetCurrentThreadId() ); */ - rc = WAIT_OBJECT_0; - assert( p->tid==0 ); - }else{ - assert( p->id!=0 && p->id!=GetCurrentThreadId() ); - rc = sqlite3Win32Wait((HANDLE)p->tid); - assert( rc!=WAIT_IO_COMPLETION ); - bRc = CloseHandle((HANDLE)p->tid); - assert( bRc ); - } - if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult; - sqlite3_free(p); - return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; -} - -#endif /* SQLITE_OS_WIN_THREADS */ -/******************************** End Win32 Threads *************************/ - - -/********************************* Single-Threaded **************************/ -#ifndef SQLITE_THREADS_IMPLEMENTED -/* -** This implementation does not actually create a new thread. It does the -** work of the thread in the main thread, when either the thread is created -** or when it is joined -*/ - -/* A running thread */ -struct SQLiteThread { - void *(*xTask)(void*); /* The routine to run as a thread */ - void *pIn; /* Argument to xTask */ - void *pResult; /* Result of xTask */ -}; - -/* Create a new thread */ -SQLITE_PRIVATE int sqlite3ThreadCreate( - SQLiteThread **ppThread, /* OUT: Write the thread object here */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - SQLiteThread *p; - - assert( ppThread!=0 ); - assert( xTask!=0 ); - *ppThread = 0; - p = sqlite3Malloc(sizeof(*p)); - if( p==0 ) return SQLITE_NOMEM; - if( (SQLITE_PTR_TO_INT(p)/17)&1 ){ - p->xTask = xTask; - p->pIn = pIn; - }else{ - p->xTask = 0; - p->pResult = xTask(pIn); - } - *ppThread = p; - return SQLITE_OK; -} - -/* Get the results of the thread */ -SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ - - assert( ppOut!=0 ); - if( NEVER(p==0) ) return SQLITE_NOMEM; - if( p->xTask ){ - *ppOut = p->xTask(p->pIn); - }else{ - *ppOut = p->pResult; - } - sqlite3_free(p); - -#if defined(SQLITE_TEST) - { - void *pTstAlloc = sqlite3Malloc(10); - if (!pTstAlloc) return SQLITE_NOMEM; - sqlite3_free(pTstAlloc); - } -#endif - - return SQLITE_OK; -} - -#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */ -/****************************** End Single-Threaded *************************/ -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - -/************** End of threads.c *********************************************/ /************** Begin file utf.c *********************************************/ /* ** 2004 April 13 @@ -24508,17 +21451,15 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ ** 0xfe 0xff big-endian utf-16 follows ** */ -/* #include "sqliteInt.h" */ /* #include */ -/* #include "vdbeInt.h" */ -#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0 +#ifndef SQLITE_AMALGAMATION /* ** The following constant value is used by the SQLITE_BIGENDIAN and ** SQLITE_LITTLEENDIAN macros. */ SQLITE_PRIVATE const int sqlite3one = 1; -#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */ +#endif /* SQLITE_AMALGAMATION */ /* ** This lookup table is used to help decode the first byte of @@ -24623,8 +21564,8 @@ static const unsigned char sqlite3Utf8Trans1[] = { ** and rendered as themselves even though they are technically ** invalid characters. ** -** * This routine accepts over-length UTF8 encodings -** for unicode values 0x80 and greater. It does not change over-length +** * This routine accepts an infinite number of different UTF8 encodings +** for unicode values 0x80 and greater. It do not change over-length ** encodings to 0xfffd as some systems recommend. */ #define READ_UTF8(zIn, zTerm, c) \ @@ -24674,7 +21615,7 @@ SQLITE_PRIVATE u32 sqlite3Utf8Read( ** desiredEnc. It is an error if the string is already of the desired ** encoding, or if *pMem does not contain a string value. */ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ +SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ int len; /* Maximum length of output string in bytes */ unsigned char *zOut; /* Output buffer */ unsigned char *zIn; /* Input iterator */ @@ -24789,13 +21730,12 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired *z = 0; assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); - c = pMem->flags; sqlite3VdbeMemRelease(pMem); - pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); + pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); pMem->enc = desiredEnc; + pMem->flags |= (MEM_Term); pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); translate_out: #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) @@ -25023,9 +21963,8 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){ ** strings, and stuff like that. ** */ -/* #include "sqliteInt.h" */ /* #include */ -#if HAVE_ISNAN || SQLITE_HAVE_ISNAN +#ifdef SQLITE_HAVE_ISNAN # include #endif @@ -25066,7 +22005,7 @@ SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ */ SQLITE_PRIVATE int sqlite3IsNaN(double x){ int rc; /* The value return */ -#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN +#if !defined(SQLITE_HAVE_ISNAN) /* ** Systems that support the isnan() library function should probably ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have @@ -25096,9 +22035,9 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){ volatile double y = x; volatile double z = y; rc = (y!=z); -#else /* if HAVE_ISNAN */ +#else /* if defined(SQLITE_HAVE_ISNAN) */ rc = isnan(x); -#endif /* HAVE_ISNAN */ +#endif /* SQLITE_HAVE_ISNAN */ testcase( rc ); return rc; } @@ -25113,17 +22052,10 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){ ** than 1GiB) the value returned might be less than the true string length. */ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){ + const char *z2 = z; if( z==0 ) return 0; - return 0x3fffffff & (int)strlen(z); -} - -/* -** Set the current error code to err_code and clear any prior error message. -*/ -SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ - assert( db!=0 ); - db->errCode = err_code; - if( db->pErr ) sqlite3ValueSetNull(db->pErr); + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); } /* @@ -25147,18 +22079,18 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ -SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ +SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ assert( db!=0 ); db->errCode = err_code; - if( zFormat==0 ){ - sqlite3Error(db, err_code); - }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ + if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); + }else if( db->pErr ){ + sqlite3ValueSetNull(db->pErr); } } @@ -25172,12 +22104,12 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *z ** %T Insert a token ** %S Insert the first element of a SrcList ** -** This function should be used to report any error that occurs while +** This function should be used to report any error that occurs whilst ** compiling an SQL statement (i.e. within sqlite3_prepare()). The ** last thing the sqlite3_prepare() function does is copy the error ** stored by this function into the database handle using sqlite3Error(). -** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used -** during statement execution (sqlite3_step() etc.). +** Function sqlite3Error() should be used during statement execution +** (sqlite3_step() etc.). */ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; @@ -25210,7 +22142,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ ** occur. ** ** 2002-Feb-14: This routine is extended to remove MS-Access style -** brackets from around identifiers. For example: "[a-b-c]" becomes +** brackets from around identifers. For example: "[a-b-c]" becomes ** "a-b-c". */ SQLITE_PRIVATE int sqlite3Dequote(char *z){ @@ -25255,25 +22187,15 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){ ** case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){ +SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ register unsigned char *a, *b; - if( zLeft==0 ){ - return zRight ? -1 : 0; - }else if( zRight==0 ){ - return 1; - } a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return UpperToLower[*a] - UpperToLower[*b]; } -SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ +SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; - if( zLeft==0 ){ - return zRight ? -1 : 0; - }else if( zRight==0 ){ - return 1; - } a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } @@ -25500,9 +22422,9 @@ static int compare2pow63(const char *zNum, int incr){ return c; } + /* -** Convert zNum to a 64-bit signed integer. zNum must be decimal. This -** routine does *not* accept hexadecimal notation. +** Convert zNum to a 64-bit signed integer. ** ** If the zNum value is representable as a 64-bit twos-complement ** integer, then write that value into *pNum and return 0. @@ -25563,8 +22485,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc testcase( i==18 ); testcase( i==19 ); testcase( i==20 ); - if( (c!=0 && &zNum[i]19*incr || nonNum ){ + if( (c!=0 && &zNum[i]19*incr || nonNum ){ /* zNum is empty or contains non-numeric text or is longer ** than 19 digits (thus guaranteeing that it is too large) */ return 1; @@ -25591,44 +22512,10 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc } } -/* -** Transform a UTF-8 integer literal, in either decimal or hexadecimal, -** into a 64-bit signed integer. This routine accepts hexadecimal literals, -** whereas sqlite3Atoi64() does not. -** -** Returns: -** -** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Integer too large for a 64-bit signed integer or is malformed -** 2 Special case of 9223372036854775808 -*/ -SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ -#ifndef SQLITE_OMIT_HEX_INTEGER - if( z[0]=='0' - && (z[1]=='x' || z[1]=='X') - && sqlite3Isxdigit(z[2]) - ){ - u64 u = 0; - int i, k; - for(i=2; z[i]=='0'; i++){} - for(k=i; sqlite3Isxdigit(z[k]); k++){ - u = u*16 + sqlite3HexToInt(z[k]); - } - memcpy(pOut, &u, 8); - return (z[k]==0 && k-i<=16) ? 0 : 1; - }else -#endif /* SQLITE_OMIT_HEX_INTEGER */ - { - return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); - } -} - /* ** If zNum represents an integer that will fit in 32-bits, then set ** *pValue to that integer and return true. Otherwise return false. ** -** This routine accepts both decimal and hexadecimal notation for integers. -** ** Any non-numeric characters that following zNum are ignored. ** This is different from sqlite3Atoi64() which requires the ** input number to be zero-terminated. @@ -25643,25 +22530,6 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ }else if( zNum[0]=='+' ){ zNum++; } -#ifndef SQLITE_OMIT_HEX_INTEGER - else if( zNum[0]=='0' - && (zNum[1]=='x' || zNum[1]=='X') - && sqlite3Isxdigit(zNum[2]) - ){ - u32 u = 0; - zNum += 2; - while( zNum[0]=='0' ) zNum++; - for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ - u = u*16 + sqlite3HexToInt(zNum[i]); - } - if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ - memcpy(pValue, &u, 4); - return 1; - }else{ - return 0; - } - } -#endif while( zNum[0]=='0' ) zNum++; for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ v = v*10 + c; @@ -25726,7 +22594,7 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ ** bit clear. Except, if we get to the 9th byte, it stores the full ** 8 bits and is the last byte. */ -static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ +SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){ int i, j, n; u8 buf[10]; if( v & (((u64)0xff000000)<<32) ){ @@ -25750,17 +22618,28 @@ static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ } return n; } -SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){ - if( v<=0x7f ){ - p[0] = v&0x7f; + +/* +** This routine is a faster version of sqlite3PutVarint() that only +** works for 32-bit positive integers and which is optimized for +** the common case of small integers. A MACRO version, putVarint32, +** is provided which inlines the single-byte case. All code should use +** the MACRO version as this function assumes the single-byte case has +** already been handled. +*/ +SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){ +#ifndef putVarint32 + if( (v & ~0x7f)==0 ){ + p[0] = v; return 1; } - if( v<=0x3fff ){ - p[0] = ((v>>7)&0x7f)|0x80; - p[1] = v&0x7f; +#endif + if( (v & ~0x3fff)==0 ){ + p[0] = (u8)((v>>7) | 0x80); + p[1] = (u8)(v & 0x7f); return 2; } - return putVarint64(p,v); + return sqlite3PutVarint(p, v); } /* @@ -25853,8 +22732,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ /* a: p0<<28 | p2<<14 | p4 (unmasked) */ if (!(a&0x80)) { - /* we can skip these cause they were (effectively) done above - ** while calculating s */ + /* we can skip these cause they were (effectively) done above in calc'ing s */ /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ /* b &= (0x7f<<14)|(0x7f); */ b = b<<7; @@ -26075,8 +22953,11 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ ** 64-bit integer. */ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ - int i; - for(i=1; (v >>= 7)!=0; i++){ assert( i<9 ); } + int i = 0; + do{ + i++; + v >>= 7; + }while( v!=0 && ALWAYS(i<9) ); return i; } @@ -26085,40 +22966,14 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){ ** Read or write a four-byte big-endian integer value. */ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){ -#if SQLITE_BYTEORDER==4321 - u32 x; - memcpy(&x,p,4); - return x; -#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ - && defined(__GNUC__) && GCC_VERSION>=4003000 - u32 x; - memcpy(&x,p,4); - return __builtin_bswap32(x); -#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ - && defined(_MSC_VER) && _MSC_VER>=1300 - u32 x; - memcpy(&x,p,4); - return _byteswap_ulong(x); -#else testcase( p[0]&0x80 ); return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; -#endif } SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ -#if SQLITE_BYTEORDER==4321 - memcpy(p,&v,4); -#elif SQLITE_BYTEORDER==1234 && defined(__GNUC__) && GCC_VERSION>=4003000 - u32 x = __builtin_bswap32(v); - memcpy(p,&x,4); -#elif SQLITE_BYTEORDER==1234 && defined(_MSC_VER) && _MSC_VER>=1300 - u32 x = _byteswap_ulong(v); - memcpy(p,&x,4); -#else p[0] = (u8)(v>>24); p[1] = (u8)(v>>16); p[2] = (u8)(v>>8); p[3] = (u8)v; -#endif } @@ -26421,7 +23276,6 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ ** This is the implementation of generic hash-tables ** used in SQLite. */ -/* #include "sqliteInt.h" */ /* #include */ /* Turn bulk memory into a hash table object by initializing the @@ -26461,11 +23315,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ /* ** The hashing function. */ -static unsigned int strHash(const char *z){ +static unsigned int strHash(const char *z, int nKey){ unsigned int h = 0; - unsigned char c; - while( (c = (unsigned char)*z++)!=0 ){ - h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; + assert( nKey>=0 ); + while( nKey > 0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; + nKey--; } return h; } @@ -26537,7 +23392,7 @@ static int rehash(Hash *pH, unsigned int new_size){ pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); memset(new_ht, 0, new_size*sizeof(struct _ht)); for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - unsigned int h = strHash(elem->pKey) % new_size; + unsigned int h = strHash(elem->pKey, elem->nKey) % new_size; next_elem = elem->next; insertElement(pH, &new_ht[h], elem); } @@ -26545,33 +23400,28 @@ static int rehash(Hash *pH, unsigned int new_size){ } /* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key is -** also computed and returned in the *pH parameter. +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. */ -static HashElem *findElementWithHash( +static HashElem *findElementGivenHash( const Hash *pH, /* The pH to be searched */ const char *pKey, /* The key we are searching for */ - unsigned int *pHash /* Write the hash value here */ + int nKey, /* Bytes in key (not counting zero terminator) */ + unsigned int h /* The hash for this key. */ ){ HashElem *elem; /* Used to loop thru the element list */ int count; /* Number of elements left to test */ - unsigned int h; /* The computed hash */ if( pH->ht ){ - struct _ht *pEntry; - h = strHash(pKey) % pH->htsize; - pEntry = &pH->ht[h]; + struct _ht *pEntry = &pH->ht[h]; elem = pEntry->chain; count = pEntry->count; }else{ - h = 0; elem = pH->first; count = pH->count; } - *pHash = h; - while( count-- ){ - assert( elem!=0 ); - if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ + while( count-- && ALWAYS(elem) ){ + if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ return elem; } elem = elem->next; @@ -26614,20 +23464,26 @@ static void removeElementGivenHash( } /* Attempt to locate an element of the hash table pH with a key -** that matches pKey. Return the data for this element if it is +** that matches pKey,nKey. Return the data for this element if it is ** found, or NULL if there is no match. */ -SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){ +SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ HashElem *elem; /* The element that matches key */ unsigned int h; /* A hash on key */ assert( pH!=0 ); assert( pKey!=0 ); - elem = findElementWithHash(pH, pKey, &h); + assert( nKey>=0 ); + if( pH->ht ){ + h = strHash(pKey, nKey) % pH->htsize; + }else{ + h = 0; + } + elem = findElementGivenHash(pH, pKey, nKey, h); return elem ? elem->data : 0; } -/* Insert an element into the hash table pH. The key is pKey +/* Insert an element into the hash table pH. The key is pKey,nKey ** and the data is "data". ** ** If no element exists with a matching key, then a new @@ -26641,14 +23497,20 @@ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){ ** If the "data" parameter to this function is NULL, then the ** element corresponding to "key" is removed from the hash table. */ -SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ +SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ unsigned int h; /* the hash of the key modulo hash table size */ HashElem *elem; /* Used to loop thru the element list */ HashElem *new_elem; /* New element added to the pH */ assert( pH!=0 ); assert( pKey!=0 ); - elem = findElementWithHash(pH,pKey,&h); + assert( nKey>=0 ); + if( pH->htsize ){ + h = strHash(pKey, nKey) % pH->htsize; + }else{ + h = 0; + } + elem = findElementGivenHash(pH,pKey,nKey,h); if( elem ){ void *old_data = elem->data; if( data==0 ){ @@ -26656,6 +23518,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ }else{ elem->data = data; elem->pKey = pKey; + assert(nKey==elem->nKey); } return old_data; } @@ -26663,25 +23526,28 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); if( new_elem==0 ) return data; new_elem->pKey = pKey; + new_elem->nKey = nKey; new_elem->data = data; pH->count++; if( pH->count>=10 && pH->count > 2*pH->htsize ){ if( rehash(pH, pH->count*2) ){ assert( pH->htsize>0 ); - h = strHash(pKey) % pH->htsize; + h = strHash(pKey, nKey) % pH->htsize; } } - insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem); + if( pH->ht ){ + insertElement(pH, &pH->ht[h], new_elem); + }else{ + insertElement(pH, 0, new_elem); + } return 0; } /************** End of hash.c ************************************************/ /************** Begin file opcodes.c *****************************************/ /* Automatically generated. Do not edit */ -/* See the tool/mkopcodec.tcl script for details. */ -#if !defined(SQLITE_OMIT_EXPLAIN) \ - || defined(VDBE_PROFILE) \ - || defined(SQLITE_DEBUG) +/* See the mkopcodec.awk script for details. */ +#if !defined(SQLITE_OMIT_EXPLAIN) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) #if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG) # define OpHelp(X) "\0" X #else @@ -26689,168 +23555,163 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ #endif SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ static const char *const azName[] = { "?", - /* 1 */ "Savepoint" OpHelp(""), - /* 2 */ "AutoCommit" OpHelp(""), - /* 3 */ "Transaction" OpHelp(""), - /* 4 */ "SorterNext" OpHelp(""), - /* 5 */ "PrevIfOpen" OpHelp(""), - /* 6 */ "NextIfOpen" OpHelp(""), - /* 7 */ "Prev" OpHelp(""), - /* 8 */ "Next" OpHelp(""), - /* 9 */ "Checkpoint" OpHelp(""), - /* 10 */ "JournalMode" OpHelp(""), - /* 11 */ "Vacuum" OpHelp(""), - /* 12 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), - /* 13 */ "VUpdate" OpHelp("data=r[P3@P2]"), - /* 14 */ "Goto" OpHelp(""), - /* 15 */ "Gosub" OpHelp(""), - /* 16 */ "Return" OpHelp(""), - /* 17 */ "InitCoroutine" OpHelp(""), - /* 18 */ "EndCoroutine" OpHelp(""), - /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "Yield" OpHelp(""), - /* 21 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 22 */ "Halt" OpHelp(""), - /* 23 */ "Integer" OpHelp("r[P2]=P1"), - /* 24 */ "Int64" OpHelp("r[P2]=P4"), - /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 27 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 28 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 29 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 30 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 31 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 32 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 33 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 34 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 35 */ "CollSeq" OpHelp(""), - /* 36 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 37 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 38 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 39 */ "MustBeInt" OpHelp(""), - /* 40 */ "RealAffinity" OpHelp(""), - /* 41 */ "Cast" OpHelp("affinity(r[P1])"), - /* 42 */ "Permutation" OpHelp(""), - /* 43 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 44 */ "Jump" OpHelp(""), - /* 45 */ "Once" OpHelp(""), - /* 46 */ "If" OpHelp(""), - /* 47 */ "IfNot" OpHelp(""), - /* 48 */ "Column" OpHelp("r[P3]=PX"), - /* 49 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 50 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 51 */ "Count" OpHelp("r[P2]=count()"), - /* 52 */ "ReadCookie" OpHelp(""), - /* 53 */ "SetCookie" OpHelp(""), - /* 54 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 55 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 56 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 57 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 58 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 59 */ "SorterOpen" OpHelp(""), - /* 60 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 61 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 62 */ "Close" OpHelp(""), - /* 63 */ "ColumnsUsed" OpHelp(""), - /* 64 */ "SeekLT" OpHelp("key=r[P3@P4]"), - /* 65 */ "SeekLE" OpHelp("key=r[P3@P4]"), - /* 66 */ "SeekGE" OpHelp("key=r[P3@P4]"), - /* 67 */ "SeekGT" OpHelp("key=r[P3@P4]"), - /* 68 */ "Seek" OpHelp("intkey=r[P2]"), - /* 69 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 70 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 73 */ "Found" OpHelp("key=r[P3@P4]"), - /* 74 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 75 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), - /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), - /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), - /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), - /* 82 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), - /* 84 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 95 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), - /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 99 */ "Delete" OpHelp(""), - /* 100 */ "ResetCount" OpHelp(""), - /* 101 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 102 */ "SorterData" OpHelp("r[P2]=data"), - /* 103 */ "RowKey" OpHelp("r[P2]=key"), - /* 104 */ "RowData" OpHelp("r[P2]=data"), - /* 105 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 106 */ "NullRow" OpHelp(""), - /* 107 */ "Last" OpHelp(""), - /* 108 */ "SorterSort" OpHelp(""), - /* 109 */ "Sort" OpHelp(""), - /* 110 */ "Rewind" OpHelp(""), - /* 111 */ "SorterInsert" OpHelp(""), - /* 112 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 113 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 114 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 115 */ "IdxLE" OpHelp("key=r[P3@P4]"), - /* 116 */ "IdxGT" OpHelp("key=r[P3@P4]"), - /* 117 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 118 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 119 */ "Destroy" OpHelp(""), - /* 120 */ "Clear" OpHelp(""), - /* 121 */ "ResetSorter" OpHelp(""), - /* 122 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), - /* 123 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), - /* 124 */ "ParseSchema" OpHelp(""), - /* 125 */ "LoadAnalysis" OpHelp(""), - /* 126 */ "DropTable" OpHelp(""), - /* 127 */ "DropIndex" OpHelp(""), - /* 128 */ "DropTrigger" OpHelp(""), - /* 129 */ "IntegrityCk" OpHelp(""), - /* 130 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 131 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 132 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 133 */ "Real" OpHelp("r[P2]=P4"), - /* 134 */ "Program" OpHelp(""), - /* 135 */ "Param" OpHelp(""), - /* 136 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 137 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 138 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 139 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 140 */ "SetIfNotPos" OpHelp("if r[P1]<=0 then r[P2]=P3"), - /* 141 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), - /* 142 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 143 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), - /* 144 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 145 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 146 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 147 */ "IncrVacuum" OpHelp(""), - /* 148 */ "Expire" OpHelp(""), - /* 149 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 150 */ "VBegin" OpHelp(""), - /* 151 */ "VCreate" OpHelp(""), - /* 152 */ "VDestroy" OpHelp(""), - /* 153 */ "VOpen" OpHelp(""), - /* 154 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 155 */ "VNext" OpHelp(""), - /* 156 */ "VRename" OpHelp(""), - /* 157 */ "Pagecount" OpHelp(""), - /* 158 */ "MaxPgcnt" OpHelp(""), - /* 159 */ "Init" OpHelp("Start at P2"), - /* 160 */ "CursorHint" OpHelp(""), - /* 161 */ "Noop" OpHelp(""), - /* 162 */ "Explain" OpHelp(""), + /* 1 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 2 */ "Savepoint" OpHelp(""), + /* 3 */ "AutoCommit" OpHelp(""), + /* 4 */ "Transaction" OpHelp(""), + /* 5 */ "SorterNext" OpHelp(""), + /* 6 */ "PrevIfOpen" OpHelp(""), + /* 7 */ "NextIfOpen" OpHelp(""), + /* 8 */ "Prev" OpHelp(""), + /* 9 */ "Next" OpHelp(""), + /* 10 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 11 */ "Checkpoint" OpHelp(""), + /* 12 */ "JournalMode" OpHelp(""), + /* 13 */ "Vacuum" OpHelp(""), + /* 14 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), + /* 15 */ "VUpdate" OpHelp("data=r[P3@P2]"), + /* 16 */ "Goto" OpHelp(""), + /* 17 */ "Gosub" OpHelp(""), + /* 18 */ "Return" OpHelp(""), + /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), + /* 20 */ "InitCoroutine" OpHelp(""), + /* 21 */ "EndCoroutine" OpHelp(""), + /* 22 */ "Yield" OpHelp(""), + /* 23 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 24 */ "Halt" OpHelp(""), + /* 25 */ "Integer" OpHelp("r[P2]=P1"), + /* 26 */ "Int64" OpHelp("r[P2]=P4"), + /* 27 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 28 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 29 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 30 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 31 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 32 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 33 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 34 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 35 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 36 */ "CollSeq" OpHelp(""), + /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 38 */ "MustBeInt" OpHelp(""), + /* 39 */ "RealAffinity" OpHelp(""), + /* 40 */ "Permutation" OpHelp(""), + /* 41 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 42 */ "Jump" OpHelp(""), + /* 43 */ "Once" OpHelp(""), + /* 44 */ "If" OpHelp(""), + /* 45 */ "IfNot" OpHelp(""), + /* 46 */ "Column" OpHelp("r[P3]=PX"), + /* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 49 */ "Count" OpHelp("r[P2]=count()"), + /* 50 */ "ReadCookie" OpHelp(""), + /* 51 */ "SetCookie" OpHelp(""), + /* 52 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 53 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 54 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 55 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 56 */ "SorterOpen" OpHelp(""), + /* 57 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 58 */ "Close" OpHelp(""), + /* 59 */ "SeekLT" OpHelp(""), + /* 60 */ "SeekLE" OpHelp(""), + /* 61 */ "SeekGE" OpHelp(""), + /* 62 */ "SeekGT" OpHelp(""), + /* 63 */ "Seek" OpHelp("intkey=r[P2]"), + /* 64 */ "NoConflict" OpHelp("key=r[P3@P4]"), + /* 65 */ "NotFound" OpHelp("key=r[P3@P4]"), + /* 66 */ "Found" OpHelp("key=r[P3@P4]"), + /* 67 */ "NotExists" OpHelp("intkey=r[P3]"), + /* 68 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 69 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 70 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), + /* 73 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 74 */ "Delete" OpHelp(""), + /* 75 */ "ResetCount" OpHelp(""), + /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), + /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), + /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), + /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), + /* 82 */ "Lt" OpHelp("if r[P1]=r[P3] goto P2"), + /* 84 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"), + /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), + /* 95 */ "SorterData" OpHelp("r[P2]=data"), + /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), + /* 97 */ "String8" OpHelp("r[P2]='P4'"), + /* 98 */ "RowKey" OpHelp("r[P2]=key"), + /* 99 */ "RowData" OpHelp("r[P2]=data"), + /* 100 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 101 */ "NullRow" OpHelp(""), + /* 102 */ "Last" OpHelp(""), + /* 103 */ "SorterSort" OpHelp(""), + /* 104 */ "Sort" OpHelp(""), + /* 105 */ "Rewind" OpHelp(""), + /* 106 */ "SorterInsert" OpHelp(""), + /* 107 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 108 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 109 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 110 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 111 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 112 */ "IdxLT" OpHelp("key=r[P3@P4]"), + /* 113 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 114 */ "Destroy" OpHelp(""), + /* 115 */ "Clear" OpHelp(""), + /* 116 */ "ResetSorter" OpHelp(""), + /* 117 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), + /* 118 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), + /* 119 */ "ParseSchema" OpHelp(""), + /* 120 */ "LoadAnalysis" OpHelp(""), + /* 121 */ "DropTable" OpHelp(""), + /* 122 */ "DropIndex" OpHelp(""), + /* 123 */ "DropTrigger" OpHelp(""), + /* 124 */ "IntegrityCk" OpHelp(""), + /* 125 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 126 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 127 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 128 */ "Program" OpHelp(""), + /* 129 */ "Param" OpHelp(""), + /* 130 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 131 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 132 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 133 */ "Real" OpHelp("r[P2]=P4"), + /* 134 */ "IfPos" OpHelp("if r[P1]>0 goto P2"), + /* 135 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"), + /* 136 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"), + /* 137 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 138 */ "IncrVacuum" OpHelp(""), + /* 139 */ "Expire" OpHelp(""), + /* 140 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 141 */ "VBegin" OpHelp(""), + /* 142 */ "VCreate" OpHelp(""), + /* 143 */ "ToText" OpHelp(""), + /* 144 */ "ToBlob" OpHelp(""), + /* 145 */ "ToNumeric" OpHelp(""), + /* 146 */ "ToInt" OpHelp(""), + /* 147 */ "ToReal" OpHelp(""), + /* 148 */ "VDestroy" OpHelp(""), + /* 149 */ "VOpen" OpHelp(""), + /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 151 */ "VNext" OpHelp(""), + /* 152 */ "VRename" OpHelp(""), + /* 153 */ "Pagecount" OpHelp(""), + /* 154 */ "MaxPgcnt" OpHelp(""), + /* 155 */ "Init" OpHelp("Start at P2"), + /* 156 */ "Noop" OpHelp(""), + /* 157 */ "Explain" OpHelp(""), }; return azName[i]; } @@ -26903,7 +23764,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ -/* #include "sqliteInt.h" */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* @@ -26931,6 +23791,18 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ # endif #endif +/* +** Define the OS_VXWORKS pre-processor macro to 1 if building on +** vxworks, or 0 otherwise. +*/ +#ifndef OS_VXWORKS +# if defined(__RTP__) || defined(_WRS_KERNEL) +# define OS_VXWORKS 1 +# else +# define OS_VXWORKS 0 +# endif +#endif + /* ** standard include files. */ @@ -26942,33 +23814,22 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ #include #include #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 -# include +#include #endif + #if SQLITE_ENABLE_LOCKING_STYLE # include -# include -# include +# if OS_VXWORKS +# include +# include +# else +# include +# include +# endif #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ - (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) -# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ - && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) -# define HAVE_GETHOSTUUID 1 -# else -# warning "gethostuuid() is disabled." -# endif -#endif - - -#if OS_VXWORKS -/* # include */ -# include -# include -#endif /* OS_VXWORKS */ - -#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE +#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) # include #endif @@ -27009,10 +23870,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ */ #define MAX_PATHNAME 512 -/* Always cast the getpid() return type for compatibility with -** kernel modules in VxWorks. */ -#define osGetpid(X) (pid_t)getpid() - /* ** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK @@ -27101,7 +23958,7 @@ struct unixFile { ** method was called. If xOpen() is called from a different process id, ** indicating that a fork() has occurred, the PRNG will be reset. */ -static pid_t randomnessPid = 0; +static int randomnessPid = 0; /* ** Allowed values for the unixFile.ctrlFlags bitmask: @@ -27118,6 +23975,7 @@ static pid_t randomnessPid = 0; #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */ /* ** Include code that is common to all os_*.c files @@ -27155,6 +24013,16 @@ static pid_t randomnessPid = 0; # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +#else +# define OSTRACE(X) +#endif + /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -27360,14 +24228,6 @@ SQLITE_API int sqlite3_open_file_count = 0; # endif #endif -/* -** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek() -** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined. -*/ -#ifdef __ANDROID__ -# define lseek lseek64 -#endif - /* ** Different Unix systems declare open() in different ways. Same use ** open(const char*,int,mode_t). Others use open(const char*,int,...). @@ -27380,6 +24240,15 @@ static int posixOpen(const char *zFile, int flags, int mode){ return open(zFile, flags, mode); } +/* +** On some systems, calls to fchown() will trigger a message in a security +** log if they come from non-root processes. So avoid calling fchown() if +** we are not running as root. +*/ +static int posixFchown(int fd, uid_t uid, gid_t gid){ + return geteuid() ? 0 : fchown(fd,uid,gid); +} + /* Forward reference */ static int openDirectory(const char*, int*); static int unixGetpagesize(void); @@ -27466,7 +24335,7 @@ static struct unix_syscall { #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ aSyscall[13].pCurrent) - { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, + { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE @@ -27488,50 +24357,29 @@ static struct unix_syscall { { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) - { "fchown", (sqlite3_syscall_ptr)fchown, 0 }, + { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) - { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, -#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) - #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, -#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) +#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent) { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, -#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) +#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent) #if HAVE_MREMAP { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, #else { "mremap", (sqlite3_syscall_ptr)0, 0 }, #endif -#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent) +#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent) +#endif { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 }, -#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent) - - { "readlink", (sqlite3_syscall_ptr)readlink, 0 }, -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) - -#endif +#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent) }; /* End of the overrideable system calls */ - -/* -** On some systems, calls to fchown() will trigger a message in a security -** log if they come from non-root processes. So avoid calling fchown() if -** we are not running as root. -*/ -static int robustFchown(int fd, uid_t uid, gid_t gid){ -#if OS_VXWORKS - return 0; -#else - return osGeteuid() ? 0 : osFchown(fd,uid,gid); -#endif -} - /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "unix" VFSes. Return SQLITE_OK opon successfully updating the @@ -27693,22 +24541,22 @@ static int robust_open(const char *z, int f, mode_t m){ ** unixEnterLeave() */ static void unixEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } static void unixLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #ifdef SQLITE_DEBUG static int unixMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #endif -#ifdef SQLITE_HAVE_OS_TRACE +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Helper function for printing out trace information from debugging -** binaries. This returns the string representation of the supplied +** binaries. This returns the string represetation of the supplied ** integer lock-type. */ static const char *azFileLock(int eFileLock){ @@ -27785,22 +24633,9 @@ static int lockTrace(int fd, int op, struct flock *p){ /* ** Retry ftruncate() calls that fail due to EINTR -** -** All calls to ftruncate() within this file should be made through -** this wrapper. On the Android platform, bypassing the logic below -** could lead to a corrupt database. */ static int robust_ftruncate(int h, sqlite3_int64 sz){ int rc; -#ifdef __ANDROID__ - /* On Android, ftruncate() always uses 32-bit offsets, even if - ** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to - ** truncate a file to any size larger than 2GiB. Silently ignore any - ** such attempts. */ - if( sz>(sqlite3_int64)0x7FFFFFFF ){ - rc = SQLITE_OK; - }else -#endif do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR ); return rc; } @@ -27816,12 +24651,23 @@ static int robust_ftruncate(int h, sqlite3_int64 sz){ ** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately. */ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { - assert( (sqliteIOErr == SQLITE_IOERR_LOCK) || - (sqliteIOErr == SQLITE_IOERR_UNLOCK) || - (sqliteIOErr == SQLITE_IOERR_RDLOCK) || - (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ); switch (posixError) { - case EACCES: +#if 0 + /* At one point this code was not commented out. In theory, this branch + ** should never be hit, as this function should only be called after + ** a locking-related function (i.e. fcntl()) has returned non-zero with + ** the value of errno as the first argument. Since a system call has failed, + ** errno should be non-zero. + ** + ** Despite this, if errno really is zero, we still don't want to return + ** SQLITE_OK. The system call failed, and *some* SQLite error should be + ** propagated back to the caller. Commenting this branch out means errno==0 + ** will be handled by the "default:" case below. + */ + case 0: + return SQLITE_OK; +#endif + case EAGAIN: case ETIMEDOUT: case EBUSY: @@ -27831,9 +24677,51 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) { * introspection, in which it actually means what it says */ return SQLITE_BUSY; + case EACCES: + /* EACCES is like EAGAIN during locking operations, but not any other time*/ + if( (sqliteIOErr == SQLITE_IOERR_LOCK) || + (sqliteIOErr == SQLITE_IOERR_UNLOCK) || + (sqliteIOErr == SQLITE_IOERR_RDLOCK) || + (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ + return SQLITE_BUSY; + } + /* else fall through */ case EPERM: return SQLITE_PERM; + /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And + ** this module never makes such a call. And the code in SQLite itself + ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons + ** this case is also commented out. If the system does set errno to EDEADLK, + ** the default SQLITE_IOERR_XXX code will be returned. */ +#if 0 + case EDEADLK: + return SQLITE_IOERR_BLOCKED; +#endif + +#if EOPNOTSUPP!=ENOTSUP + case EOPNOTSUPP: + /* something went terribly awry, unless during file system support + * introspection, in which it actually means what it says */ +#endif +#ifdef ENOTSUP + case ENOTSUP: + /* invalid fd, unless during file system support introspection, in which + * it actually means what it says */ +#endif + case EIO: + case EBADF: + case EINVAL: + case ENOTCONN: + case ENODEV: + case ENXIO: + case ENOENT: +#ifdef ESTALE /* ESTALE is not defined on Interix systems */ + case ESTALE: +#endif + case ENOSYS: + /* these should force the client to close the file and reconnect */ + default: return sqliteIOErr; } @@ -27925,7 +24813,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ assert( zAbsoluteName[0]=='/' ); n = (int)strlen(zAbsoluteName); - pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) ); + pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) ); if( pNew==0 ) return 0; pNew->zCanonicalName = (char*)&pNew[1]; memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); @@ -28117,7 +25005,7 @@ static unixInodeInfo *inodeList = 0; /* ** -** This function - unixLogErrorAtLine(), is only ever called via the macro +** This function - unixLogError_x(), is only ever called via the macro ** unixLogError(). ** ** It is invoked after an error occurs in an OS function and errno has been @@ -28204,14 +25092,6 @@ static void robust_close(unixFile *pFile, int h, int lineno){ } } -/* -** Set the pFile->lastErrno. Do this in a subroutine as that provides -** a convenient place to set a breakpoint. -*/ -static void storeLastErrno(unixFile *pFile, int error){ - pFile->lastErrno = error; -} - /* ** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. */ @@ -28285,8 +25165,8 @@ static int findInodeInfo( fd = pFile->h; rc = osFstat(fd, &statbuf); if( rc!=0 ){ - storeLastErrno(pFile, errno); -#if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS) + pFile->lastErrno = errno; +#ifdef EOVERFLOW if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; #endif return SQLITE_IOERR; @@ -28306,12 +25186,12 @@ static int findInodeInfo( if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); if( rc!=1 ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return SQLITE_IOERR; } rc = osFstat(fd, &statbuf); if( rc!=0 ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return SQLITE_IOERR; } } @@ -28329,7 +25209,7 @@ static int findInodeInfo( pInode = pInode->pNext; } if( pInode==0 ){ - pInode = sqlite3_malloc64( sizeof(*pInode) ); + pInode = sqlite3_malloc( sizeof(*pInode) ); if( pInode==0 ){ return SQLITE_NOMEM; } @@ -28351,13 +25231,9 @@ static int findInodeInfo( ** Return TRUE if pFile has been renamed or unlinked since it was first opened. */ static int fileHasMoved(unixFile *pFile){ -#if OS_VXWORKS - return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; -#else struct stat buf; return pFile->pInode!=0 && - (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); -#endif + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); } @@ -28373,21 +25249,30 @@ static int fileHasMoved(unixFile *pFile){ static void verifyDbFile(unixFile *pFile){ struct stat buf; int rc; + if( pFile->ctrlFlags & UNIXFILE_WARNED ){ + /* One or more of the following warnings have already been issued. Do not + ** repeat them so as not to clutter the error log */ + return; + } rc = osFstat(pFile->h, &buf); if( rc!=0 ){ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; return; } if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){ sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; return; } if( buf.st_nlink>1 ){ sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; return; } if( fileHasMoved(pFile) ){ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; return; } } @@ -28407,7 +25292,6 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); - assert( pFile->eFileLock<=SHARED_LOCK ); unixEnterMutex(); /* Because pFile->pInode is shared across threads */ /* Check if a thread in this process holds such a lock */ @@ -28426,7 +25310,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ rc = SQLITE_IOERR_CHECKRESERVEDLOCK; - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } @@ -28464,7 +25348,9 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ unixInodeInfo *pInode = pFile->pInode; assert( unixMutexHeld() ); assert( pInode!=0 ); - if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ + if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock) + && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0) + ){ if( pInode->bProcessLock==0 ){ struct flock lock; assert( pInode->nLock==0 ); @@ -28557,8 +25443,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared, - osGetpid(0))); + azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid())); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the end_lock: exit path, as @@ -28625,7 +25510,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } goto end_lock; } @@ -28660,7 +25545,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ if( rc ){ if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } goto end_lock; }else{ @@ -28693,7 +25578,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } } } @@ -28766,7 +25651,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - osGetpid(0))); + getpid())); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -28800,6 +25685,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** 4: [RRRR.] */ if( eFileLock==SHARED_LOCK ){ + #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE (void)handleNFSUnlock; assert( handleNFSUnlock==0 ); @@ -28816,7 +25702,9 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); + if( IS_LOCK_ERROR(rc) ){ + pFile->lastErrno = tErrno; + } goto end_unlock; } lock.l_type = F_RDLCK; @@ -28827,7 +25715,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } goto end_unlock; } @@ -28838,7 +25726,9 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ if( unixFileLock(pFile, &lock)==(-1) ){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); + if( IS_LOCK_ERROR(rc) ){ + pFile->lastErrno = tErrno; + } goto end_unlock; } }else @@ -28856,7 +25746,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** SQLITE_BUSY would confuse the upper layer (in practice it causes ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; goto end_unlock; } } @@ -28869,7 +25759,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = SHARED_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; goto end_unlock; } } @@ -28887,7 +25777,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } @@ -28956,13 +25846,6 @@ static int closeUnixFile(sqlite3_file *id){ vxworksReleaseFileId(pFile->pId); pFile->pId = 0; } -#endif -#ifdef SQLITE_UNLINK_AFTER_CLOSE - if( pFile->ctrlFlags & UNIXFILE_DELETE ){ - osUnlink(pFile->zPath); - sqlite3_free(*(char**)&pFile->zPath); - pFile->zPath = 0; - } #endif OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); @@ -29089,7 +25972,17 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); - reserved = osAccess((const char*)pFile->lockingContext, 0)==0; + + /* Check if a thread in this process holds such a lock */ + if( pFile->eFileLock>SHARED_LOCK ){ + /* Either this connection or some other connection in the same process + ** holds a lock on the file. No need to check further. */ + reserved = 1; + }else{ + /* The lock is held if and only if the lockfile exists */ + const char *zLockFile = (const char*)pFile->lockingContext; + reserved = osAccess(zLockFile, 0)==0; + } OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved)); *pResOut = reserved; return rc; @@ -29151,8 +26044,8 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) { rc = SQLITE_BUSY; } else { rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); - if( rc!=SQLITE_BUSY ){ - storeLastErrno(pFile, tErrno); + if( IS_LOCK_ERROR(rc) ){ + pFile->lastErrno = tErrno; } } return rc; @@ -29179,7 +26072,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); + pFile->eFileLock, getpid())); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -29198,13 +26091,15 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); rc = osRmdir(zLockFile); + if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile); if( rc<0 ){ int tErrno = errno; - if( tErrno==ENOENT ){ - rc = SQLITE_OK; - }else{ + rc = 0; + if( ENOENT != tErrno ){ rc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); + } + if( IS_LOCK_ERROR(rc) ){ + pFile->lastErrno = tErrno; } return rc; } @@ -29216,11 +26111,14 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { ** Close a file. Make sure the lock has been released before closing. */ static int dotlockClose(sqlite3_file *id) { - unixFile *pFile = (unixFile*)id; - assert( id!=0 ); - dotlockUnlock(id, NO_LOCK); - sqlite3_free(pFile->lockingContext); - return closeUnixFile(id); + int rc = SQLITE_OK; + if( id ){ + unixFile *pFile = (unixFile*)id; + dotlockUnlock(id, NO_LOCK); + sqlite3_free(pFile->lockingContext); + rc = closeUnixFile(id); + } + return rc; } /****************** End of the dot-file lock implementation ******************* ******************************************************************************/ @@ -29237,9 +26135,10 @@ static int dotlockClose(sqlite3_file *id) { ** still works when you do this, but concurrency is reduced since ** only a single process can be reading the database at a time. ** -** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off +** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if +** compiling for VXWORKS. */ -#if SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS /* ** Retry flock() calls that fail with EINTR @@ -29286,8 +26185,10 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ int tErrno = errno; /* unlock failed with an error */ lrc = SQLITE_IOERR_UNLOCK; - storeLastErrno(pFile, tErrno); - rc = lrc; + if( IS_LOCK_ERROR(lrc) ){ + pFile->lastErrno = tErrno; + rc = lrc; + } } } else { int tErrno = errno; @@ -29295,7 +26196,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ /* someone else might have it reserved */ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(lrc) ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; rc = lrc; } } @@ -29361,7 +26262,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) { /* didn't get, must be busy */ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } } else { /* got it, set the type and return ok */ @@ -29390,7 +26291,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); + pFile->eFileLock, getpid())); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -29420,9 +26321,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { ** Close a file. */ static int flockClose(sqlite3_file *id) { - assert( id!=0 ); - flockUnlock(id, NO_LOCK); - return closeUnixFile(id); + int rc = SQLITE_OK; + if( id ){ + flockUnlock(id, NO_LOCK); + rc = closeUnixFile(id); + } + return rc; } #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */ @@ -29448,7 +26352,7 @@ static int flockClose(sqlite3_file *id) { ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ -static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { +static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; @@ -29465,12 +26369,13 @@ static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { /* Otherwise see if some other process holds it. */ if( !reserved ){ sem_t *pSem = pFile->pInode->pSem; + struct stat statBuf; if( sem_trywait(pSem)==-1 ){ int tErrno = errno; if( EAGAIN != tErrno ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } else { /* someone else has the lock when we are in NO_LOCK */ reserved = (pFile->eFileLock < SHARED_LOCK); @@ -29515,8 +26420,9 @@ static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -static int semXLock(sqlite3_file *id, int eFileLock) { +static int semLock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; + int fd; sem_t *pSem = pFile->pInode->pSem; int rc = SQLITE_OK; @@ -29548,14 +26454,14 @@ static int semXLock(sqlite3_file *id, int eFileLock) { ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ -static int semXUnlock(sqlite3_file *id, int eFileLock) { +static int semUnlock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; assert( pFile ); assert( pSem ); OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, - pFile->eFileLock, osGetpid(0))); + pFile->eFileLock, getpid())); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -29574,7 +26480,7 @@ static int semXUnlock(sqlite3_file *id, int eFileLock) { int rc, tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } return rc; } @@ -29585,10 +26491,10 @@ static int semXUnlock(sqlite3_file *id, int eFileLock) { /* ** Close a file. */ -static int semXClose(sqlite3_file *id) { +static int semClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; - semXUnlock(id, NO_LOCK); + semUnlock(id, NO_LOCK); assert( pFile ); unixEnterMutex(); releaseInodeInfo(pFile); @@ -29676,7 +26582,7 @@ static int afpSetLock( setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); #endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */ if( IS_LOCK_ERROR(rc) ){ - storeLastErrno(pFile, tErrno); + pFile->lastErrno = tErrno; } return rc; } else { @@ -29769,7 +26675,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); + azFileLock(pInode->eFileLock), pInode->nShared , getpid())); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as @@ -29859,7 +26765,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); if( IS_LOCK_ERROR(lrc1) ) { - storeLastErrno(pFile, lrc1Errno); + pFile->lastErrno = lrc1Errno; rc = lrc1; goto afp_end_lock; } else if( IS_LOCK_ERROR(lrc2) ){ @@ -29955,7 +26861,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - osGetpid(0))); + getpid())); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -30047,22 +26953,23 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { */ static int afpClose(sqlite3_file *id) { int rc = SQLITE_OK; - unixFile *pFile = (unixFile*)id; - assert( id!=0 ); - afpUnlock(id, NO_LOCK); - unixEnterMutex(); - if( pFile->pInode && pFile->pInode->nLock ){ - /* If there are outstanding locks, do not actually close the file just - ** yet because that would clear those locks. Instead, add the file - ** descriptor to pInode->aPending. It will be automatically closed when - ** the last lock is cleared. - */ - setPendingFd(pFile); + if( id ){ + unixFile *pFile = (unixFile*)id; + afpUnlock(id, NO_LOCK); + unixEnterMutex(); + if( pFile->pInode && pFile->pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + setPendingFd(pFile); + } + releaseInodeInfo(pFile); + sqlite3_free(pFile->lockingContext); + rc = closeUnixFile(id); + unixLeaveMutex(); } - releaseInodeInfo(pFile); - sqlite3_free(pFile->lockingContext); - rc = closeUnixFile(id); - unixLeaveMutex(); return rc; } @@ -30117,7 +27024,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){ ** 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. +** any 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 @@ -30132,6 +27039,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ TIMER_START; assert( cnt==(cnt&0x1ffff) ); assert( id->h>2 ); + cnt &= 0x1ffff; do{ #if defined(USE_PREAD) got = osPread(id->h, pBuf, cnt, offset); @@ -30141,9 +27049,13 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ SimulateIOError( got = -1 ); #else newOffset = lseek(id->h, offset, SEEK_SET); - SimulateIOError( newOffset = -1 ); - if( newOffset<0 ){ - storeLastErrno((unixFile*)id, errno); + SimulateIOError( newOffset-- ); + if( newOffset!=offset ){ + if( newOffset == -1 ){ + ((unixFile*)id)->lastErrno = errno; + }else{ + ((unixFile*)id)->lastErrno = 0; + } return -1; } got = osRead(id->h, pBuf, cnt); @@ -30152,7 +27064,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ if( got<0 ){ if( errno==EINTR ){ got = 1; continue; } prior = 0; - storeLastErrno((unixFile*)id, errno); + ((unixFile*)id)->lastErrno = errno; break; }else if( got>0 ){ cnt -= got; @@ -30217,7 +27129,7 @@ static int unixRead( /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ - storeLastErrno(pFile, 0); /* not a system error */ + pFile->lastErrno = 0; /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; @@ -30242,21 +27154,21 @@ static int seekAndWriteFd( assert( nBuf==(nBuf&0x1ffff) ); assert( fd>2 ); - assert( piErrno!=0 ); nBuf &= 0x1ffff; TIMER_START; #if defined(USE_PREAD) - do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); + do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); #elif defined(USE_PREAD64) - do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); + do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ i64 iSeek = lseek(fd, iOff, SEEK_SET); - SimulateIOError( iSeek = -1 ); - if( iSeek<0 ){ - rc = -1; - break; + SimulateIOError( iSeek-- ); + + if( iSeek!=iOff ){ + if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0); + return -1; } rc = osWrite(fd, pBuf, nBuf); }while( rc<0 && errno==EINTR ); @@ -30265,7 +27177,7 @@ static int seekAndWriteFd( TIMER_END; OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED)); - if( rc<0 ) *piErrno = errno; + if( rc<0 && piErrno ) *piErrno = errno; return rc; } @@ -30328,7 +27240,7 @@ static int unixWrite( } #endif -#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_MAX_MMAP_SIZE>0 /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ @@ -30344,8 +27256,8 @@ static int unixWrite( } } #endif - - while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))0 ){ + + while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; @@ -30353,12 +27265,12 @@ static int unixWrite( SimulateIOError(( wrote=(-1), amt=1 )); SimulateDiskfullError(( wrote=0, amt=1 )); - if( amt>wrote ){ + if( amt>0 ){ if( wrote<0 && pFile->lastErrno!=ENOSPC ){ /* lastErrno set by seekAndWrite */ return SQLITE_IOERR_WRITE; }else{ - storeLastErrno(pFile, 0); /* not a system error */ + pFile->lastErrno = 0; /* not a system error */ return SQLITE_FULL; } } @@ -30379,9 +27291,9 @@ SQLITE_API int sqlite3_fullsync_count = 0; ** We do not trust systems to provide a working fdatasync(). Some do. ** Others do no. To be safe, we will stick with the (slightly slower) ** fsync(). If you know that your system does support fdatasync() correctly, -** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC +** then simply compile with -Dfdatasync=fdatasync */ -#if !defined(fdatasync) && !HAVE_FDATASYNC +#if !defined(fdatasync) # define fdatasync fsync #endif @@ -30449,15 +27361,10 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ #endif /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a - ** no-op. But go ahead and call fstat() to validate the file - ** descriptor as we need a method to provoke a failure during - ** coverate testing. + ** no-op */ #ifdef SQLITE_NO_SYNC - { - struct stat buf; - rc = osFstat(fd, &buf); - } + rc = SQLITE_OK; #elif HAVE_FULLFSYNC if( fullSync ){ rc = osFcntl(fd, F_FULLFSYNC, 0); @@ -30523,20 +27430,16 @@ static int openDirectory(const char *zFilename, int *pFd){ char zDirname[MAX_PATHNAME+1]; sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); - for(ii=(int)strlen(zDirname); ii>0 && zDirname[ii]!='/'; ii--); + for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); if( ii>0 ){ zDirname[ii] = '\0'; - }else{ - if( zDirname[0]!='/' ) zDirname[0] = '.'; - zDirname[1] = 0; - } - fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); - if( fd>=0 ){ - OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); + fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); + if( fd>=0 ){ + OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); + } } *pFd = fd; - if( fd>=0 ) return SQLITE_OK; - return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname); + return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); } /* @@ -30576,7 +27479,7 @@ static int unixSync(sqlite3_file *id, int flags){ rc = full_fsync(pFile->h, isFullsync, isDataOnly); SimulateIOError( rc=1 ); if( rc ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } @@ -30589,11 +27492,10 @@ static int unixSync(sqlite3_file *id, int flags){ OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, HAVE_FULLFSYNC, isFullsync)); rc = osOpenDirectory(pFile->zPath, &dirfd); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && dirfd>=0 ){ full_fsync(dirfd, 0, 0); robust_close(pFile, dirfd, __LINE__); - }else{ - assert( rc==SQLITE_CANTOPEN ); + }else if( rc==SQLITE_CANTOPEN ){ rc = SQLITE_OK; } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; @@ -30619,9 +27521,9 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } - rc = robust_ftruncate(pFile->h, nByte); + rc = robust_ftruncate(pFile->h, (off_t)nByte); if( rc ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); }else{ #ifdef SQLITE_DEBUG @@ -30661,7 +27563,7 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){ rc = osFstat(((unixFile*)id)->h, &buf); SimulateIOError( rc=1 ); if( rc!=0 ){ - storeLastErrno((unixFile*)id, errno); + ((unixFile*)id)->lastErrno = errno; return SQLITE_IOERR_FSTAT; } *pSize = buf.st_size; @@ -30697,9 +27599,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - if( osFstat(pFile->h, &buf) ){ - return SQLITE_IOERR_FSTAT; - } + if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT; nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ @@ -30714,24 +27614,24 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ }while( err==EINTR ); if( err ) return SQLITE_IOERR_WRITE; #else - /* If the OS does not have posix_fallocate(), fake it. Write a - ** single byte to the last byte in each block that falls entirely - ** within the extended region. Then, if required, a single byte - ** at offset (nSize-1), to set the size of the file correctly. - ** This is a similar technique to that used by glibc on systems - ** that do not have a real fallocate() call. + /* If the OS does not have posix_fallocate(), fake it. First use + ** ftruncate() to set the file size, then write a single byte to + ** the last byte in each block within the extended region. This + ** is the same technique used by glibc to implement posix_fallocate() + ** on systems that do not have a real fallocate() system call. */ int nBlk = buf.st_blksize; /* File-system block size */ - int nWrite = 0; /* Number of bytes written by seekAndWrite */ i64 iWrite; /* Next offset to write to */ - iWrite = (buf.st_size/nBlk)*nBlk + nBlk - 1; - assert( iWrite>=buf.st_size ); - assert( ((iWrite+1)%nBlk)==0 ); - for(/*no-op*/; iWrite=nSize ) iWrite = nSize - 1; - nWrite = seekAndWrite(pFile, iWrite, "", 1); + if( robust_ftruncate(pFile->h, nSize) ){ + pFile->lastErrno = errno; + return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); + } + iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; + while( iWriteszChunk<=0 ){ if( robust_ftruncate(pFile->h, nByte) ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); } } @@ -30756,7 +27656,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ } /* -** If *pArg is initially negative then this is a query. Set *pArg to +** If *pArg is inititially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. @@ -30784,7 +27684,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ *(int*)pArg = pFile->eFileLock; return SQLITE_OK; } - case SQLITE_FCNTL_LAST_ERRNO: { + case SQLITE_LAST_ERRNO: { *(int*)pArg = pFile->lastErrno; return SQLITE_OK; } @@ -30812,7 +27712,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname ); + char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname ); if( zTFile ){ unixGetTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; @@ -30853,8 +27753,8 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_FCNTL_SET_LOCKPROXYFILE: - case SQLITE_FCNTL_GET_LOCKPROXYFILE: { + case SQLITE_SET_LOCKPROXYFILE: + case SQLITE_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ @@ -30963,7 +27863,7 @@ static int unixSectorSize(sqlite3_file *id){ ** Return the device characteristics for the file. ** ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. -** However, that choice is controversial since technically the underlying +** However, that choice is contraversial since technically the underlying ** file system does not always provide powersafe overwrites. (In other ** words, after a power-loss event, parts of the file that were never ** written might end up being altered.) However, non-PSOW behavior is very, @@ -30985,28 +27885,9 @@ static int unixDeviceCharacteristics(sqlite3_file *id){ return rc; } -#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 - -/* -** Return the system page size. -** -** This function should not be called directly by other code in this file. -** Instead, it should be called via macro osGetpagesize(). -*/ -static int unixGetpagesize(void){ -#if OS_VXWORKS - return 1024; -#elif defined(_BSD_SOURCE) - return getpagesize(); -#else - return (int)sysconf(_SC_PAGESIZE); -#endif -} - -#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */ - #ifndef SQLITE_OMIT_WAL + /* ** Object used to represent an shared memory buffer. ** @@ -31089,24 +27970,22 @@ struct unixShm { ** otherwise. */ static int unixShmSystemLock( - unixFile *pFile, /* Open connection to the WAL file */ + unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ int ofst, /* First byte of the locking range */ int n /* Number of bytes to lock */ ){ - unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ - struct flock f; /* The posix advisory locking structure */ - int rc = SQLITE_OK; /* Result code form fcntl() */ + 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( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); /* Locks are within range */ - assert( n>=1 && n<=SQLITE_SHM_NLOCK ); + assert( n>=1 && nh>=0 ){ /* Initialize the locking parameters */ @@ -31158,6 +28037,20 @@ static int unixShmSystemLock( return rc; } +/* +** Return the system page size. +** +** This function should not be called directly by other code in this file. +** Instead, it should be called via macro osGetpagesize(). +*/ +static int unixGetpagesize(void){ +#if defined(_BSD_SOURCE) + return getpagesize(); +#else + return (int)sysconf(_SC_PAGESIZE); +#endif +} + /* ** Return the minimum number of 32KB shm regions that should be mapped at ** a time, assuming that each mapping must be an integer multiple of the @@ -31184,7 +28077,7 @@ static int unixShmRegionPerMap(void){ static void unixShmPurge(unixFile *pFd){ unixShmNode *p = pFd->pInode->pShmNode; assert( unixMutexHeld() ); - if( p && ALWAYS(p->nRef==0) ){ + if( p && p->nRef==0 ){ int nShmPerMap = unixShmRegionPerMap(); int i; assert( p->pInode==pFd->pInode ); @@ -31250,7 +28143,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ int nShmFilename; /* Size of the SHM filename in bytes */ /* Allocate space for the new unixShm object. */ - p = sqlite3_malloc64( sizeof(*p) ); + p = sqlite3_malloc( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM; memset(p, 0, sizeof(*p)); assert( pDbFd->pShm==0 ); @@ -31263,15 +28156,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ pShmNode = pInode->pShmNode; if( pShmNode==0 ){ struct stat sStat; /* fstat() info for database file */ -#ifndef SQLITE_SHM_DIRECTORY - const char *zBasePath = pDbFd->zPath; -#endif /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it ** with the same permissions. */ - if( osFstat(pDbFd->h, &sStat) ){ + if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){ rc = SQLITE_IOERR_FSTAT; goto shm_open_err; } @@ -31279,9 +28169,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ #ifdef SQLITE_SHM_DIRECTORY nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else - nShmFilename = 6 + (int)strlen(zBasePath); + nShmFilename = 6 + (int)strlen(pDbFd->zPath); #endif - pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); + pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ rc = SQLITE_NOMEM; goto shm_open_err; @@ -31293,7 +28183,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", (u32)sStat.st_ino, (u32)sStat.st_dev); #else - sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); + sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath); sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); #endif pShmNode->h = -1; @@ -31321,19 +28211,19 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ ** is owned by the same user that owns the original database. Otherwise, ** the original owner will not be able to connect. */ - robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); + osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. */ rc = SQLITE_OK; - if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ + if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ if( robust_ftruncate(pShmNode->h, 0) ){ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); } } if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); + rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1); } if( rc ) goto shm_open_err; } @@ -31458,8 +28348,7 @@ static int unixShmMap( /* Write to the last byte of each newly allocated or extended page */ assert( (nByte % pgsz)==0 ); for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ - int x = 0; - if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ + if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){ const char *zFile = pShmNode->zFilename; rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); goto shmpage_out; @@ -31492,7 +28381,7 @@ static int unixShmMap( goto shmpage_out; } }else{ - pMem = sqlite3_malloc64(szRegion); + pMem = sqlite3_malloc(szRegion); if( pMem==0 ){ rc = SQLITE_NOMEM; goto shmpage_out; @@ -31566,7 +28455,7 @@ static int unixShmLock( /* Unlock the system-level locks */ if( (mask & allMask)==0 ){ - rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -31594,7 +28483,7 @@ static int unixShmLock( /* Get shared locks at the system level, if necessary */ if( rc==SQLITE_OK ){ if( (allShared & mask)==0 ){ - rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -31619,7 +28508,7 @@ static int unixShmLock( ** also mark the local connection as being locked. */ if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n); if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; @@ -31628,7 +28517,7 @@ static int unixShmLock( } sqlite3_mutex_leave(pShmNode->mutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", - p->id, osGetpid(0), p->sharedMask, p->exclMask)); + p->id, getpid(), p->sharedMask, p->exclMask)); return rc; } @@ -31642,8 +28531,7 @@ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); - sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - unixEnterMutex(); /* Also mutex, for redundancy */ + unixEnterMutex(); unixLeaveMutex(); } @@ -31688,9 +28576,7 @@ static int unixShmUnmap( assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ){ - osUnlink(pShmNode->zFilename); - } + if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -31753,9 +28639,7 @@ static void unixRemapfile( assert( pFd->mmapSizeActual>=pFd->mmapSize ); assert( MAP_FAILED!=0 ); -#ifdef SQLITE_MMAP_READWRITE if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; -#endif if( pOrig ){ #if HAVE_MREMAP @@ -31827,14 +28711,17 @@ static void unixRemapfile( ** recreated as a result of outstanding references) or an SQLite error ** code otherwise. */ -static int unixMapfile(unixFile *pFd, i64 nMap){ +static int unixMapfile(unixFile *pFd, i64 nByte){ + i64 nMap = nByte; + int rc; + assert( nMap>=0 || pFd->nFetchOut==0 ); - assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) ); if( pFd->nFetchOut>0 ) return SQLITE_OK; if( nMap<0 ){ struct stat statbuf; /* Low-level file information */ - if( osFstat(pFd->h, &statbuf) ){ + rc = osFstat(pFd->h, &statbuf); + if( rc!=SQLITE_OK ){ return SQLITE_IOERR_FSTAT; } nMap = statbuf.st_size; @@ -31843,9 +28730,12 @@ static int unixMapfile(unixFile *pFd, i64 nMap){ nMap = pFd->mmapSizeMax; } - assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) ); if( nMap!=pFd->mmapSize ){ - unixRemapfile(pFd, nMap); + if( nMap>0 ){ + unixRemapfile(pFd, nMap); + }else{ + unixUnmapfile(pFd); + } } return SQLITE_OK; @@ -31942,7 +28832,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ ** looks at the filesystem type and tries to guess the best locking ** strategy from that. ** -** For finder-function F, two objects are created: +** For finder-funtion F, two objects are created: ** ** (1) The real finder-function named "FImpt()". ** @@ -31963,7 +28853,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. */ -#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \ +#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \ static const sqlite3_io_methods METHOD = { \ VERSION, /* iVersion */ \ CLOSE, /* xClose */ \ @@ -31978,7 +28868,7 @@ static const sqlite3_io_methods METHOD = { \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics, /* xDeviceCapabilities */ \ - SHMMAP, /* xShmMap */ \ + unixShmMap, /* xShmMap */ \ unixShmLock, /* xShmLock */ \ unixShmBarrier, /* xShmBarrier */ \ unixShmUnmap, /* xShmUnmap */ \ @@ -32004,18 +28894,16 @@ IOMETHODS( unixClose, /* xClose method */ unixLock, /* xLock method */ unixUnlock, /* xUnlock method */ - unixCheckReservedLock, /* xCheckReservedLock method */ - unixShmMap /* xShmMap method */ + unixCheckReservedLock /* xCheckReservedLock method */ ) IOMETHODS( nolockIoFinder, /* Finder function name */ nolockIoMethods, /* sqlite3_io_methods object name */ - 3, /* shared memory is disabled */ + 1, /* shared memory is disabled */ nolockClose, /* xClose method */ nolockLock, /* xLock method */ nolockUnlock, /* xUnlock method */ - nolockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + nolockCheckReservedLock /* xCheckReservedLock method */ ) IOMETHODS( dotlockIoFinder, /* Finder function name */ @@ -32024,11 +28912,10 @@ IOMETHODS( dotlockClose, /* xClose method */ dotlockLock, /* xLock method */ dotlockUnlock, /* xUnlock method */ - dotlockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + dotlockCheckReservedLock /* xCheckReservedLock method */ ) -#if SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS IOMETHODS( flockIoFinder, /* Finder function name */ flockIoMethods, /* sqlite3_io_methods object name */ @@ -32036,8 +28923,7 @@ IOMETHODS( flockClose, /* xClose method */ flockLock, /* xLock method */ flockUnlock, /* xUnlock method */ - flockCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + flockCheckReservedLock /* xCheckReservedLock method */ ) #endif @@ -32046,11 +28932,10 @@ IOMETHODS( semIoFinder, /* Finder function name */ semIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ - semXClose, /* xClose method */ - semXLock, /* xLock method */ - semXUnlock, /* xUnlock method */ - semXCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + semClose, /* xClose method */ + semLock, /* xLock method */ + semUnlock, /* xUnlock method */ + semCheckReservedLock /* xCheckReservedLock method */ ) #endif @@ -32062,8 +28947,7 @@ IOMETHODS( afpClose, /* xClose method */ afpLock, /* xLock method */ afpUnlock, /* xUnlock method */ - afpCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + afpCheckReservedLock /* xCheckReservedLock method */ ) #endif @@ -32088,8 +28972,7 @@ IOMETHODS( proxyClose, /* xClose method */ proxyLock, /* xLock method */ proxyUnlock, /* xUnlock method */ - proxyCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + proxyCheckReservedLock /* xCheckReservedLock method */ ) #endif @@ -32102,8 +28985,7 @@ IOMETHODS( unixClose, /* xClose method */ unixLock, /* xLock method */ nfsUnlock, /* xUnlock method */ - unixCheckReservedLock, /* xCheckReservedLock method */ - 0 /* xShmMap method */ + unixCheckReservedLock /* xCheckReservedLock method */ ) #endif @@ -32173,13 +29055,15 @@ static const sqlite3_io_methods #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -#if OS_VXWORKS -/* -** This "finder" function for VxWorks checks to see if posix advisory -** locking works. If it does, then that is what is used. If it does not -** work, then fallback to named semaphore locking. +#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE +/* +** This "finder" function attempts to determine the best locking strategy +** for the database file "filePath". It then returns the sqlite3_io_methods +** object that implements that strategy. +** +** This is for VXWorks only. */ -static const sqlite3_io_methods *vxworksIoFinderImpl( +static const sqlite3_io_methods *autolockIoFinderImpl( const char *filePath, /* name of the database file */ unixFile *pNew /* the open file object */ ){ @@ -32205,12 +29089,12 @@ static const sqlite3_io_methods *vxworksIoFinderImpl( } } static const sqlite3_io_methods - *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; + *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; -#endif /* OS_VXWORKS */ +#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */ /* -** An abstract type for a pointer to an IO method finder function: +** An abstract type for a pointer to a IO method finder function: */ typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*); @@ -32326,7 +29210,7 @@ static int fillInUnixFile( ** the afpLockingContext. */ afpLockingContext *pCtx; - pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); + pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) ); if( pCtx==0 ){ rc = SQLITE_NOMEM; }else{ @@ -32356,7 +29240,7 @@ static int fillInUnixFile( int nFilename; assert( zFilename!=0 ); nFilename = (int)strlen(zFilename) + 6; - zLockFile = (char *)sqlite3_malloc64(nFilename); + zLockFile = (char *)sqlite3_malloc(nFilename); if( zLockFile==0 ){ rc = SQLITE_NOMEM; }else{ @@ -32389,7 +29273,7 @@ static int fillInUnixFile( } #endif - storeLastErrno(pNew, 0); + pNew->lastErrno = 0; #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); @@ -32414,19 +29298,21 @@ static int fillInUnixFile( */ static const char *unixTempFileDir(void){ static const char *azDirs[] = { + 0, 0, 0, "/var/tmp", "/usr/tmp", "/tmp", - "." + 0 /* List terminator */ }; unsigned int i; struct stat buf; - const char *zDir = sqlite3_temp_directory; + const char *zDir = 0; - if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); - if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); + azDirs[0] = sqlite3_temp_directory; + if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR"); + if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR"); for(i=0; imxPathname bytes. */ static int unixGetTempname(int nBuf, char *zBuf){ + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + unsigned int i, j; const char *zDir; - int iLimit = 0; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -32453,14 +29343,24 @@ static int unixGetTempname(int nBuf, char *zBuf){ SimulateIOError( return SQLITE_IOERR ); zDir = unixTempFileDir(); + if( zDir==0 ) zDir = "."; + + /* Check that the output buffer is large enough for the temporary file + ** name. If it is not, return SQLITE_ERROR. + */ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){ + return SQLITE_ERROR; + } + do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; + sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); + j = (int)strlen(zBuf); + sqlite3_randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + zBuf[j+1] = 0; }while( osAccess(zBuf,0)==0 ); return SQLITE_OK; } @@ -32508,7 +29408,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** descriptor on the same path, fail, and return an error to SQLite. ** ** Even if a subsequent open() call does succeed, the consequences of - ** not searching for a reusable file descriptor are not dire. */ + ** not searching for a resusable file descriptor are not dire. */ if( 0==osStat(zPath, &sStat) ){ unixInodeInfo *pInode; @@ -32539,7 +29439,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** written to *pMode. If an IO error occurs, an SQLite error code is ** returned and the value of *pMode is not modified. ** -** In most cases, this routine sets *pMode to 0, which will become +** In most cases cases, this routine sets *pMode to 0, which will become ** an indication to robust_open() to create the file using ** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask. ** But if the file being opened is a WAL or regular journal file, then @@ -32582,19 +29482,16 @@ static int findCreateFileMode( ** used by the test_multiplex.c module. */ nDb = sqlite3Strlen30(zPath) - 1; - while( zPath[nDb]!='-' ){ -#ifndef SQLITE_ENABLE_8_3_NAMES - /* In the normal case (8+3 filenames disabled) the journal filename - ** is guaranteed to contain a '-' character. */ - assert( nDb>0 ); - assert( sqlite3Isalnum(zPath[nDb]) ); +#ifdef SQLITE_ENABLE_8_3_NAMES + while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--; + if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK; #else - /* If 8+3 names are possible, then the journal file might not contain - ** a '-' character. So check for that case and return early. */ - if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK; -#endif + while( zPath[nDb]!='-' ){ + assert( nDb>0 ); + assert( zPath[nDb]!='\n' ); nDb--; } +#endif memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; @@ -32707,8 +29604,8 @@ static int unixOpen( ** the same instant might all reset the PRNG. But multiple resets ** are harmless. */ - if( randomnessPid!=osGetpid(0) ){ - randomnessPid = osGetpid(0); + if( randomnessPid!=getpid() ){ + randomnessPid = getpid(); sqlite3_randomness(0,0); } @@ -32720,7 +29617,7 @@ static int unixOpen( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc64(sizeof(*pUnused)); + pUnused = sqlite3_malloc(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -32735,7 +29632,7 @@ static int unixOpen( }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ assert(isDelete && !syncDir); - rc = unixGetTempname(pVfs->mxPathname, zTmpname); + rc = unixGetTempname(MAX_PATHNAME+2, zTmpname); if( rc!=SQLITE_OK ){ return rc; } @@ -32768,8 +29665,7 @@ static int unixOpen( } fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); - assert( !isExclusive || (openFlags & O_CREAT)!=0 ); - if( fd<0 && errno!=EISDIR && isReadWrite ){ + if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); @@ -32788,7 +29684,7 @@ static int unixOpen( ** the same as the original database. */ if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ - robustFchown(fd, uid, gid); + osFchown(fd, uid, gid); } } assert( fd>=0 ); @@ -32804,12 +29700,6 @@ static int unixOpen( if( isDelete ){ #if OS_VXWORKS zPath = zName; -#elif defined(SQLITE_UNLINK_AFTER_CLOSE) - zPath = sqlite3_mprintf("%s", zName); - if( zPath==0 ){ - robust_close(p, fd, __LINE__); - return SQLITE_NOMEM; - } #else osUnlink(zName); #endif @@ -32825,16 +29715,13 @@ static int unixOpen( #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ - storeLastErrno(p, errno); + ((unixFile*)pFile)->lastErrno = errno; robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; } - if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { - ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; - } #endif /* Set up appropriate ctrlFlags */ @@ -32857,6 +29744,19 @@ static int unixOpen( if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ + if( statfs(zPath, &fsInfo) == -1 ){ + /* In theory, the close(fd) call is sub-optimal. If the file opened + ** with fd is a database file, and there are other connections open + ** on that file that are currently holding advisory locks on it, + ** then the call to close() will cancel those locks. In practice, + ** we're assuming that statfs() doesn't fail very often. At least + ** not while other file descriptors opened by the same process on + ** the same file are working. */ + p->lastErrno = errno; + robust_close(p, fd, __LINE__); + rc = SQLITE_IOERR_ACCESS; + goto open_finished; + } useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ @@ -32900,11 +29800,7 @@ static int unixDelete( UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); if( osUnlink(zPath)==(-1) ){ - if( errno==ENOENT -#if OS_VXWORKS - || osAccess(zPath,0)!=0 -#endif - ){ + if( errno==ENOENT ){ rc = SQLITE_IOERR_DELETE_NOENT; }else{ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); @@ -32925,8 +29821,7 @@ static int unixDelete( rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } robust_close(0, fd, __LINE__); - }else{ - assert( rc==SQLITE_CANTOPEN ); + }else if( rc==SQLITE_CANTOPEN ){ rc = SQLITE_OK; } } @@ -32950,19 +29845,29 @@ static int unixAccess( int flags, /* What do we want to learn about the zPath file? */ int *pResOut /* Write result boolean here */ ){ + int amode = 0; UNUSED_PARAMETER(NotUsed); SimulateIOError( return SQLITE_IOERR_ACCESS; ); - assert( pResOut!=0 ); + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READ: + amode = R_OK; + break; - /* The spec says there are three possible values for flags. But only - ** two of them are actually used */ - assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); - - if( flags==SQLITE_ACCESS_EXISTS ){ + default: + assert(!"Invalid flags argument"); + } + *pResOut = (osAccess(zPath, amode)==0); + if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ struct stat buf; - *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0); - }else{ - *pResOut = osAccess(zPath, W_OK|R_OK)==0; + if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ + *pResOut = 0; + } } return SQLITE_OK; } @@ -32983,7 +29888,6 @@ static int unixFullPathname( int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ - int nByte; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -32995,54 +29899,17 @@ static int unixFullPathname( assert( pVfs->mxPathname==MAX_PATHNAME ); UNUSED_PARAMETER(pVfs); - /* Attempt to resolve the path as if it were a symbolic link. If it is - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if - ** the identified file is not a symbolic link or does not exist, then - ** zPath is copied directly into zOut. Either way, nByte is left set to - ** the size of the string copied into zOut[] in bytes. */ - nByte = osReadlink(zPath, zOut, nOut-1); - if( nByte<0 ){ - if( errno!=EINVAL && errno!=ENOENT ){ - return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); - } + zOut[nOut-1] = '\0'; + if( zPath[0]=='/' ){ sqlite3_snprintf(nOut, zOut, "%s", zPath); - nByte = sqlite3Strlen30(zOut); }else{ - zOut[nByte] = '\0'; - } - - /* If buffer zOut[] now contains an absolute path there is nothing more - ** to do. If it contains a relative path, do the following: - ** - ** * move the relative path string so that it is at the end of th - ** zOut[] buffer. - ** * Call getcwd() to read the path of the current working directory - ** into the start of the zOut[] buffer. - ** * Append a '/' character to the cwd string and move the - ** relative path back within the buffer so that it immediately - ** follows the '/'. - ** - ** This code is written so that if the combination of the CWD and relative - ** path are larger than the allocated size of zOut[] the CWD is silently - ** truncated to make it fit. This is Ok, as SQLite refuses to open any - ** file for which this function returns a full path larger than (nOut-8) - ** bytes in size. */ - testcase( nByte==nOut-5 ); - testcase( nByte==nOut-4 ); - if( zOut[0]!='/' && nByte | ":auto:"); -** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE, -** &); +** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &); ** ** ** SQL pragmas @@ -33360,7 +30221,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** proxy path against the values stored in the conch. The conch file is ** stored in the same directory as the database file and the file name ** is patterned after the database file name as ".-conch". -** If the conch file does not exist, or its contents do not match the +** If the conch file does not exist, or it's contents do not match the ** host ID and/or proxy path, then the lock is escalated to an exclusive ** lock and the conch file contents is updated with the host ID and proxy ** path and the lock is downgraded to a shared lock again. If the conch @@ -33412,7 +30273,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will ** force proxy locking to be used for every database file opened, and 0 ** will force automatic proxy locking to be disabled for all database -** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or +** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or ** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). */ @@ -33433,7 +30294,6 @@ struct proxyLockingContext { char *lockProxyPath; /* Name of the proxy lock file */ char *dbPath; /* Name of the open file */ int conchHeld; /* 1 if the conch is held, -1 if lockless */ - int nFails; /* Number of conch taking failures */ void *oldLockingContext; /* Original lockingcontext to restore on close */ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ }; @@ -33455,7 +30315,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ { if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", - lPath, errno, osGetpid(0))); + lPath, errno, getpid())); return SQLITE_IOERR_LOCK; } len = strlcat(lPath, "sqliteplocks", maxLen); @@ -33477,7 +30337,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); - OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0))); + OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid())); return SQLITE_OK; } @@ -33504,7 +30364,7 @@ static int proxyCreateLockPath(const char *lockPath){ if( err!=EEXIST ) { OSTRACE(("CREATELOCKPATH FAILED creating %s, " "'%s' proxy lock path=%s pid=%d\n", - buf, strerror(err), lockPath, osGetpid(0))); + buf, strerror(err), lockPath, getpid())); return err; } } @@ -33513,7 +30373,7 @@ static int proxyCreateLockPath(const char *lockPath){ } buf[i] = lockPath[i]; } - OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0))); + OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid())); return 0; } @@ -33547,7 +30407,7 @@ static int proxyCreateUnixFile( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc64(sizeof(*pUnused)); + pUnused = sqlite3_malloc(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -33580,7 +30440,7 @@ static int proxyCreateUnixFile( } } - pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); + pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); if( pNew==NULL ){ rc = SQLITE_NOMEM; goto end_create_proxy; @@ -33613,10 +30473,8 @@ SQLITE_API int sqlite3_hostid_num = 0; #define PROXY_HOSTIDLEN 16 /* conch file host id length */ -#ifdef HAVE_GETHOSTUUID /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); -#endif /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. @@ -33624,9 +30482,10 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait); static int proxyGetHostID(unsigned char *pHostID, int *pError){ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memset(pHostID, 0, PROXY_HOSTIDLEN); -#ifdef HAVE_GETHOSTUUID +#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\ + && __MAC_OS_X_VERSION_MIN_REQUIRED<1050 { - struct timespec timeout = {1, 0}; /* 1 sec timeout */ + static const struct timespec timeout = {1, 0}; /* 1 sec timeout */ if( gethostuuid(pHostID, &timeout) ){ int err = errno; if( pError ){ @@ -33741,7 +30600,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ */ struct stat buf; if( osFstat(conchFile->h, &buf) ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return SQLITE_IOERR_LOCK; } @@ -33761,7 +30620,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ char tBuf[PROXY_MAXCONCHLEN]; int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ - storeLastErrno(pFile, errno); + pFile->lastErrno = errno; return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ @@ -33781,7 +30640,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ if( 0==proxyBreakConchLock(pFile, myHostID) ){ rc = SQLITE_OK; if( lockType==EXCLUSIVE_LOCK ){ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); } if( !rc ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); @@ -33819,12 +30678,11 @@ static int proxyTakeConch(unixFile *pFile){ int forceNewLockPath = 0; OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - osGetpid(0))); + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid())); rc = proxyGetHostID(myHostID, &pError); if( (rc&0xff)==SQLITE_IOERR ){ - storeLastErrno(pFile, pError); + pFile->lastErrno = pError; goto end_takeconch; } rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); @@ -33835,7 +30693,7 @@ static int proxyTakeConch(unixFile *pFile){ readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ - storeLastErrno(pFile, conchFile->lastErrno); + pFile->lastErrno = conchFile->lastErrno; rc = SQLITE_IOERR_READ; goto end_takeconch; }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || @@ -33908,7 +30766,7 @@ static int proxyTakeConch(unixFile *pFile){ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } }else{ - rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); } if( rc==SQLITE_OK ){ char writeBuffer[PROXY_MAXCONCHLEN]; @@ -33917,8 +30775,7 @@ static int proxyTakeConch(unixFile *pFile){ writeBuffer[0] = (char)PROXY_CONCHVERSION; memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); if( pCtx->lockProxyPath!=NULL ){ - strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, - MAXPATHLEN); + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); }else{ strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); } @@ -34030,7 +30887,7 @@ static int proxyReleaseConch(unixFile *pFile){ conchFile = pCtx->conchFile; OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - osGetpid(0))); + getpid())); if( pCtx->conchHeld>0 ){ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } @@ -34042,7 +30899,7 @@ static int proxyReleaseConch(unixFile *pFile){ /* ** Given the name of a database file, compute the name of its conch file. -** Store the conch filename in memory obtained from sqlite3_malloc64(). +** Store the conch filename in memory obtained from sqlite3_malloc(). ** Make *pConchPath point to the new name. Return SQLITE_OK on success ** or SQLITE_NOMEM if unable to obtain memory. ** @@ -34058,7 +30915,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ /* Allocate space for the conch filename and initialize the name to ** the name of the original database file. */ - *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); + *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8); if( conchPath==0 ){ return SQLITE_NOMEM; } @@ -34130,8 +30987,7 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ /* afp style keeps a reference to the db path in the filePath field ** of the struct */ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); - strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, - MAXPATHLEN); + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); } else #endif if( pFile->pMethod == &dotlockIoMethods ){ @@ -34172,9 +31028,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { } OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, - (lockPath ? lockPath : ":auto:"), osGetpid(0))); + (lockPath ? lockPath : ":auto:"), getpid())); - pCtx = sqlite3_malloc64( sizeof(*pCtx) ); + pCtx = sqlite3_malloc( sizeof(*pCtx) ); if( pCtx==0 ){ return SQLITE_NOMEM; } @@ -34244,7 +31100,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { */ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ - case SQLITE_FCNTL_GET_LOCKPROXYFILE: { + case SQLITE_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( pFile->pMethod == &proxyIoMethods ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; @@ -34259,16 +31115,13 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } - case SQLITE_FCNTL_SET_LOCKPROXYFILE: { + case SQLITE_SET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; int rc = SQLITE_OK; int isProxyStyle = (pFile->pMethod == &proxyIoMethods); if( pArg==NULL || (const char *)pArg==0 ){ if( isProxyStyle ){ - /* turn off proxy locking - not supported. If support is added for - ** switching proxy locking mode off then it will need to fail if - ** the journal mode is WAL mode. - */ + /* turn off proxy locking - not supported */ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; }else{ /* turn off proxy locking - already off - NOOP */ @@ -34398,7 +31251,7 @@ static int proxyUnlock(sqlite3_file *id, int eFileLock) { ** Close a file that uses proxy locks. */ static int proxyClose(sqlite3_file *id) { - if( ALWAYS(id) ){ + if( id ){ unixFile *pFile = (unixFile*)id; proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *lockProxy = pCtx->lockProxy; @@ -34459,7 +31312,7 @@ static int proxyClose(sqlite3_file *id) { ** necessarily been initialized when this routine is called, and so they ** should not be used. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a pointer @@ -34513,10 +31366,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ ** array cannot be const. */ static sqlite3_vfs aVfs[] = { -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) +#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__)) UNIXVFS("unix", autolockIoFinder ), -#elif OS_VXWORKS - UNIXVFS("unix", vxworksIoFinder ), #else UNIXVFS("unix", posixIoFinder ), #endif @@ -34526,12 +31377,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ #if OS_VXWORKS UNIXVFS("unix-namedsem", semIoFinder ), #endif -#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS - UNIXVFS("unix-posix", posixIoFinder ), -#endif #if SQLITE_ENABLE_LOCKING_STYLE + UNIXVFS("unix-posix", posixIoFinder ), +#if !OS_VXWORKS UNIXVFS("unix-flock", flockIoFinder ), #endif +#endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) UNIXVFS("unix-afp", afpIoFinder ), UNIXVFS("unix-nfs", nfsIoFinder ), @@ -34542,7 +31393,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==27 ); + assert( ArraySize(aSyscall)==25 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ @@ -34558,7 +31409,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ return SQLITE_OK; } @@ -34580,7 +31431,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ ** ** This file contains code that is specific to Windows. */ -/* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* @@ -34619,6 +31469,16 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +#else +# define OSTRACE(X) +#endif + /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. @@ -34789,7 +31649,6 @@ SQLITE_API int sqlite3_open_file_count = 0; /* ** Include the header file for the Windows VFS. */ -/* #include "os_win.h" */ /* ** Compiling and using WAL mode requires several APIs that are only @@ -34800,11 +31659,6 @@ SQLITE_API int sqlite3_open_file_count = 0; with SQLITE_OMIT_WAL." #endif -#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 -# error "Memory mapped files require support from the Windows NT kernel,\ - compile with SQLITE_MAX_MMAP_SIZE=0." -#endif - /* ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions ** based on the sub-platform)? @@ -34843,14 +31697,18 @@ SQLITE_API int sqlite3_open_file_count = 0; #endif /* -** Check to see if the GetVersionEx[AW] functions are deprecated on the -** target system. GetVersionEx was first deprecated in Win8.1. +** Check if the GetVersionEx[AW] functions should be considered deprecated +** and avoid using them in that case. It should be noted here that if the +** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero +** (whether via this block or via being manually specified), that implies +** the underlying operating system will always be based on the Windows NT +** Kernel. */ #ifndef SQLITE_WIN32_GETVERSIONEX # if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE -# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */ +# define SQLITE_WIN32_GETVERSIONEX 0 # else -# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ +# define SQLITE_WIN32_GETVERSIONEX 1 # endif #endif @@ -34922,7 +31780,7 @@ SQLITE_API int sqlite3_open_file_count = 0; ** [sometimes] not used by the code (e.g. via conditional compilation). */ #ifndef UNUSED_VARIABLE_VALUE -# define UNUSED_VARIABLE_VALUE(x) (void)(x) +# define UNUSED_VARIABLE_VALUE(x) (void)(x) #endif /* @@ -34934,11 +31792,10 @@ SQLITE_API int sqlite3_open_file_count = 0; /* ** Do we need to manually define the Win32 file mapping APIs for use with WAL -** mode or memory mapped files (e.g. these APIs are available in the Windows -** CE SDK; however, they are not present in the header file)? +** mode (e.g. these APIs are available in the Windows CE SDK; however, they +** are not present in the header file)? */ -#if SQLITE_WIN32_FILEMAPPING_API && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) /* ** Two of the file mapping APIs are different under WinRT. Figure out which ** set we need. @@ -34963,18 +31820,16 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif /* SQLITE_OS_WINRT */ /* -** These file mapping APIs are common to both Win32 and WinRT. +** This file mapping API is common to both Win32 and WinRT. */ - -WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); -#endif /* SQLITE_WIN32_FILEMAPPING_API */ +#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */ /* ** Some Microsoft compilers lack this definition. */ #ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif #ifndef FILE_FLAG_MASK @@ -35024,7 +31879,7 @@ struct winFile { int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ #if SQLITE_OS_WINCE LPWSTR zDeleteOnClose; /* Name of file to delete when closing */ - HANDLE hMutex; /* Mutex used to control access to shared lock */ + HANDLE hMutex; /* Mutex used to control access to shared lock */ HANDLE hShared; /* Shared memory segment used for locking */ winceLock local; /* Locks obtained by this instance of winFile */ winceLock *shared; /* Global shared lock memory for the file */ @@ -35184,9 +32039,10 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void); ** can manually set this value to 1 to emulate Win98 behavior. */ #ifdef SQLITE_TEST -SQLITE_API LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; -#else -static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; +SQLITE_API int sqlite3_os_type = 0; +#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE) +static int sqlite3_os_type = 0; #endif #ifndef SYSCALL @@ -35261,7 +32117,7 @@ static struct win_syscall { LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + !defined(SQLITE_OMIT_WAL)) { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, #else { "CreateFileMappingA", (SYSCALL)0, 0 }, @@ -35271,7 +32127,7 @@ static struct win_syscall { DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) + !defined(SQLITE_OMIT_WAL)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, @@ -35611,8 +32467,7 @@ static struct win_syscall { LPOVERLAPPED))aSyscall[48].pCurrent) #endif -#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, @@ -35682,7 +32537,7 @@ static struct win_syscall { #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ LPOVERLAPPED))aSyscall[58].pCurrent) -#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, #else { "UnmapViewOfFile", (SYSCALL)0, 0 }, @@ -35718,7 +32573,7 @@ static struct win_syscall { #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ DWORD))aSyscall[63].pCurrent) -#if !SQLITE_OS_WINCE +#if SQLITE_OS_WINRT { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, #else { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, @@ -35745,7 +32600,7 @@ static struct win_syscall { #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL) { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, #else { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, @@ -35809,7 +32664,7 @@ static struct win_syscall { #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) -#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL) { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, #else { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, @@ -35818,48 +32673,6 @@ static struct win_syscall { #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) -/* -** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" -** is really just a macro that uses a compiler intrinsic (e.g. x64). -** So do not try to make this is into a redefinable interface. -*/ -#if defined(InterlockedCompareExchange) - { "InterlockedCompareExchange", (SYSCALL)0, 0 }, - -#define osInterlockedCompareExchange InterlockedCompareExchange -#else - { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, - -#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ - SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) -#endif /* defined(InterlockedCompareExchange) */ - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - { "UuidCreate", (SYSCALL)UuidCreate, 0 }, -#else - { "UuidCreate", (SYSCALL)0, 0 }, -#endif - -#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, -#else - { "UuidCreateSequential", (SYSCALL)0, 0 }, -#endif - -#define osUuidCreateSequential \ - ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) - -#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 - { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, -#else - { "FlushViewOfFile", (SYSCALL)0, 0 }, -#endif - -#define osFlushViewOfFile \ - ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) - }; /* End of the overrideable system calls */ /* @@ -35953,7 +32766,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ ** "pnLargest" argument, if non-zero, will be used to return the size of the ** largest committed free block in the heap, in bytes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ +SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ int rc = SQLITE_OK; UINT nLargest = 0; HANDLE hHeap; @@ -35993,12 +32806,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){ ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will ** be returned and no changes will be made to the Win32 native heap. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ +SQLITE_API int sqlite3_win32_reset_heap(){ int rc; MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ - MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) - MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) + MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) sqlite3_mutex_enter(pMaster); sqlite3_mutex_enter(pMem); winMemAssertMagic(); @@ -36038,7 +32851,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){ ** (if available). */ -SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){ +SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ @@ -36078,7 +32891,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int n static HANDLE sleepObj = NULL; #endif -SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ #if SQLITE_OS_WINRT if ( sleepObj==NULL ){ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, @@ -36091,16 +32904,6 @@ SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){ #endif } -#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ - SQLITE_THREADSAFE>0 -SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ - DWORD rc; - while( (rc = osWaitForSingleObjectEx(hObject, INFINITE, - TRUE))==WAIT_IO_COMPLETION ){} - return rc; -} -#endif - /* ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, ** or WinCE. Return false (zero) for Win95, Win98, or WinME. @@ -36120,47 +32923,22 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ #elif !defined(SQLITE_WIN32_HAS_WIDE) # define osIsNT() (0) #else -# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt()) -#endif - -/* -** This function determines if the machine is running a version of Windows -** based on the NT kernel. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){ -#if SQLITE_OS_WINRT - /* - ** NOTE: The WinRT sub-platform is always assumed to be based on the NT - ** kernel. - */ - return 1; -#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX - if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ -#if defined(SQLITE_WIN32_HAS_ANSI) - OSVERSIONINFOA sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - osGetVersionExA(&sInfo); - osInterlockedCompareExchange(&sqlite3_os_type, - (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); -#elif defined(SQLITE_WIN32_HAS_WIDE) - OSVERSIONINFOW sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - osGetVersionExW(&sInfo); - osInterlockedCompareExchange(&sqlite3_os_type, - (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); -#endif - } - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; -#elif SQLITE_TEST - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; + static int osIsNT(void){ + if( sqlite3_os_type==0 ){ +#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8 + OSVERSIONINFOW sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + osGetVersionExW(&sInfo); #else - /* - ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are - ** deprecated are always assumed to be based on the NT kernel. - */ - return 1; + OSVERSIONINFOA sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + osGetVersionExA(&sInfo); +#endif + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; + } #endif -} #ifdef SQLITE_WIN32_MALLOC /* @@ -36368,7 +33146,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ #endif /* SQLITE_WIN32_MALLOC */ /* -** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). +** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). ** ** Space to hold the returned string is obtained from malloc. */ @@ -36421,7 +33199,7 @@ static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ /* ** Convert an ANSI string to Microsoft Unicode, based on the ** current codepage settings for file apis. -** +** ** Space to hold the returned string is obtained ** from sqlite3_malloc. */ @@ -36481,7 +33259,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ ** Convert multibyte character string to UTF-8. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ char *zFilenameUtf8; LPWSTR zTmpWide; @@ -36495,10 +33273,10 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename } /* -** Convert UTF-8 to multibyte character string. Space to hold the +** Convert UTF-8 to multibyte character string. Space to hold the ** returned string is obtained from sqlite3_malloc(). */ -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){ +SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){ char *zFilenameMbcs; LPWSTR zTmpWide; @@ -36518,7 +33296,7 @@ SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename ** argument is the name of the directory to use. The return value will be ** SQLITE_OK if successful. */ -SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ +SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ char **ppDirectory = 0; #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); @@ -36635,11 +33413,11 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ ** ** This routine is invoked after an error occurs in an OS function. ** It logs a message using sqlite3_log() containing the current value of -** error code and, if possible, the human-readable equivalent from +** error code and, if possible, the human-readable equivalent from ** FormatMessage. ** ** The first argument passed to the macro should be the error code that -** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). +** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). ** The two subsequent arguments should be the name of the OS function that ** failed and the associated file-system path, if any. */ @@ -36670,7 +33448,7 @@ static int winLogErrorAtLine( /* ** The number of times that a ReadFile(), WriteFile(), and DeleteFile() -** will be retried following a locking error - probably caused by +** will be retried following a locking error - probably caused by ** antivirus software. Also the initial delay before the first retry. ** The delay increases linearly with each retry. */ @@ -36743,11 +33521,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){ /* ** Log a I/O error retry episode. */ -static void winLogIoerr(int nRetry, int lineno){ +static void winLogIoerr(int nRetry){ if( nRetry ){ - sqlite3_log(SQLITE_NOTICE, - "delayed %dms for lock/sharing conflict at line %d", - winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno + sqlite3_log(SQLITE_IOERR, + "delayed %dms for lock/sharing conflict", + winIoerrRetryDelay*nRetry*(nRetry+1)/2 ); } } @@ -36839,17 +33617,17 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){ /* Acquire the mutex before continuing */ winceMutexAcquire(pFile->hMutex); - - /* Since the names of named mutexes, semaphores, file mappings etc are + + /* Since the names of named mutexes, semaphores, file mappings etc are ** case-sensitive, take advantage of that by uppercasing the mutex name ** and using that as the shared filemapping name. */ osCharUpperW(zName); pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(winceLock), - zName); + zName); - /* Set a flag that indicates we're the first to create the memory so it + /* Set a flag that indicates we're the first to create the memory so it ** must be zero-initialized */ lastErrno = osGetLastError(); if (lastErrno == ERROR_ALREADY_EXISTS){ @@ -36860,7 +33638,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){ /* If we succeeded in making the shared memory handle, map it. */ if( pFile->hShared ){ - pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, + pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); /* If mapping failed, close the shared memory handle and erase it */ if( !pFile->shared ){ @@ -36886,7 +33664,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){ pFile->hMutex = NULL; return SQLITE_IOERR; } - + /* Initialize the shared memory if we're supposed to */ if( bInit ){ memset(pFile->shared, 0, sizeof(winceLock)); @@ -36924,13 +33702,13 @@ static void winceDestroyLock(winFile *pFile){ osCloseHandle(pFile->hShared); /* Done with the mutex */ - winceMutexRelease(pFile->hMutex); + winceMutexRelease(pFile->hMutex); osCloseHandle(pFile->hMutex); pFile->hMutex = NULL; } } -/* +/* ** An implementation of the LockFile() API of Windows for CE */ static BOOL winceLockFile( @@ -37141,8 +33919,8 @@ static BOOL winUnlockFile( #endif /* -** Move the current position of the file handle passed as the first -** argument to offset iOffset within the file. If successful, return 0. +** Move the current position of the file handle passed as the first +** argument to offset iOffset within the file. If successful, return 0. ** Otherwise, set pFile->lastErrno and return non-zero. */ static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ @@ -37157,11 +33935,11 @@ static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ upperBits = (LONG)((iOffset>>32) & 0x7fffffff); lowerBits = (LONG)(iOffset & 0xffffffff); - /* API oddity: If successful, SetFilePointer() returns a dword + /* API oddity: If successful, SetFilePointer() returns a dword ** containing the lower 32-bits of the new file-offset. Or, if it fails, - ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, - ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine - ** whether an error has actually occurred, it is also necessary to call + ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, + ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine + ** whether an error has actually occurred, it is also necessary to call ** GetLastError(). */ dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); @@ -37227,8 +34005,7 @@ static int winClose(sqlite3_file *id){ assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); - OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("CLOSE file=%p\n", pFile->h)); #if SQLITE_MAX_MMAP_SIZE>0 winUnmapfile(pFile); @@ -37245,7 +34022,7 @@ static int winClose(sqlite3_file *id){ int cnt = 0; while( osDeleteFileW(pFile->zDeleteOnClose)==0 - && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff + && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff && cnt++ < WINCE_DELETION_ATTEMPTS ){ sqlite3_win32_sleep(100); /* Wait a little before trying again */ @@ -37257,8 +34034,7 @@ static int winClose(sqlite3_file *id){ pFile->h = NULL; } OpenCounter(-1); - OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", - osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); + OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed")); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), "winClose", pFile->zPath); @@ -37275,7 +34051,7 @@ static int winRead( int amt, /* Number of bytes to read */ sqlite3_int64 offset /* Begin reading at this offset */ ){ -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) +#if !SQLITE_OS_WINCE OVERLAPPED overlapped; /* The offset for ReadFile. */ #endif winFile *pFile = (winFile*)id; /* file handle */ @@ -37286,8 +34062,7 @@ static int winRead( assert( amt>0 ); assert( offset>=0 ); SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " - "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, + OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 @@ -37296,8 +34071,7 @@ static int winRead( if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -37309,10 +34083,9 @@ static int winRead( } #endif -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) +#if SQLITE_OS_WINCE if( winSeekFile(pFile, offset) ){ - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ @@ -37326,22 +34099,19 @@ static int winRead( DWORD lastErrno; if( winRetryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h)); return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, "winRead", pFile->zPath); } - winLogIoerr(nRetry, __LINE__); + winLogIoerr(nRetry); if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h)); return SQLITE_IOERR_SHORT_READ; } - OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } @@ -37364,18 +34134,16 @@ static int winWrite( SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " - "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, + OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", pFile->h, pBuf, amt, offset, pFile->locktype)); -#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_MAX_MMAP_SIZE>0 /* Deal with as much of this write request as possible by transfering ** data from the memory mapping using memcpy(). */ if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -37387,13 +34155,13 @@ static int winWrite( } #endif -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) +#if SQLITE_OS_WINCE rc = winSeekFile(pFile, offset); if( rc==0 ){ #else { #endif -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) +#if !SQLITE_OS_WINCE OVERLAPPED overlapped; /* The offset for WriteFile. */ #endif u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ @@ -37401,14 +34169,14 @@ static int winWrite( DWORD nWrite; /* Bytes written by each WriteFile() call */ DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) +#if !SQLITE_OS_WINCE memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.Offset = (LONG)(offset & 0xffffffff); overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); #endif while( nRem>0 ){ -#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) +#if SQLITE_OS_WINCE if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ #else if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ @@ -37421,7 +34189,7 @@ static int winWrite( lastErrno = osGetLastError(); break; } -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) +#if !SQLITE_OS_WINCE offset += nWrite; overlapped.Offset = (LONG)(offset & 0xffffffff); overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); @@ -37438,20 +34206,17 @@ static int winWrite( if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h)); return winLogError(SQLITE_FULL, pFile->lastErrno, "winWrite1", pFile->zPath); } - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h)); return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, "winWrite2", pFile->zPath); }else{ - winLogIoerr(nRetry, __LINE__); + winLogIoerr(nRetry); } - OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } @@ -37465,8 +34230,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ assert( pFile ); SimulateIOError(return SQLITE_IOERR_TRUNCATE); - OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", - osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); + OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n", + pFile->h, nByte, pFile->locktype)); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the @@ -37498,8 +34263,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ } #endif - OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", - osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); + OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); return rc; } @@ -37523,7 +34287,7 @@ static int winSync(sqlite3_file *id, int flags){ BOOL rc; #endif #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ - defined(SQLITE_HAVE_OS_TRACE) + (defined(SQLITE_TEST) && defined(SQLITE_DEBUG)) /* ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or ** OSTRACE() macros. @@ -37544,9 +34308,8 @@ static int winSync(sqlite3_file *id, int flags){ */ SimulateDiskfullError( return SQLITE_FULL ); - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", - osGetCurrentProcessId(), pFile, pFile->h, flags, - pFile->locktype)); + OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n", + pFile->h, flags, pFile->locktype)); #ifndef SQLITE_TEST UNUSED_PARAMETER(flags); @@ -37561,38 +34324,19 @@ static int winSync(sqlite3_file *id, int flags){ ** no-op */ #ifdef SQLITE_NO_SYNC - OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; #else -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->pMapRegion ){ - if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ - OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_OK\n", osGetCurrentProcessId(), - pFile, pFile->pMapRegion)); - }else{ - pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), - pFile, pFile->pMapRegion)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winSync1", pFile->zPath); - } - } -#endif rc = osFlushFileBuffers(pFile->h); SimulateIOError( rc=FALSE ); if( rc ){ - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; }else{ pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", - osGetCurrentProcessId(), pFile, pFile->h)); + OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h)); return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, - "winSync2", pFile->zPath); + "winSync", pFile->zPath); } #endif } @@ -37781,12 +34525,6 @@ static int winLock(sqlite3_file *id, int locktype){ return SQLITE_OK; } - /* Do not allow any kind of write-lock on a read-only database - */ - if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){ - return SQLITE_IOERR_LOCK; - } - /* Make sure the locking sequence is correct */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); @@ -37916,7 +34654,7 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ res = 1; OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res)); }else{ - res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE,0,1,0); + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); if( res ){ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } @@ -37974,7 +34712,7 @@ static int winUnlock(sqlite3_file *id, int locktype){ } /* -** If *pArg is initially negative then this is a query. Set *pArg to +** If *pArg is inititially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. @@ -38132,7 +34870,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){ ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } -/* +/* ** Windows will only let you create file view mappings ** on allocation size granularity boundaries. ** During sqlite3_os_init() we do a GetSystemInfo() @@ -38144,11 +34882,11 @@ static SYSTEM_INFO winSysInfo; /* ** Helper functions to obtain and relinquish the global mutex. The -** global mutex is used to protect the winLockInfo objects used by +** global mutex is used to protect the winLockInfo objects used by ** this file, all of which may be shared by multiple threads. ** -** Function winShmMutexHeld() is used to assert() that the global mutex -** is held when required. This function is only used as part of assert() +** Function winShmMutexHeld() is used to assert() that the global mutex +** is held when required. This function is only used as part of assert() ** statements. e.g. ** ** winShmEnterMutex() @@ -38156,14 +34894,14 @@ static SYSTEM_INFO winSysInfo; ** winShmLeaveMutex() */ static void winShmEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #ifndef NDEBUG static int winShmMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #endif @@ -38178,10 +34916,10 @@ static int winShmMutexHeld(void) { ** this object or while reading or writing the following fields: ** ** nRef -** pNext +** pNext ** ** The following fields are read-only after the object is created: -** +** ** fid ** zFilename ** @@ -38206,7 +34944,7 @@ struct winShmNode { int nRef; /* Number of winShm objects pointing to this */ winShm *pFirst; /* All winShm objects pointing to this */ winShmNode *pNext; /* Next in list of all winShmNode objects */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +#ifdef SQLITE_DEBUG u8 nextShmId; /* Next available winShm.id value */ #endif }; @@ -38237,7 +34975,7 @@ struct winShm { u8 hasMutex; /* True if holding the winShmNode mutex */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +#ifdef SQLITE_DEBUG u8 id; /* Id of this connection with its winShmNode */ #endif }; @@ -38277,7 +35015,7 @@ static int winShmSystemLock( if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); } - + if( rc!= 0 ){ rc = SQLITE_OK; }else{ @@ -38373,7 +35111,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ } pNew->zFilename = (char*)&pNew[1]; sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); - sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); + sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); /* Look to see if there is an existing winShmNode that can be used. ** If no matching winShmNode currently exists, create a new one. @@ -38410,7 +35148,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ } /* Check to see if another process is holding the dead-man switch. - ** If not, truncate the file to zero length. + ** If not, truncate the file to zero length. */ if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); @@ -38428,7 +35166,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Make the new connection a child of the winShmNode */ p->pShmNode = pShmNode; -#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +#ifdef SQLITE_DEBUG p->id = pShmNode->nextShmId++; #endif pShmNode->nRef++; @@ -38439,7 +35177,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ ** the cover of the winShmEnterMutex() mutex and the pointer from the ** new (struct winShm) object to the pShmNode has been set. All that is ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex + ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex ** mutex. */ sqlite3_mutex_enter(pShmNode->mutex); @@ -38459,7 +35197,7 @@ shm_open_err: } /* -** Close a connection to shared-memory. Delete the underlying +** Close a connection to shared-memory. Delete the underlying ** storage if deleteFlag is true. */ static int winShmUnmap( @@ -38548,7 +35286,7 @@ static int winShmLock( if( rc==SQLITE_OK ){ p->exclMask &= ~mask; p->sharedMask &= ~mask; - } + } }else if( flags & SQLITE_SHM_SHARED ){ u16 allShared = 0; /* Union of locks held by connections other than "p" */ @@ -38587,7 +35325,7 @@ static int winShmLock( break; } } - + /* Get the exclusive locks at the system level. Then if successful ** also mark the local connection as being locked. */ @@ -38607,7 +35345,7 @@ static int winShmLock( } /* -** Implement a memory barrier or memory fence on shared memory. +** Implement a memory barrier or memory fence on shared memory. ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. @@ -38616,28 +35354,28 @@ static void winShmBarrier( sqlite3_file *fd /* Database holding the shared memory */ ){ UNUSED_PARAMETER(fd); - sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ - winShmEnterMutex(); /* Also mutex, for redundancy */ + /* MemoryBarrier(); // does not work -- do not know why not */ + winShmEnterMutex(); winShmLeaveMutex(); } /* -** This function is called to obtain a pointer to region iRegion of the -** shared-memory associated with the database file fd. Shared-memory regions -** are numbered starting from zero. Each shared-memory region is szRegion +** This function is called to obtain a pointer to region iRegion of the +** shared-memory associated with the database file fd. Shared-memory regions +** are numbered starting from zero. Each shared-memory region is szRegion ** bytes in size. ** ** If an error occurs, an error code is returned and *pp is set to NULL. ** ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory ** region has not been allocated (by any client, including one running in a -** separate process), then *pp is set to NULL and SQLITE_OK returned. If -** isWrite is non-zero and the requested shared-memory region has not yet +** separate process), then *pp is set to NULL and SQLITE_OK returned. If +** isWrite is non-zero and the requested shared-memory region has not yet ** been allocated, it is allocated by this function. ** ** If the shared-memory region has already been allocated or is allocated by -** this call as described above, then it is mapped into this processes -** address space (if it is not already), *pp is set to point to the mapped +** this call as described above, then it is mapped into this processes +** address space (if it is not already), *pp is set to point to the mapped ** memory and SQLITE_OK returned. */ static int winShmMap( @@ -38648,16 +35386,16 @@ static int winShmMap( void volatile **pp /* OUT: Mapped memory */ ){ winFile *pDbFd = (winFile*)fd; - winShm *pShm = pDbFd->pShm; + winShm *p = pDbFd->pShm; winShmNode *pShmNode; int rc = SQLITE_OK; - if( !pShm ){ + if( !p ){ rc = winOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; - pShm = pDbFd->pShm; + p = pDbFd->pShm; } - pShmNode = pShm->pShmNode; + pShmNode = p->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); @@ -38697,7 +35435,7 @@ static int winShmMap( } /* Map the requested memory region into this processes address space. */ - apNew = (struct ShmRegion *)sqlite3_realloc64( + apNew = (struct ShmRegion *)sqlite3_realloc( pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) ); if( !apNew ){ @@ -38709,17 +35447,17 @@ static int winShmMap( while( pShmNode->nRegion<=iRegion ){ HANDLE hMap = NULL; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ - + #if SQLITE_OS_WINRT hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, NULL, PAGE_READWRITE, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_WIDE) - hMap = osCreateFileMappingW(pShmNode->hFile.h, + hMap = osCreateFileMappingW(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) - hMap = osCreateFileMappingA(pShmNode->hFile.h, + hMap = osCreateFileMappingA(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #endif @@ -38816,14 +35554,14 @@ static int winUnmapfile(winFile *pFile){ /* ** Memory map or remap the file opened by file-descriptor pFd (if the file -** is already mapped, the existing mapping is replaced by the new). Or, if -** there already exists a mapping for this file, and there are still +** is already mapped, the existing mapping is replaced by the new). Or, if +** there already exists a mapping for this file, and there are still ** outstanding xFetch() references to it, this function is a no-op. ** -** If parameter nByte is non-negative, then it is the requested size of -** the mapping to create. Otherwise, if nByte is less than zero, then the +** If parameter nByte is non-negative, then it is the requested size of +** the mapping to create. Otherwise, if nByte is less than zero, then the ** requested size is the size of the file on disk. The actual size of the -** created mapping is either the requested size or the value configured +** created mapping is either the requested size or the value configured ** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller. ** ** SQLITE_OK is returned if no error occurs (even if the mapping is not @@ -38852,7 +35590,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ nMap = pFd->mmapSizeMax; } nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1); - + if( nMap==0 && pFd->mmapSize>0 ){ winUnmapfile(pFd); } @@ -38862,12 +35600,10 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ DWORD flags = FILE_MAP_READ; winUnmapfile(pFd); -#ifdef SQLITE_MMAP_READWRITE if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ protect = PAGE_READWRITE; flags |= FILE_MAP_WRITE; } -#endif #if SQLITE_OS_WINRT pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); #elif defined(SQLITE_WIN32_HAS_WIDE) @@ -38926,7 +35662,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ ** Finally, if an error does occur, return an SQLite error code. The final ** value of *pp is undefined in this case. ** -** If this function does return a pointer, the caller must eventually +** If this function does return a pointer, the caller must eventually ** release the reference by calling winUnfetch(). */ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ @@ -38961,20 +35697,20 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ } /* -** If the third argument is non-NULL, then this function releases a +** If the third argument is non-NULL, then this function releases a ** reference obtained by an earlier call to winFetch(). The second ** argument passed to this function must be the same as the corresponding -** argument that was passed to the winFetch() invocation. +** argument that was passed to the winFetch() invocation. ** -** Or, if the third argument is NULL, then this function is being called -** to inform the VFS layer that, according to POSIX, any existing mapping +** Or, if the third argument is NULL, then this function is being called +** to inform the VFS layer that, according to POSIX, any existing mapping ** may now be invalid and should be unmapped. */ static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ #if SQLITE_MAX_MMAP_SIZE>0 winFile *pFd = (winFile*)fd; /* The underlying database file */ - /* If p==0 (unmap the entire file) then there must be no outstanding + /* If p==0 (unmap the entire file) then there must be no outstanding ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), ** then there must be at least one outstanding. */ assert( (p==0)==(pFd->nFetchOut==0) ); @@ -38990,7 +35726,7 @@ static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ }else{ /* FIXME: If Windows truly always prevents truncating or deleting a ** file while a mapping is held, then the following winUnmapfile() call - ** is unnecessary can be omitted - potentially improving + ** is unnecessary can can be omitted - potentially improving ** performance. */ winUnmapfile(pFd); } @@ -39120,7 +35856,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this - ** function failing. + ** function failing. */ SimulateIOError( return SQLITE_IOERR ); @@ -39302,7 +36038,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ } /* - ** Check that the output buffer is large enough for the temporary file + ** Check that the output buffer is large enough for the temporary file ** name in the following format: ** ** "/etilqs_XXXXXXXXXXXXXXX\0\0" @@ -39405,8 +36141,8 @@ static int winOpen( #ifndef NDEBUG int isOpenJournal = (isCreate && ( - eType==SQLITE_OPEN_MASTER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); #endif @@ -39414,9 +36150,9 @@ static int winOpen( OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n", zUtf8Name, id, flags, pOutFlags)); - /* Check the following statements are true: + /* Check the following statements are true: ** - ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and ** (b) if CREATE is set, then READWRITE must also be set, and ** (c) if EXCLUSIVE is set, then CREATE must also be set. ** (d) if DELETEONCLOSE is set, then CREATE must also be set. @@ -39426,7 +36162,7 @@ static int winOpen( assert(isExclusive==0 || isCreate); assert(isDelete==0 || isCreate); - /* The main DB, main journal, WAL file and master journal are never + /* The main DB, main journal, WAL file and master journal are never ** automatically deleted. Nor are they ever temporary files. */ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); @@ -39434,9 +36170,9 @@ static int winOpen( assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); /* Assert that the upper layer has set one of the "file-type" flags. */ - assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB - || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); @@ -39451,8 +36187,8 @@ static int winOpen( } #endif - /* If the second argument to this function is NULL, generate a - ** temporary file name to use + /* If the second argument to this function is NULL, generate a + ** temporary file name to use */ if( !zUtf8Name ){ assert( isDelete && !isOpenJournal ); @@ -39492,8 +36228,8 @@ static int winOpen( dwDesiredAccess = GENERIC_READ; } - /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is - ** created. SQLite doesn't use it to indicate "exclusive access" + /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is + ** created. SQLite doesn't use it to indicate "exclusive access" ** as it is usually understood. */ if( isExclusive ){ @@ -39571,7 +36307,7 @@ static int winOpen( } } #endif - winLogIoerr(cnt, __LINE__); + winLogIoerr(cnt); OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); @@ -39582,7 +36318,7 @@ static int winOpen( sqlite3_free(zConverted); sqlite3_free(zTmpname); if( isReadWrite && !isExclusive ){ - return winOpen(pVfs, zName, id, + return winOpen(pVfs, zName, id, ((flags|SQLITE_OPEN_READONLY) & ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); @@ -39755,7 +36491,7 @@ static int winDelete( if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); }else{ - winLogIoerr(cnt, __LINE__); + winLogIoerr(cnt); } sqlite3_free(zConverted); OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); @@ -39791,21 +36527,21 @@ static int winAccess( WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, - GetFileExInfoStandard, + GetFileExInfoStandard, &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} if( rc ){ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file ** as if it does not exist. */ if( flags==SQLITE_ACCESS_EXISTS - && sAttrData.nFileSizeHigh==0 + && sAttrData.nFileSizeHigh==0 && sAttrData.nFileSizeLow==0 ){ attr = INVALID_FILE_ATTRIBUTES; }else{ attr = sAttrData.dwFileAttributes; } }else{ - winLogIoerr(cnt, __LINE__); + winLogIoerr(cnt); if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ sqlite3_free(zConverted); return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", @@ -39897,7 +36633,7 @@ static int winFullPathname( int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ - + #if defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); UNUSED_PARAMETER(nFull); @@ -40146,7 +36882,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ int n = 0; UNUSED_PARAMETER(pVfs); -#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) +#if defined(SQLITE_TEST) n = nBuf; memset(zBuf, 0, nBuf); #else @@ -40180,23 +36916,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memcpy(&zBuf[n], &i, sizeof(i)); n += sizeof(i); } -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID - if( sizeof(UUID)<=nBuf-n ){ - UUID id; - memset(&id, 0, sizeof(UUID)); - osUuidCreate(&id); - memcpy(&zBuf[n], &id, sizeof(UUID)); - n += sizeof(UUID); - } - if( sizeof(UUID)<=nBuf-n ){ - UUID id; - memset(&id, 0, sizeof(UUID)); - osUuidCreateSequential(&id); - memcpy(&zBuf[n], &id, sizeof(UUID)); - n += sizeof(UUID); - } #endif -#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ return n; } @@ -40226,12 +36946,12 @@ SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the ** proleptic Gregorian calendar. ** -** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date +** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date ** cannot be found. */ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ - /* FILETIME structure is a 64-bit value representing the number of - 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). + /* FILETIME structure is a 64-bit value representing the number of + 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ FILETIME ft; static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; @@ -40239,7 +36959,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; #endif /* 2^32 - to avoid use of LL and warnings in gcc */ - static const sqlite3_int64 max32BitValue = + static const sqlite3_int64 max32BitValue = (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296; @@ -40255,7 +36975,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ #endif *piNow = winFiletimeEpoch + - ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + + ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; #ifdef SQLITE_TEST @@ -40320,7 +37040,7 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ /* ** Initialize and deinitialize the operating system interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ +SQLITE_API int sqlite3_os_init(void){ static sqlite3_vfs winVfs = { 3, /* iVersion */ sizeof(winFile), /* szOsFile */ @@ -40374,7 +37094,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==80 ); + assert( ArraySize(aSyscall)==76 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); @@ -40392,10 +37112,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){ sqlite3_vfs_register(&winLongPathVfs, 0); #endif - return SQLITE_OK; + return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ +SQLITE_API int sqlite3_os_end(void){ #if SQLITE_OS_WINRT if( sleepObj!=NULL ){ osCloseHandle(sleepObj); @@ -40445,15 +37165,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){ ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. */ -/* #include "sqliteInt.h" */ /* Size of the Bitvec structure in bytes. */ #define BITVEC_SZ 512 /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ -#define BITVEC_USIZE \ - (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) +#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) /* Type of the array "element" for the bitmap representation. ** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. @@ -40538,10 +37256,10 @@ SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){ ** If p is NULL (if the bitmap has not been created) or if ** i is out of range, then return false. */ -SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){ - assert( p!=0 ); +SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ + if( p==0 ) return 0; + if( i>p->iSize || i==0 ) return 0; i--; - if( i>=p->iSize ) return 0; while( p->iDivisor ){ u32 bin = i/p->iDivisor; i = i%p->iDivisor; @@ -40561,9 +37279,6 @@ SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){ return 0; } } -SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ - return p!=0 && sqlite3BitvecTestNotNull(p,i); -} /* ** Set the i-th bit. Return 0 on success and an error code if @@ -40756,7 +37471,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3MallocZero( (sz+7)/8 + 1 ); - pTmpSpace = sqlite3_malloc64(BITVEC_SZ); + pTmpSpace = sqlite3_malloc(BITVEC_SZ); if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ @@ -40836,7 +37551,6 @@ bitvec_end: ************************************************************************* ** This file implements that page cache. */ -/* #include "sqliteInt.h" */ /* ** A complete page cache is an instance of this structure. @@ -40844,9 +37558,8 @@ bitvec_end: struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ - int nRefSum; /* Sum of ref counts over all pages */ + int nRef; /* Number of referenced pages */ int szCache; /* Configured cache size */ - int szSpill; /* Size before spilling occurs */ int szPage; /* Size of every page in this cache */ int szExtra; /* Size of extra space for each page */ u8 bPurgeable; /* True if pages are on backing store */ @@ -40854,75 +37567,105 @@ struct PCache { int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ void *pStress; /* Argument to xStress */ sqlite3_pcache *pCache; /* Pluggable cache module */ + PgHdr *pPage1; /* Reference to page 1 */ }; +/* +** Some of the assert() macros in this code are too expensive to run +** even during normal debugging. Use them only rarely on long-running +** tests. Enable the expensive asserts using the +** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option. +*/ +#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT +# define expensive_assert(X) assert(X) +#else +# define expensive_assert(X) +#endif + /********************************** Linked List Management ********************/ -/* Allowed values for second argument to pcacheManageDirtyList() */ -#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ -#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */ -#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */ +#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) +/* +** Check that the pCache->pSynced variable is set correctly. If it +** is not, either fail an assert or return zero. Otherwise, return +** non-zero. This is only used in debugging builds, as follows: +** +** expensive_assert( pcacheCheckSynced(pCache) ); +*/ +static int pcacheCheckSynced(PCache *pCache){ + PgHdr *p; + for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){ + assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) ); + } + return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0); +} +#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ /* -** Manage pPage's participation on the dirty list. Bits of the addRemove -** argument determines what operation to do. The 0x01 bit means first -** remove pPage from the dirty list. The 0x02 means add pPage back to -** the dirty list. Doing both moves pPage to the front of the dirty list. +** Remove page pPage from the list of dirty pages. */ -static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ +static void pcacheRemoveFromDirtyList(PgHdr *pPage){ PCache *p = pPage->pCache; - if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ - assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); - assert( pPage->pDirtyPrev || pPage==p->pDirty ); - - /* Update the PCache1.pSynced variable if necessary. */ - if( p->pSynced==pPage ){ - PgHdr *pSynced = pPage->pDirtyPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pDirtyPrev; - } - p->pSynced = pSynced; + assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); + assert( pPage->pDirtyPrev || pPage==p->pDirty ); + + /* Update the PCache1.pSynced variable if necessary. */ + if( p->pSynced==pPage ){ + PgHdr *pSynced = pPage->pDirtyPrev; + while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ + pSynced = pSynced->pDirtyPrev; } - - if( pPage->pDirtyNext ){ - pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; - }else{ - assert( pPage==p->pDirtyTail ); - p->pDirtyTail = pPage->pDirtyPrev; - } - if( pPage->pDirtyPrev ){ - pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; - }else{ - assert( pPage==p->pDirty ); - p->pDirty = pPage->pDirtyNext; - if( p->pDirty==0 && p->bPurgeable ){ - assert( p->eCreate==1 ); - p->eCreate = 2; - } - } - pPage->pDirtyNext = 0; - pPage->pDirtyPrev = 0; + p->pSynced = pSynced; } - if( addRemove & PCACHE_DIRTYLIST_ADD ){ - assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - - pPage->pDirtyNext = p->pDirty; - if( pPage->pDirtyNext ){ - assert( pPage->pDirtyNext->pDirtyPrev==0 ); - pPage->pDirtyNext->pDirtyPrev = pPage; - }else{ - p->pDirtyTail = pPage; - if( p->bPurgeable ){ - assert( p->eCreate==2 ); - p->eCreate = 1; - } - } - p->pDirty = pPage; - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ - p->pSynced = pPage; + + if( pPage->pDirtyNext ){ + pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; + }else{ + assert( pPage==p->pDirtyTail ); + p->pDirtyTail = pPage->pDirtyPrev; + } + if( pPage->pDirtyPrev ){ + pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; + }else{ + assert( pPage==p->pDirty ); + p->pDirty = pPage->pDirtyNext; + if( p->pDirty==0 && p->bPurgeable ){ + assert( p->eCreate==1 ); + p->eCreate = 2; } } + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; + + expensive_assert( pcacheCheckSynced(p) ); +} + +/* +** Add page pPage to the head of the dirty list (PCache1.pDirty is set to +** pPage). +*/ +static void pcacheAddToDirtyList(PgHdr *pPage){ + PCache *p = pPage->pCache; + + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); + + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); + pPage->pDirtyNext->pDirtyPrev = pPage; + }else if( p->bPurgeable ){ + assert( p->eCreate==2 ); + p->eCreate = 1; + } + p->pDirty = pPage; + if( !p->pDirtyTail ){ + p->pDirtyTail = pPage; + } + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + p->pSynced = pPage; + } + expensive_assert( pcacheCheckSynced(p) ); } /* @@ -40930,25 +37673,12 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ ** being used for an in-memory database, this function is a no-op. */ static void pcacheUnpin(PgHdr *p){ - if( p->pCache->bPurgeable ){ - sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); - } -} - -/* -** Compute the number of pages of cache requested. p->szCache is the -** cache size requested by the "PRAGMA cache_size" statement. -*/ -static int numberOfCachePages(PCache *p){ - if( p->szCache>=0 ){ - /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the - ** suggested cache size is set to N. */ - return p->szCache; - }else{ - /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then - ** the number of cache pages is adjusted to use approximately abs(N*1024) - ** bytes of memory. */ - return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); + PCache *pCache = p->pCache; + if( pCache->bPurgeable ){ + if( p->pgno==1 ){ + pCache->pPage1 = 0; + } + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0); } } @@ -40984,7 +37714,7 @@ SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } ** The caller discovers how much space needs to be allocated by ** calling sqlite3PcacheSize(). */ -SQLITE_PRIVATE int sqlite3PcacheOpen( +SQLITE_PRIVATE void sqlite3PcacheOpen( int szPage, /* Size of every page */ int szExtra, /* Extra space associated with each page */ int bPurgeable, /* True if pages are on backing store */ @@ -40993,76 +37723,76 @@ SQLITE_PRIVATE int sqlite3PcacheOpen( PCache *p /* Preallocated space for the PCache */ ){ memset(p, 0, sizeof(PCache)); - p->szPage = 1; + p->szPage = szPage; p->szExtra = szExtra; p->bPurgeable = bPurgeable; p->eCreate = 2; p->xStress = xStress; p->pStress = pStress; p->szCache = 100; - p->szSpill = 1; - return sqlite3PcacheSetPageSize(p, szPage); } /* ** Change the page size for PCache object. The caller must ensure that there ** are no outstanding page references when this function is called. */ -SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ - assert( pCache->nRefSum==0 && pCache->pDirty==0 ); - if( pCache->szPage ){ - sqlite3_pcache *pNew; - pNew = sqlite3GlobalConfig.pcache2.xCreate( - szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), - pCache->bPurgeable - ); - if( pNew==0 ) return SQLITE_NOMEM; - sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); - } - pCache->pCache = pNew; - pCache->szPage = szPage; +SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ + assert( pCache->nRef==0 && pCache->pDirty==0 ); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); + pCache->pCache = 0; + pCache->pPage1 = 0; + } + pCache->szPage = szPage; +} + +/* +** Compute the number of pages of cache requested. +*/ +static int numberOfCachePages(PCache *p){ + if( p->szCache>=0 ){ + return p->szCache; + }else{ + return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); } - return SQLITE_OK; } /* ** Try to obtain a page from the cache. -** -** This routine returns a pointer to an sqlite3_pcache_page object if -** such an object is already in cache, or if a new one is created. -** This routine returns a NULL pointer if the object was not in cache -** and could not be created. -** -** The createFlags should be 0 to check for existing pages and should -** be 3 (not 1, but 3) to try to create a new page. -** -** If the createFlag is 0, then NULL is always returned if the page -** is not already in the cache. If createFlag is 1, then a new page -** is created only if that can be done without spilling dirty pages -** and without exceeding the cache size limit. -** -** The caller needs to invoke sqlite3PcacheFetchFinish() to properly -** initialize the sqlite3_pcache_page object and convert it into a -** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish() -** routines are split this way for performance reasons. When separated -** they can both (usually) operate without having to push values to -** the stack on entry and pop them back off on exit, which saves a -** lot of pushing and popping. */ -SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( +SQLITE_PRIVATE int sqlite3PcacheFetch( PCache *pCache, /* Obtain the page from this cache */ Pgno pgno, /* Page number to obtain */ - int createFlag /* If true, create page if it does not exist already */ + int createFlag, /* If true, create page if it does not exist already */ + PgHdr **ppPage /* Write the page here */ ){ + sqlite3_pcache_page *pPage; + PgHdr *pPgHdr = 0; int eCreate; assert( pCache!=0 ); - assert( pCache->pCache!=0 ); - assert( createFlag==3 || createFlag==0 ); + assert( createFlag==1 || createFlag==0 ); assert( pgno>0 ); + /* If the pluggable cache (sqlite3_pcache*) has not been allocated, + ** allocate it now. + */ + if( !pCache->pCache ){ + sqlite3_pcache *p; + if( !createFlag ){ + *ppPage = 0; + return SQLITE_OK; + } + p = sqlite3GlobalConfig.pcache2.xCreate( + pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable + ); + if( !p ){ + return SQLITE_NOMEM; + } + sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache)); + pCache->pCache = p; + } + /* eCreate defines what to do if the page does not exist. ** 0 Do not allocate a new page. (createFlag==0) ** 1 Allocate a new page if doing so is inexpensive. @@ -41070,38 +37800,18 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( ** 2 Allocate a new page even it doing so is difficult. ** (createFlag==1 AND !(bPurgeable AND pDirty) */ - eCreate = createFlag & pCache->eCreate; - assert( eCreate==0 || eCreate==1 || eCreate==2 ); - assert( createFlag==0 || pCache->eCreate==eCreate ); - assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); - return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); -} + eCreate = createFlag==0 ? 0 : pCache->eCreate; + assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate ); + pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); + if( !pPage && eCreate==1 ){ + PgHdr *pPg; -/* -** If the sqlite3PcacheFetch() routine is unable to allocate a new -** page because new clean pages are available for reuse and the cache -** size limit has been reached, then this routine can be invoked to -** try harder to allocate a page. This routine might invoke the stress -** callback to spill dirty pages to the journal. It will then try to -** allocate the new page and will only fail to allocate a new page on -** an OOM error. -** -** This routine should be invoked only after sqlite3PcacheFetch() fails. -*/ -SQLITE_PRIVATE int sqlite3PcacheFetchStress( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number to obtain */ - sqlite3_pcache_page **ppPage /* Write result here */ -){ - PgHdr *pPg; - if( pCache->eCreate==2 ) return 0; - - if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){ /* Find a dirty page to write-out and recycle. First try to find a ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. */ + expensive_assert( pcacheCheckSynced(pCache) ); for(pPg=pCache->pSynced; pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); pPg=pPg->pDirtyPrev @@ -41117,84 +37827,62 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress( "spill page %d making room for %d - cache used: %d/%d", pPg->pgno, pgno, sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), - numberOfCachePages(pCache)); + numberOfCachePages(pCache)); #endif rc = pCache->xStress(pCache->pStress, pPg); if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ return rc; } } + + pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); } - *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); - return *ppPage==0 ? SQLITE_NOMEM : SQLITE_OK; -} -/* -** This is a helper routine for sqlite3PcacheFetchFinish() -** -** In the uncommon case where the page being fetched has not been -** initialized, this routine is invoked to do the initialization. -** This routine is broken out into a separate function since it -** requires extra stack manipulation that can be avoided in the common -** case. -*/ -static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number obtained */ - sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ -){ - PgHdr *pPgHdr; - assert( pPage!=0 ); - pPgHdr = (PgHdr*)pPage->pExtra; - assert( pPgHdr->pPage==0 ); - memset(pPgHdr, 0, sizeof(PgHdr)); - pPgHdr->pPage = pPage; - pPgHdr->pData = pPage->pBuf; - pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, pCache->szExtra); - pPgHdr->pCache = pCache; - pPgHdr->pgno = pgno; - pPgHdr->flags = PGHDR_CLEAN; - return sqlite3PcacheFetchFinish(pCache,pgno,pPage); -} + if( pPage ){ + pPgHdr = (PgHdr *)pPage->pExtra; -/* -** This routine converts the sqlite3_pcache_page object returned by -** sqlite3PcacheFetch() into an initialized PgHdr object. This routine -** must be called after sqlite3PcacheFetch() in order to get a usable -** result. -*/ -SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number obtained */ - sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */ -){ - PgHdr *pPgHdr; + if( !pPgHdr->pPage ){ + memset(pPgHdr, 0, sizeof(PgHdr)); + pPgHdr->pPage = pPage; + pPgHdr->pData = pPage->pBuf; + pPgHdr->pExtra = (void *)&pPgHdr[1]; + memset(pPgHdr->pExtra, 0, pCache->szExtra); + pPgHdr->pCache = pCache; + pPgHdr->pgno = pgno; + } + assert( pPgHdr->pCache==pCache ); + assert( pPgHdr->pgno==pgno ); + assert( pPgHdr->pData==pPage->pBuf ); + assert( pPgHdr->pExtra==(void *)&pPgHdr[1] ); - assert( pPage!=0 ); - pPgHdr = (PgHdr *)pPage->pExtra; - - if( !pPgHdr->pPage ){ - return pcacheFetchFinishWithInit(pCache, pgno, pPage); + if( 0==pPgHdr->nRef ){ + pCache->nRef++; + } + pPgHdr->nRef++; + if( pgno==1 ){ + pCache->pPage1 = pPgHdr; + } } - pCache->nRefSum++; - pPgHdr->nRef++; - return pPgHdr; + *ppPage = pPgHdr; + return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; } /* ** Decrement the reference count on a page. If the page is clean and the -** reference count drops to 0, then it is made eligible for recycling. +** reference count drops to 0, then it is made elible for recycling. */ -SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ +SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){ assert( p->nRef>0 ); - p->pCache->nRefSum--; - if( (--p->nRef)==0 ){ - if( p->flags&PGHDR_CLEAN ){ + p->nRef--; + if( p->nRef==0 ){ + PCache *pCache = p->pCache; + pCache->nRef--; + if( (p->flags&PGHDR_DIRTY)==0 ){ pcacheUnpin(p); - }else if( p->pDirtyPrev!=0 ){ + }else{ /* Move the page to the head of the dirty list. */ - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + pcacheRemoveFromDirtyList(p); + pcacheAddToDirtyList(p); } } } @@ -41205,7 +37893,6 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ assert(p->nRef>0); p->nRef++; - p->pCache->nRefSum++; } /* @@ -41214,12 +37901,17 @@ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ ** page pointed to by p is invalid. */ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ + PCache *pCache; assert( p->nRef==1 ); if( p->flags&PGHDR_DIRTY ){ - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); + pcacheRemoveFromDirtyList(p); } - p->pCache->nRefSum--; - sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); + pCache = p->pCache; + pCache->nRef--; + if( p->pgno==1 ){ + pCache->pPage1 = 0; + } + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1); } /* @@ -41227,14 +37919,11 @@ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ ** make it so. */ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ + p->flags &= ~PGHDR_DONT_WRITE; assert( p->nRef>0 ); - if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ - p->flags &= ~PGHDR_DONT_WRITE; - if( p->flags & PGHDR_CLEAN ){ - p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); - assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); - } + if( 0==(p->flags & PGHDR_DIRTY) ){ + p->flags |= PGHDR_DIRTY; + pcacheAddToDirtyList( p); } } @@ -41244,10 +37933,8 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ if( (p->flags & PGHDR_DIRTY) ){ - assert( (p->flags & PGHDR_CLEAN)==0 ); - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); - p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); - p->flags |= PGHDR_CLEAN; + pcacheRemoveFromDirtyList(p); + p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC); if( p->nRef==0 ){ pcacheUnpin(p); } @@ -41285,7 +37972,8 @@ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ - pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + pcacheRemoveFromDirtyList(p); + pcacheAddToDirtyList(p); } } @@ -41314,14 +38002,9 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ sqlite3PcacheMakeClean(p); } } - if( pgno==0 && pCache->nRefSum ){ - sqlite3_pcache_page *pPage1; - pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0); - if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because - ** pCache->nRefSum>0 */ - memset(pPage1->pBuf, 0, pCache->szPage); - pgno = 1; - } + if( pgno==0 && pCache->pPage1 ){ + memset(pCache->pPage1->pData, 0, pCache->szPage); + pgno = 1; } sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1); } @@ -41331,8 +38014,9 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ ** Close a cache. */ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ - assert( pCache->pCache!=0 ); - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); + } } /* @@ -41424,13 +38108,10 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){ } /* -** Return the total number of references to all pages held by the cache. -** -** This is not the total number of pages referenced, but the sum of the -** reference count for all pages. +** Return the total number of referenced pages held by the cache. */ SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ - return pCache->nRefSum; + return pCache->nRef; } /* @@ -41444,8 +38125,11 @@ SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ ** Return the total number of pages in the cache. */ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){ - assert( pCache->pCache!=0 ); - return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); + int nPage = 0; + if( pCache->pCache ){ + nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); + } + return nPage; } #ifdef SQLITE_TEST @@ -41461,46 +38145,22 @@ SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){ ** Set the suggested cache-size value. */ SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ - assert( pCache->pCache!=0 ); pCache->szCache = mxPage; - sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, - numberOfCachePages(pCache)); -} - -/* -** Set the suggested cache-spill value. Make no changes if if the -** argument is zero. Return the effective cache-spill size, which will -** be the larger of the szSpill and szCache. -*/ -SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){ - int res; - assert( p->pCache!=0 ); - if( mxPage ){ - if( mxPage<0 ){ - mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra)); - } - p->szSpill = mxPage; + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, + numberOfCachePages(pCache)); } - res = numberOfCachePages(p); - if( resszSpill ) res = p->szSpill; - return res; } /* ** Free up as much memory as possible from the page cache. */ SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){ - assert( pCache->pCache!=0 ); - sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); + } } -/* -** Return the size of the header added by this middleware layer -** in the page-cache hierarchy. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } - - #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified @@ -41532,100 +38192,18 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd ** This file implements the default page cache implementation (the ** sqlite3_pcache interface). It also contains part of the implementation ** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. -** If the default page cache implementation is overridden, then neither of +** If the default page cache implementation is overriden, then neither of ** these two features are available. -** -** A Page cache line looks like this: -** -** ------------------------------------------------------------- -** | database page content | PgHdr1 | MemPage | PgHdr | -** ------------------------------------------------------------- -** -** The database page content is up front (so that buffer overreads tend to -** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage -** is the extension added by the btree.c module containing information such -** as the database page number and how that database page is used. PgHdr -** is added by the pcache.c layer and contains information used to keep track -** of which pages are "dirty". PgHdr1 is an extension added by this -** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page. -** PgHdr1 contains information needed to look up a page by its page number. -** The superclass sqlite3_pcache_page.pBuf points to the start of the -** database page content and sqlite3_pcache_page.pExtra points to PgHdr. -** -** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at -** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The -** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this -** size can vary according to architecture, compile-time options, and -** SQLite library version number. -** -** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained -** using a separate memory allocation from the database page content. This -** seeks to overcome the "clownshoe" problem (also called "internal -** fragmentation" in academic literature) of allocating a few bytes more -** than a power of two with the memory allocator rounding up to the next -** power of two, and leaving the rounded-up space unused. -** -** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates -** with this module. Information is passed back and forth as PgHdr1 pointers. -** -** The pcache.c and pager.c modules deal pointers to PgHdr objects. -** The btree.c module deals with pointers to MemPage objects. -** -** SOURCE OF PAGE CACHE MEMORY: -** -** Memory for a page might come from any of three sources: -** -** (1) The general-purpose memory allocator - sqlite3Malloc() -** (2) Global page-cache memory provided using sqlite3_config() with -** SQLITE_CONFIG_PAGECACHE. -** (3) PCache-local bulk allocation. -** -** The third case is a chunk of heap memory (defaulting to 100 pages worth) -** that is allocated when the page cache is created. The size of the local -** bulk allocation can be adjusted using -** -** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N). -** -** If N is positive, then N pages worth of memory are allocated using a single -** sqlite3Malloc() call and that memory is used for the first N pages allocated. -** Or if N is negative, then -1024*N bytes of memory are allocated and used -** for as many pages as can be accomodated. -** -** Only one of (2) or (3) can be used. Once the memory available to (2) or -** (3) is exhausted, subsequent allocations fail over to the general-purpose -** memory allocator (1). -** -** Earlier versions of SQLite used only methods (1) and (2). But experiments -** show that method (3) with N==100 provides about a 5% performance boost for -** common workloads. */ -/* #include "sqliteInt.h" */ + typedef struct PCache1 PCache1; typedef struct PgHdr1 PgHdr1; typedef struct PgFreeslot PgFreeslot; typedef struct PGroup PGroup; -/* -** Each cache entry is represented by an instance of the following -** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of -** PgHdr1.pCache->szPage bytes is allocated directly before this structure -** in memory. -*/ -struct PgHdr1 { - sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ - unsigned int iKey; /* Key value (page number) */ - u8 isPinned; /* Page in use, not on the LRU list */ - u8 isBulkLocal; /* This page from bulk local storage */ - u8 isAnchor; /* This is the PGroup.lru element */ - PgHdr1 *pNext; /* Next in hash table chain */ - PCache1 *pCache; /* Cache that currently owns this page */ - PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ - PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ -}; - /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set -** of one or more PCaches that are able to recycle each other's unpinned +** of one or more PCaches that are able to recycle each others unpinned ** pages when they are under memory pressure. A PGroup is an instance of ** the following object. ** @@ -41652,7 +38230,7 @@ struct PGroup { unsigned int nMinPage; /* Sum of nMin for purgeable caches */ unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ unsigned int nCurrentPage; /* Number of purgeable pages allocated */ - PgHdr1 lru; /* The beginning and end of the LRU list */ + PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ }; /* Each page cache is an instance of the following object. Every @@ -41670,9 +38248,8 @@ struct PCache1 { ** The PGroup mutex must be held when accessing nMax. */ PGroup *pGroup; /* PGroup this cache belongs to */ - int szPage; /* Size of database content section */ - int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ - int szAlloc; /* Total size of one pcache line */ + int szPage; /* Size of allocated pages in bytes */ + int szExtra; /* Size of extra space in bytes */ int bPurgeable; /* True if cache is purgeable */ unsigned int nMin; /* Minimum number of pages reserved */ unsigned int nMax; /* Configured "cache_size" value */ @@ -41686,13 +38263,27 @@ struct PCache1 { unsigned int nPage; /* Total number of pages in apHash */ unsigned int nHash; /* Number of slots in apHash[] */ PgHdr1 **apHash; /* Hash table for fast lookup by key */ - PgHdr1 *pFree; /* List of unused pcache-local pages */ - void *pBulk; /* Bulk memory used by pcache-local */ }; /* -** Free slots in the allocator used to divide up the global page cache -** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism. +** Each cache entry is represented by an instance of the following +** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of +** PgHdr1.pCache->szPage bytes is allocated directly before this structure +** in memory. +*/ +struct PgHdr1 { + sqlite3_pcache_page page; + unsigned int iKey; /* Key value (page number) */ + u8 isPinned; /* Page in use, not on the LRU list */ + PgHdr1 *pNext; /* Next in hash table chain */ + PCache1 *pCache; /* Cache that currently owns this page */ + PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ + PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ +}; + +/* +** Free slots in the allocator used to divide up the buffer provided using +** the SQLITE_CONFIG_PAGECACHE mechanism. */ struct PgFreeslot { PgFreeslot *pNext; /* Next free slot */ @@ -41710,12 +38301,10 @@ static SQLITE_WSD struct PCacheGlobal { ** The nFreeSlot and pFree values do require mutex protection. */ int isInit; /* True if initialized */ - int separateCache; /* Use a new PGroup for each PCache */ - int nInitPage; /* Initial bulk allocation size */ int szSlot; /* Size of each free slot */ int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ - void *pStart, *pEnd; /* Bounds of global page cache memory */ + void *pStart, *pEnd; /* Bounds of pagecache malloc range */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ PgFreeslot *pFree; /* Free page blocks */ @@ -41737,20 +38326,12 @@ static SQLITE_WSD struct PCacheGlobal { /* ** Macros to enter and leave the PCache LRU mutex. */ -#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 -# define pcache1EnterMutex(X) assert((X)->mutex==0) -# define pcache1LeaveMutex(X) assert((X)->mutex==0) -# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0 -#else -# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) -# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) -# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1 -#endif +#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) +#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) /******************************************************************************/ /******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ - /* ** This function is called during initialization if a static buffer is ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE @@ -41763,7 +38344,6 @@ static SQLITE_WSD struct PCacheGlobal { SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ if( pcache1.isInit ){ PgFreeslot *p; - if( pBuf==0 ) sz = n = 0; sz = ROUNDDOWN8(sz); pcache1.szSlot = sz; pcache1.nSlot = pcache1.nFreeSlot = n; @@ -41781,44 +38361,6 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ } } -/* -** Try to initialize the pCache->pFree and pCache->pBulk fields. Return -** true if pCache->pFree ends up containing one or more free pages. -*/ -static int pcache1InitBulk(PCache1 *pCache){ - i64 szBulk; - char *zBulk; - if( pcache1.nInitPage==0 ) return 0; - /* Do not bother with a bulk allocation if the cache size very small */ - if( pCache->nMax<3 ) return 0; - sqlite3BeginBenignMalloc(); - if( pcache1.nInitPage>0 ){ - szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; - }else{ - szBulk = -1024 * (i64)pcache1.nInitPage; - } - if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ - szBulk = pCache->szAlloc*pCache->nMax; - } - zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); - sqlite3EndBenignMalloc(); - if( zBulk ){ - int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; - int i; - for(i=0; iszPage]; - pX->page.pBuf = zBulk; - pX->page.pExtra = &pX[1]; - pX->isBulkLocal = 1; - pX->isAnchor = 0; - pX->pNext = pCache->pFree; - pCache->pFree = pX; - zBulk += pCache->szAlloc; - } - } - return pCache->pFree!=0; -} - /* ** Malloc function used within this file to allocate space from the buffer ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no @@ -41831,6 +38373,7 @@ static int pcache1InitBulk(PCache1 *pCache){ static void *pcache1Alloc(int nByte){ void *p = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); if( nByte<=pcache1.szSlot ){ sqlite3_mutex_enter(pcache1.mutex); p = (PgHdr1 *)pcache1.pFree; @@ -41839,8 +38382,7 @@ static void *pcache1Alloc(int nByte){ pcache1.nFreeSlot--; pcache1.bUnderPressure = pcache1.nFreeSlot=0 ); - sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); - sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); } sqlite3_mutex_leave(pcache1.mutex); } @@ -41853,8 +38395,7 @@ static void *pcache1Alloc(int nByte){ if( p ){ int sz = sqlite3MallocSize(p); sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte); - sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); sqlite3_mutex_leave(pcache1.mutex); } #endif @@ -41866,13 +38407,13 @@ static void *pcache1Alloc(int nByte){ /* ** Free an allocated buffer obtained from pcache1Alloc(). */ -static void pcache1Free(void *p){ +static int pcache1Free(void *p){ int nFreed = 0; - if( p==0 ) return; - if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){ + if( p==0 ) return 0; + if( p>=pcache1.pStart && ppNext = pcache1.pFree; pcache1.pFree = pSlot; @@ -41883,14 +38424,15 @@ static void pcache1Free(void *p){ }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); -#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS nFreed = sqlite3MallocSize(p); +#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed); sqlite3_mutex_leave(pcache1.mutex); #endif sqlite3_free(p); } + return nFreed; } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT @@ -41914,72 +38456,58 @@ static int pcache1MemSize(void *p){ /* ** Allocate a new page object initially associated with cache pCache. */ -static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){ +static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ PgHdr1 *p = 0; void *pPg; + /* The group mutex must be released before pcache1Alloc() is called. This + ** is because it may call sqlite3_release_memory(), which assumes that + ** this mutex is not held. */ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ - p = pCache->pFree; - pCache->pFree = p->pNext; - p->pNext = 0; - }else{ -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - /* The group mutex must be released before pcache1Alloc() is called. This - ** is because it might call sqlite3_release_memory(), which assumes that - ** this mutex is not held. */ - assert( pcache1.separateCache==0 ); - assert( pCache->pGroup==&pcache1.grp ); - pcache1LeaveMutex(pCache->pGroup); -#endif - if( benignMalloc ){ sqlite3BeginBenignMalloc(); } + pcache1LeaveMutex(pCache->pGroup); #ifdef SQLITE_PCACHE_SEPARATE_HEADER - pPg = pcache1Alloc(pCache->szPage); - p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); - if( !pPg || !p ){ - pcache1Free(pPg); - sqlite3_free(p); - pPg = 0; - } + pPg = pcache1Alloc(pCache->szPage); + p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); + if( !pPg || !p ){ + pcache1Free(pPg); + sqlite3_free(p); + pPg = 0; + } #else - pPg = pcache1Alloc(pCache->szAlloc); - p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; + pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); + p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; #endif - if( benignMalloc ){ sqlite3EndBenignMalloc(); } -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - pcache1EnterMutex(pCache->pGroup); -#endif - if( pPg==0 ) return 0; + pcache1EnterMutex(pCache->pGroup); + + if( pPg ){ p->page.pBuf = pPg; p->page.pExtra = &p[1]; - p->isBulkLocal = 0; - p->isAnchor = 0; + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage++; + } + return p; } - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage++; - } - return p; + return 0; } /* ** Free a page object allocated by pcache1AllocPage(). +** +** The pointer is allowed to be NULL, which is prudent. But it turns out +** that the current implementation happens to never call this routine +** with a NULL pointer, so we mark the NULL test with ALWAYS(). */ static void pcache1FreePage(PgHdr1 *p){ - PCache1 *pCache; - assert( p!=0 ); - pCache = p->pCache; - assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); - if( p->isBulkLocal ){ - p->pNext = pCache->pFree; - pCache->pFree = p; - }else{ + if( ALWAYS(p) ){ + PCache1 *pCache = p->pCache; + assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); pcache1Free(p->page.pBuf); #ifdef SQLITE_PCACHE_SEPARATE_HEADER sqlite3_free(p); #endif - } - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage--; + if( pCache->bPurgeable ){ + pCache->pGroup->nCurrentPage--; + } } } @@ -42033,7 +38561,7 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){ ** ** The PCache mutex must be held when this function is called. */ -static void pcache1ResizeHash(PCache1 *p){ +static int pcache1ResizeHash(PCache1 *p){ PgHdr1 **apNew; unsigned int nNew; unsigned int i; @@ -42065,6 +38593,8 @@ static void pcache1ResizeHash(PCache1 *p){ p->apHash = apNew; p->nHash = nNew; } + + return (p->apHash ? SQLITE_OK : SQLITE_NOMEM); } /* @@ -42074,35 +38604,41 @@ static void pcache1ResizeHash(PCache1 *p){ ** ** The PGroup mutex must be held when this function is called. */ -static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ +static void pcache1PinPage(PgHdr1 *pPage){ PCache1 *pCache; + PGroup *pGroup; assert( pPage!=0 ); assert( pPage->isPinned==0 ); pCache = pPage->pCache; - assert( pPage->pLruNext ); - assert( pPage->pLruPrev ); - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - pPage->pLruPrev->pLruNext = pPage->pLruNext; - pPage->pLruNext->pLruPrev = pPage->pLruPrev; + pGroup = pCache->pGroup; + assert( pPage->pLruNext || pPage==pGroup->pLruTail ); + assert( pPage->pLruPrev || pPage==pGroup->pLruHead ); + assert( sqlite3_mutex_held(pGroup->mutex) ); + if( pPage->pLruPrev ){ + pPage->pLruPrev->pLruNext = pPage->pLruNext; + }else{ + pGroup->pLruHead = pPage->pLruNext; + } + if( pPage->pLruNext ){ + pPage->pLruNext->pLruPrev = pPage->pLruPrev; + }else{ + pGroup->pLruTail = pPage->pLruPrev; + } pPage->pLruNext = 0; pPage->pLruPrev = 0; pPage->isPinned = 1; - assert( pPage->isAnchor==0 ); - assert( pCache->pGroup->lru.isAnchor==1 ); pCache->nRecyclable--; - return pPage; } /* ** Remove the page supplied as an argument from the hash table ** (PCache1.apHash structure) that it is currently stored in. -** Also free the page if freePage is true. ** ** The PGroup mutex must be held when this function is called. */ -static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){ +static void pcache1RemoveFromHash(PgHdr1 *pPage){ unsigned int h; PCache1 *pCache = pPage->pCache; PgHdr1 **pp; @@ -42113,28 +38649,21 @@ static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){ *pp = (*pp)->pNext; pCache->nPage--; - if( freeFlag ) pcache1FreePage(pPage); } /* ** If there are currently more than nMaxPage pages allocated, try ** to recycle pages to reduce the number allocated to nMaxPage. */ -static void pcache1EnforceMaxPage(PCache1 *pCache){ - PGroup *pGroup = pCache->pGroup; - PgHdr1 *p; +static void pcache1EnforceMaxPage(PGroup *pGroup){ assert( sqlite3_mutex_held(pGroup->mutex) ); - while( pGroup->nCurrentPage>pGroup->nMaxPage - && (p=pGroup->lru.pLruPrev)->isAnchor==0 - ){ + while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ + PgHdr1 *p = pGroup->pLruTail; assert( p->pCache->pGroup==pGroup ); assert( p->isPinned==0 ); pcache1PinPage(p); - pcache1RemoveFromHash(p, 1); - } - if( pCache->nPage==0 && pCache->pBulk ){ - sqlite3_free(pCache->pBulk); - pCache->pBulk = pCache->pFree = 0; + pcache1RemoveFromHash(p); + pcache1FreePage(p); } } @@ -42180,45 +38709,10 @@ static int pcache1Init(void *NotUsed){ UNUSED_PARAMETER(NotUsed); assert( pcache1.isInit==0 ); memset(&pcache1, 0, sizeof(pcache1)); - - - /* - ** The pcache1.separateCache variable is true if each PCache has its own - ** private PGroup (mode-1). pcache1.separateCache is false if the single - ** PGroup in pcache1.grp is used for all page caches (mode-2). - ** - ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT - ** - ** * Use a unified cache in single-threaded applications that have - ** configured a start-time buffer for use as page-cache memory using - ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL - ** pBuf argument. - ** - ** * Otherwise use separate caches (mode-1) - */ -#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) - pcache1.separateCache = 0; -#elif SQLITE_THREADSAFE - pcache1.separateCache = sqlite3GlobalConfig.pPage==0 - || sqlite3GlobalConfig.bCoreMutex>0; -#else - pcache1.separateCache = sqlite3GlobalConfig.pPage==0; -#endif - -#if SQLITE_THREADSAFE if( sqlite3GlobalConfig.bCoreMutex ){ pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); } -#endif - if( pcache1.separateCache - && sqlite3GlobalConfig.nPage!=0 - && sqlite3GlobalConfig.pPage==0 - ){ - pcache1.nInitPage = sqlite3GlobalConfig.nPage; - }else{ - pcache1.nInitPage = 0; - } pcache1.grp.mxPinned = 10; pcache1.isInit = 1; return SQLITE_OK; @@ -42235,9 +38729,6 @@ static void pcache1Shutdown(void *NotUsed){ memset(&pcache1, 0, sizeof(pcache1)); } -/* forward declaration */ -static void pcache1Destroy(sqlite3_pcache *p); - /* ** Implementation of the sqlite3_pcache.xCreate method. ** @@ -42248,38 +38739,46 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ PGroup *pGroup; /* The group the new page cache will belong to */ int sz; /* Bytes of memory required to allocate the new cache */ + /* + ** The separateCache variable is true if each PCache has its own private + ** PGroup. In other words, separateCache is true for mode (1) where no + ** mutexing is required. + ** + ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT + ** + ** * Always use a unified cache in single-threaded applications + ** + ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off) + ** use separate caches (mode-1) + */ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 + const int separateCache = 0; +#else + int separateCache = sqlite3GlobalConfig.bCoreMutex>0; +#endif + assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); assert( szExtra < 300 ); - sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache; + sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; pCache = (PCache1 *)sqlite3MallocZero(sz); if( pCache ){ - if( pcache1.separateCache ){ + if( separateCache ){ pGroup = (PGroup*)&pCache[1]; pGroup->mxPinned = 10; }else{ pGroup = &pcache1.grp; } - if( pGroup->lru.isAnchor==0 ){ - pGroup->lru.isAnchor = 1; - pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru; - } pCache->pGroup = pGroup; pCache->szPage = szPage; pCache->szExtra = szExtra; - pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1)); pCache->bPurgeable = (bPurgeable ? 1 : 0); - pcache1EnterMutex(pGroup); - pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; + pcache1EnterMutex(pGroup); pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - } - pcache1LeaveMutex(pGroup); - if( pCache->nHash==0 ){ - pcache1Destroy((sqlite3_pcache*)pCache); - pCache = 0; + pcache1LeaveMutex(pGroup); } } return (sqlite3_pcache *)pCache; @@ -42299,7 +38798,7 @@ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pCache->nMax = nMax; pCache->n90pct = pCache->nMax*9/10; - pcache1EnforceMaxPage(pCache); + pcache1EnforceMaxPage(pGroup); pcache1LeaveMutex(pGroup); } } @@ -42317,7 +38816,7 @@ static void pcache1Shrink(sqlite3_pcache *p){ pcache1EnterMutex(pGroup); savedMaxPage = pGroup->nMaxPage; pGroup->nMaxPage = 0; - pcache1EnforceMaxPage(pCache); + pcache1EnforceMaxPage(pGroup); pGroup->nMaxPage = savedMaxPage; pcache1LeaveMutex(pGroup); } @@ -42335,84 +38834,6 @@ static int pcache1Pagecount(sqlite3_pcache *p){ return n; } - -/* -** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described -** in the header of the pcache1Fetch() procedure. -** -** This steps are broken out into a separate procedure because they are -** usually not needed, and by avoiding the stack initialization required -** for these steps, the main pcache1Fetch() procedure can run faster. -*/ -static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( - PCache1 *pCache, - unsigned int iKey, - int createFlag -){ - unsigned int nPinned; - PGroup *pGroup = pCache->pGroup; - PgHdr1 *pPage = 0; - - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ - assert( pCache->nPage >= pCache->nRecyclable ); - nPinned = pCache->nPage - pCache->nRecyclable; - assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); - assert( pCache->n90pct == pCache->nMax*9/10 ); - if( createFlag==1 && ( - nPinned>=pGroup->mxPinned - || nPinned>=pCache->n90pct - || (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclablenPage>=pCache->nHash ) pcache1ResizeHash(pCache); - assert( pCache->nHash>0 && pCache->apHash ); - - /* Step 4. Try to recycle a page. */ - if( pCache->bPurgeable - && !pGroup->lru.pLruPrev->isAnchor - && ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache)) - ){ - PCache1 *pOther; - pPage = pGroup->lru.pLruPrev; - assert( pPage->isPinned==0 ); - pcache1RemoveFromHash(pPage, 0); - pcache1PinPage(pPage); - pOther = pPage->pCache; - if( pOther->szAlloc != pCache->szAlloc ){ - pcache1FreePage(pPage); - pPage = 0; - }else{ - pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); - } - } - - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. - */ - if( !pPage ){ - pPage = pcache1AllocPage(pCache, createFlag==1); - } - - if( pPage ){ - unsigned int h = iKey % pCache->nHash; - pCache->nPage++; - pPage->iKey = iKey; - pPage->pNext = pCache->apHash[h]; - pPage->pCache = pCache; - pPage->pLruPrev = 0; - pPage->pLruNext = 0; - pPage->isPinned = 1; - *(void **)pPage->page.pExtra = 0; - pCache->apHash[h] = pPage; - if( iKey>pCache->iMaxKey ){ - pCache->iMaxKey = iKey; - } - } - return pPage; -} - /* ** Implementation of the sqlite3_pcache.xFetch method. ** @@ -42466,80 +38887,124 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( ** proceed to step 5. ** ** 5. Otherwise, allocate and return a new page buffer. -** -** There are two versions of this routine. pcache1FetchWithMutex() is -** the general case. pcache1FetchNoMutex() is a faster implementation for -** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper -** invokes the appropriate routine. */ -static PgHdr1 *pcache1FetchNoMutex( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = 0; - - /* Step 1: Search the hash table for an existing entry. */ - pPage = pCache->apHash[iKey % pCache->nHash]; - while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } - - /* Step 2: If the page was found in the hash table, then return it. - ** If the page was not in the hash table and createFlag is 0, abort. - ** Otherwise (page not in hash and createFlag!=0) continue with - ** subsequent steps to try to create the page. */ - if( pPage ){ - if( !pPage->isPinned ){ - return pcache1PinPage(pPage); - }else{ - return pPage; - } - }else if( createFlag ){ - /* Steps 3, 4, and 5 implemented by this subroutine */ - return pcache1FetchStage2(pCache, iKey, createFlag); - }else{ - return 0; - } -} -#if PCACHE1_MIGHT_USE_GROUP_MUTEX -static PgHdr1 *pcache1FetchWithMutex( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage; - - pcache1EnterMutex(pCache->pGroup); - pPage = pcache1FetchNoMutex(p, iKey, createFlag); - assert( pPage==0 || pCache->iMaxKey>=iKey ); - pcache1LeaveMutex(pCache->pGroup); - return pPage; -} -#endif static sqlite3_pcache_page *pcache1Fetch( sqlite3_pcache *p, unsigned int iKey, int createFlag ){ -#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG) + unsigned int nPinned; PCache1 *pCache = (PCache1 *)p; -#endif + PGroup *pGroup; + PgHdr1 *pPage = 0; assert( offsetof(PgHdr1,page)==0 ); assert( pCache->bPurgeable || createFlag!=1 ); assert( pCache->bPurgeable || pCache->nMin==0 ); assert( pCache->bPurgeable==0 || pCache->nMin==10 ); assert( pCache->nMin==0 || pCache->bPurgeable ); - assert( pCache->nHash>0 ); -#if PCACHE1_MIGHT_USE_GROUP_MUTEX - if( pCache->pGroup->mutex ){ - return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag); - }else -#endif - { - return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag); + pcache1EnterMutex(pGroup = pCache->pGroup); + + /* Step 1: Search the hash table for an existing entry. */ + if( pCache->nHash>0 ){ + unsigned int h = iKey % pCache->nHash; + for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext); } + + /* Step 2: Abort if no existing page is found and createFlag is 0 */ + if( pPage ){ + if( !pPage->isPinned ) pcache1PinPage(pPage); + goto fetch_out; + } + if( createFlag==0 ){ + goto fetch_out; + } + + /* The pGroup local variable will normally be initialized by the + ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, + ** then pcache1EnterMutex() is a no-op, so we have to initialize the + ** local variable here. Delaying the initialization of pGroup is an + ** optimization: The common case is to exit the module before reaching + ** this point. + */ +#ifdef SQLITE_MUTEX_OMIT + pGroup = pCache->pGroup; +#endif + + /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ + assert( pCache->nPage >= pCache->nRecyclable ); + nPinned = pCache->nPage - pCache->nRecyclable; + assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); + assert( pCache->n90pct == pCache->nMax*9/10 ); + if( createFlag==1 && ( + nPinned>=pGroup->mxPinned + || nPinned>=pCache->n90pct + || pcache1UnderMemoryPressure(pCache) + )){ + goto fetch_out; + } + + if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){ + goto fetch_out; + } + assert( pCache->nHash>0 && pCache->apHash ); + + /* Step 4. Try to recycle a page. */ + if( pCache->bPurgeable && pGroup->pLruTail && ( + (pCache->nPage+1>=pCache->nMax) + || pGroup->nCurrentPage>=pGroup->nMaxPage + || pcache1UnderMemoryPressure(pCache) + )){ + PCache1 *pOther; + pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); + pcache1RemoveFromHash(pPage); + pcache1PinPage(pPage); + pOther = pPage->pCache; + + /* We want to verify that szPage and szExtra are the same for pOther + ** and pCache. Assert that we can verify this by comparing sums. */ + assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); + assert( pCache->szExtra<512 ); + assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); + assert( pOther->szExtra<512 ); + + if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ + pcache1FreePage(pPage); + pPage = 0; + }else{ + pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); + } + } + + /* Step 5. If a usable page buffer has still not been found, + ** attempt to allocate a new one. + */ + if( !pPage ){ + if( createFlag==1 ) sqlite3BeginBenignMalloc(); + pPage = pcache1AllocPage(pCache); + if( createFlag==1 ) sqlite3EndBenignMalloc(); + } + + if( pPage ){ + unsigned int h = iKey % pCache->nHash; + pCache->nPage++; + pPage->iKey = iKey; + pPage->pNext = pCache->apHash[h]; + pPage->pCache = pCache; + pPage->pLruPrev = 0; + pPage->pLruNext = 0; + pPage->isPinned = 1; + *(void **)pPage->page.pExtra = 0; + pCache->apHash[h] = pPage; + } + +fetch_out: + if( pPage && iKey>pCache->iMaxKey ){ + pCache->iMaxKey = iKey; + } + pcache1LeaveMutex(pGroup); + return (sqlite3_pcache_page*)pPage; } @@ -42564,16 +39029,22 @@ static void pcache1Unpin( ** part of the PGroup LRU list. */ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); + assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); assert( pPage->isPinned==1 ); if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ - pcache1RemoveFromHash(pPage, 1); + pcache1RemoveFromHash(pPage); + pcache1FreePage(pPage); }else{ /* Add the page to the PGroup LRU list. */ - PgHdr1 **ppFirst = &pGroup->lru.pLruNext; - pPage->pLruPrev = &pGroup->lru; - (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; - *ppFirst = pPage; + if( pGroup->pLruHead ){ + pGroup->pLruHead->pLruPrev = pPage; + pPage->pLruNext = pGroup->pLruHead; + pGroup->pLruHead = pPage; + }else{ + pGroup->pLruTail = pPage; + pGroup->pLruHead = pPage; + } pCache->nRecyclable++; pPage->isPinned = 0; } @@ -42650,9 +39121,8 @@ static void pcache1Destroy(sqlite3_pcache *p){ assert( pGroup->nMinPage >= pCache->nMin ); pGroup->nMinPage -= pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1EnforceMaxPage(pCache); + pcache1EnforceMaxPage(pGroup); pcache1LeaveMutex(pGroup); - sqlite3_free(pCache->pBulk); sqlite3_free(pCache->apHash); sqlite3_free(pCache); } @@ -42681,19 +39151,6 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){ sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); } -/* -** Return the size of the header on each page of this PCACHE implementation. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } - -/* -** Return the global mutex used by this PCACHE implementation. The -** sqlite3_status() routine needs access to this mutex. -*/ -SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){ - return pcache1.mutex; -} - #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory @@ -42708,20 +39165,18 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); assert( sqlite3_mutex_notheld(pcache1.mutex) ); - if( sqlite3GlobalConfig.nPage==0 ){ + if( pcache1.pStart==0 ){ PgHdr1 *p; pcache1EnterMutex(&pcache1.grp); - while( (nReq<0 || nFreeisAnchor==0 - ){ + while( (nReq<0 || nFreepage.pBuf); #ifdef SQLITE_PCACHE_SEPARATE_HEADER nFree += sqlite3MemSize(p); #endif assert( p->isPinned==0 ); pcache1PinPage(p); - pcache1RemoveFromHash(p, 1); + pcache1RemoveFromHash(p); + pcache1FreePage(p); } pcache1LeaveMutex(&pcache1.grp); } @@ -42742,7 +39197,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ){ PgHdr1 *p; int nRecyclable = 0; - for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ + for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ assert( p->isPinned==0 ); nRecyclable++; } @@ -42807,7 +39262,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** No INSERTs may occurs after a SMALLEST. An assertion will fail if ** that is attempted. ** -** The cost of an INSERT is roughly constant. (Sometimes new memory +** The cost of an INSERT is roughly constant. (Sometime new memory ** has to be allocated on an INSERT.) The cost of a TEST with a new ** batch number is O(NlogN) where N is the number of elements in the RowSet. ** The cost of a TEST using the same batch number is O(logN). The cost @@ -42817,7 +39272,6 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** There is an added cost of O(N) when switching between TEST and ** SMALLEST primitives. */ -/* #include "sqliteInt.h" */ /* @@ -43200,8 +39654,8 @@ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ ** Check to see if element iRowid was inserted into the rowset as ** part of any insert batch prior to iBatch. Return 1 or 0. ** -** If this is the first test of a new batch and if there exist entries -** on pRowSet->pEntry, then sort those entries into the forest at +** If this is the first test of a new batch and if there exist entires +** on pRowSet->pEntry, then sort those entires into the forest at ** pRowSet->pForest so that they can be tested. */ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){ @@ -43287,7 +39741,6 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 ** another is writing. */ #ifndef SQLITE_OMIT_DISKIO -/* #include "sqliteInt.h" */ /************** Include wal.h in the middle of pager.c ***********************/ /************** Begin file wal.h *********************************************/ /* @@ -43309,7 +39762,6 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 #ifndef _WAL_H_ #define _WAL_H_ -/* #include "sqliteInt.h" */ /* Additional values that can be added to the sync_flags argument of ** sqlite3WalFrames(): @@ -43336,7 +39788,6 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 # define sqlite3WalHeapMemory(z) 0 # define sqlite3WalFramesize(z) 0 # define sqlite3WalFindFrame(x,y,z) 0 -# define sqlite3WalFile(x) 0 #else #define WAL_SAVEPOINT_NDATA 4 @@ -43419,11 +39870,6 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); */ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); -#ifdef SQLITE_ENABLE_SNAPSHOT -SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); -SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); -#endif - #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content ** stored in each frame (i.e. the db page-size when the WAL was created). @@ -43431,9 +39877,6 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapsho SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); #endif -/* Return the sqlite3_file object for the WAL file */ -SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal); - #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* _WAL_H_ */ @@ -43494,12 +39937,12 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal); ** Definition: Two databases (or the same database at two points it time) ** are said to be "logically equivalent" if they give the same answer to ** all queries. Note in particular the content of freelist leaf -** pages can be changed arbitrarily without affecting the logical equivalence +** pages can be changed arbitarily without effecting the logical equivalence ** of the database. ** ** (7) At any time, if any subset, including the empty set and the total set, ** of the unsynced changes to a rollback journal are removed and the -** journal is rolled back, the resulting database file will be logically +** journal is rolled back, the resulting database file will be logical ** equivalent to the database file at the beginning of the transaction. ** ** (8) When a transaction is rolled back, the xTruncate method of the VFS @@ -43796,7 +40239,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ ** ** The exception is when the database file is unlocked as the pager moves ** from ERROR to OPEN state. At this point there may be a hot-journal file -** in the file-system that needs to be rolled back (as part of an OPEN->SHARED +** in the file-system that needs to be rolled back (as part of a OPEN->SHARED ** transition, by the same pager or any other). If the call to xUnlock() ** fails at this point and the pager is left holding an EXCLUSIVE lock, this ** can confuse the call to xCheckReservedLock() call made later as part @@ -43874,12 +40317,12 @@ struct PagerSavepoint { /* ** Bits of the Pager.doNotSpill flag. See further description below. */ -#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */ -#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */ -#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */ +#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */ +#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */ +#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */ /* -** An open page cache is an instance of struct Pager. A description of +** A open page cache is an instance of struct Pager. A description of ** some of the more important member variables follows: ** ** eState @@ -43958,11 +40401,11 @@ struct PagerSavepoint { ** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF ** case is a user preference. ** -** If the SPILLFLAG_NOSYNC bit is set, writing to the database from -** pagerStress() is permitted, but syncing the journal file is not. -** This flag is set by sqlite3PagerWrite() when the file-system sector-size -** is larger than the database page-size in order to prevent a journal sync -** from happening in between the journalling of two pages on the same sector. +** If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress() +** is permitted, but syncing the journal file is not. This flag is set +** by sqlite3PagerWrite() when the file-system sector-size is larger than +** the database page-size in order to prevent a journal sync from happening +** in between the journalling of two pages on the same sector. ** ** subjInMemory ** @@ -44051,7 +40494,7 @@ struct Pager { /************************************************************************** ** The following block contains those class members that change during - ** routine operation. Class members not in this block are either fixed + ** routine opertion. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a ** significant mode change (such as changing the page_size, locking_mode, ** or the journal_mode). From another view, these class members describe @@ -44064,8 +40507,6 @@ struct Pager { u8 setMaster; /* True if a m-j name has been written to jrnl */ u8 doNotSpill; /* Do not spill the cache when non-zero */ u8 subjInMemory; /* True to use in-memory sub-journals */ - u8 bUseFetch; /* True to use xFetch() */ - u8 hasHeldSharedLock; /* True if a shared lock has ever been held */ Pgno dbSize; /* Number of pages in the database */ Pgno dbOrigSize; /* dbSize before the current transaction */ Pgno dbFileSize; /* Number of pages in the database file */ @@ -44083,9 +40524,9 @@ struct Pager { sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ PagerSavepoint *aSavepoint; /* Array of active savepoints */ int nSavepoint; /* Number of elements in aSavepoint[] */ - u32 iDataVersion; /* Changes whenever database content changes */ char dbFileVers[16]; /* Changes whenever database file changes */ + u8 bUseFetch; /* True to use xFetch() */ int nMmapOut; /* Number of mmap pages currently outstanding */ sqlite3_int64 szMmap; /* Desired maximum mmap size */ PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ @@ -44226,7 +40667,7 @@ static const unsigned char aJournalMagic[] = { ** ** if( pPager->jfd->pMethods ){ ... */ -#define isOpen(pFd) ((pFd)->pMethods!=0) +#define isOpen(pFd) ((pFd)->pMethods) /* ** Return true if this pager uses a write-ahead log instead of the usual @@ -44449,21 +40890,19 @@ static int subjRequiresPage(PgHdr *pPg){ int i; for(i=0; inSavepoint; i++){ p = &pPager->aSavepoint[i]; - if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){ + if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ return 1; } } return 0; } -#ifdef SQLITE_DEBUG /* ** Return true if the page is already in the journal file. */ static int pageInJournal(Pager *pPager, PgHdr *pPg){ return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno); } -#endif /* ** Read a 32-bit integer from the given file descriptor. Store the integer @@ -45075,8 +41514,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4))) || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster))) || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum))) - || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, - iHdrOff+4+nMaster+8))) + || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8))) ){ return rc; } @@ -45101,20 +41539,26 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ } /* -** Discard the entire contents of the in-memory page-cache. +** Find a page in the hash table given its page number. Return +** a pointer to the page or NULL if the requested page is not +** already in memory. */ -static void pager_reset(Pager *pPager){ - pPager->iDataVersion++; - sqlite3BackupRestart(pPager->pBackup); - sqlite3PcacheClear(pPager->pPCache); +static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ + PgHdr *p = 0; /* Return value */ + + /* It is not possible for a call to PcacheFetch() with createFlag==0 to + ** fail, since no attempt to allocate dynamic memory will be made. + */ + (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); + return p; } /* -** Return the pPager->iDataVersion value +** Discard the entire contents of the in-memory page-cache. */ -SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ - assert( pPager->eState>PAGER_OPEN ); - return pPager->iDataVersion; +static void pager_reset(Pager *pPager){ + sqlite3BackupRestart(pPager->pBackup); + sqlite3PcacheClear(pPager->pPCache); } /* @@ -45373,14 +41817,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ rc = SQLITE_OK; }else{ rc = sqlite3OsTruncate(pPager->jfd, 0); - if( rc==SQLITE_OK && pPager->fullSync ){ - /* Make sure the new file size is written into the inode right away. - ** Otherwise the journal might resurrect following a power loss and - ** cause the last transaction to roll back. See - ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773 - */ - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); - } } pPager->journalOff = 0; }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST @@ -45409,7 +41845,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ - PgHdr *p = sqlite3PagerLookup(pPager, 1); + PgHdr *p = pager_lookup(pPager, 1); if( p ){ p->pageHash = 0; sqlite3PagerUnrefNotNull(p); @@ -45534,20 +41970,6 @@ static void pagerReportSize(Pager *pPager){ # define pagerReportSize(X) /* No-op if we do not support a codec */ #endif -#ifdef SQLITE_HAS_CODEC -/* -** Make sure the number of reserved bits is the same in the destination -** pager as it is in the source. This comes up when a VACUUM changes the -** number of reserved bits to the "optimal" amount. -*/ -SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){ - if( pDest->nReserve!=pSrc->nReserve ){ - pDest->nReserve = pSrc->nReserve; - pagerReportSize(pDest); - } -} -#endif - /* ** Read a single page from either the journal file (if isMainJrnl==1) or ** from the sub-journal (if isMainJrnl==0) and playback that page. @@ -45650,7 +42072,7 @@ static int pager_playback_one_page( } } - /* If this page has already been played back before during the current + /* If this page has already been played by before during the current ** rollback, then don't bother to play it back again. */ if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ @@ -45702,7 +42124,7 @@ static int pager_playback_one_page( if( pagerUseWal(pPager) ){ pPg = 0; }else{ - pPg = sqlite3PagerLookup(pPager, pgno); + pPg = pager_lookup(pPager, pgno); } assert( pPg || !MEMDB ); assert( pPager->eState!=PAGER_OPEN || pPg==0 ); @@ -45751,7 +42173,7 @@ static int pager_playback_one_page( assert( isSavepnt ); assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 ); pPager->doNotSpill |= SPILLFLAG_ROLLBACK; - rc = sqlite3PagerGet(pPager, pgno, &pPg, 1); + rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1); assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; if( rc!=SQLITE_OK ) return rc; @@ -45882,7 +42304,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){ rc = sqlite3OsFileSize(pMaster, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; nMasterPtr = pVfs->mxPathname+1; - zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1); + zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1); if( !zMasterJournal ){ rc = SQLITE_NOMEM; goto delmaster_out; @@ -45951,7 +42373,7 @@ delmaster_out: ** If the file on disk is currently larger than nPage pages, then use the VFS ** xTruncate() method to truncate it. ** -** Or, it might be the case that the file on disk is smaller than +** Or, it might might be the case that the file on disk is smaller than ** nPage pages. Some operating system implementations can get confused if ** you try to truncate a file to some size that is larger than it ** currently is, so detect this case and write a single zero byte to @@ -46010,7 +42432,7 @@ SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){ /* ** Set the value of the Pager.sectorSize variable for the given ** pager based on the value returned by the xSectorSize method -** of the open database file. The sector size will be used +** of the open database file. The sector size will be used used ** to determine the size and alignment of journal header and ** master journal pointers within created journal files. ** @@ -46345,7 +42767,7 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){ ** ** For an encrypted database, the situation is more complex: bytes ** 24..39 of the database are white noise. But the probability of - ** white noise equaling 16 bytes of 0xff is vanishingly small so + ** white noising equaling 16 bytes of 0xff is vanishingly small so ** we should still be ok. */ memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers)); @@ -46479,7 +42901,9 @@ static int pagerWalFrames( ){ int rc; /* Return code */ int nList; /* Number of pages in pList */ +#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) PgHdr *p; /* For looping over pages */ +#endif assert( pPager->pWal ); assert( pList ); @@ -46496,6 +42920,7 @@ static int pagerWalFrames( ** any pages with page numbers greater than nTruncate into the WAL file. ** They will never be read by any client. So remove them from the pDirty ** list here. */ + PgHdr *p; PgHdr **ppNext = &pList; nList = 0; for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ @@ -46515,6 +42940,7 @@ static int pagerWalFrames( pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags ); if( rc==SQLITE_OK && pPager->pBackup ){ + PgHdr *p; for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); } @@ -46584,10 +43010,11 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ assert( pPager->eLock>=SHARED_LOCK ); nPage = sqlite3WalDbsize(pPager->pWal); - /* If the number of pages in the database is not available from the - ** WAL sub-system, determine the page counte based on the size of - ** the database file. If the size of the database file is not an - ** integer multiple of the page-size, round up the result. + /* If the database size was not available from the WAL sub-system, + ** determine it based on the size of the database file. If the size + ** of the database file is not an integer multiple of the page-size, + ** round down to the nearest page. Except, any file larger than 0 + ** bytes in size is considered to contain at least one page. */ if( nPage==0 ){ i64 n = 0; /* Size of db file in bytes */ @@ -46810,21 +43237,12 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ } /* -** Change the maximum number of in-memory pages that are allowed -** before attempting to recycle clean and unused pages. +** Change the maximum number of in-memory pages that are allowed. */ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); } -/* -** Change the maximum number of in-memory pages that are allowed -** before attempting to spill pages to journal. -*/ -SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){ - return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage); -} - /* ** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. */ @@ -47076,15 +43494,11 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR if( rc==SQLITE_OK ){ pager_reset(pPager); - rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); - } - if( rc==SQLITE_OK ){ - sqlite3PageFree(pPager->pTmpSpace); - pPager->pTmpSpace = pNew; pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); pPager->pageSize = pageSize; - }else{ - sqlite3PageFree(pNew); + sqlite3PageFree(pPager->pTmpSpace); + pPager->pTmpSpace = pNew; + sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); } } @@ -47218,7 +43632,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ int rc; /* Return code */ /* Check that this is either a no-op (because the requested lock is - ** already held), or one of the transitions that the busy-handler + ** already held, or one of the transistions that the busy-handler ** may be invoked during, according to the comment above ** sqlite3PagerSetBusyhandler(). */ @@ -47337,7 +43751,7 @@ static int pagerAcquireMapPage( PgHdr **ppPage /* OUT: Acquired page object */ ){ PgHdr *p; /* Memory mapped page to return */ - + if( pPager->pMmapFreelist ){ *ppPage = p = pPager->pMmapFreelist; pPager->pMmapFreelist = p->pDirty; @@ -47761,6 +44175,8 @@ static int openSubJournal(Pager *pPager){ /* ** Append a record of the current state of page pPg to the sub-journal. +** It is the callers responsibility to use subjRequiresPage() to check +** that it is really required before calling this function. ** ** If successful, set the bit corresponding to pPg->pgno in the bitvecs ** for all open savepoints before returning. @@ -47807,13 +44223,6 @@ static int subjournalPage(PgHdr *pPg){ } return rc; } -static int subjournalPageIfRequired(PgHdr *pPg){ - if( subjRequiresPage(pPg) ){ - return subjournalPage(pPg); - }else{ - return SQLITE_OK; - } -} /* ** This function is called by the pcache layer when it has reached some @@ -47851,8 +44260,8 @@ static int pagerStress(void *p, PgHdr *pPg){ ** a rollback or by user request, respectively. ** ** Spilling is also prohibited when in an error state since that could - ** lead to database corruption. In the current implementation it - ** is impossible for sqlite3PcacheFetch() to be called with createFlag==3 + ** lead to database corruption. In the current implementaton it + ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1 ** while in the error state, hence it is impossible for this routine to ** be called in the error state. Nevertheless, we include a NEVER() ** test for the error state as a safeguard against future changes. @@ -47871,7 +44280,9 @@ static int pagerStress(void *p, PgHdr *pPg){ pPg->pDirty = 0; if( pagerUseWal(pPager) ){ /* Write a single frame for this page to the log. */ - rc = subjournalPageIfRequired(pPg); + if( subjRequiresPage(pPg) ){ + rc = subjournalPage(pPg); + } if( rc==SQLITE_OK ){ rc = pagerWalFrames(pPager, pPg, 0, 0); } @@ -47884,6 +44295,39 @@ static int pagerStress(void *p, PgHdr *pPg){ rc = syncJournal(pPager, 1); } + /* If the page number of this page is larger than the current size of + ** the database image, it may need to be written to the sub-journal. + ** This is because the call to pager_write_pagelist() below will not + ** actually write data to the file in this case. + ** + ** Consider the following sequence of events: + ** + ** BEGIN; + ** + ** + ** SAVEPOINT sp; + ** + ** pagerStress(page X) + ** ROLLBACK TO sp; + ** + ** If (X>Y), then when pagerStress is called page X will not be written + ** out to the database file, but will be dropped from the cache. Then, + ** following the "ROLLBACK TO sp" statement, reading page X will read + ** data from the database file. This will be the copy of page X as it + ** was when the transaction started, not as it was when "SAVEPOINT sp" + ** was executed. + ** + ** The solution is to write the current data for page X into the + ** sub-journal file now (if it is not already there), so that it will + ** be restored to its current value when the "ROLLBACK TO sp" is + ** executed. + */ + if( NEVER( + rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg) + ) ){ + rc = subjournalPage(pPg); + } + /* Write the contents of the page out to the database file. */ if( rc==SQLITE_OK ){ assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); @@ -47900,25 +44344,6 @@ static int pagerStress(void *p, PgHdr *pPg){ return pager_error(pPager, rc); } -/* -** Flush all unreferenced dirty pages to disk. -*/ -SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){ - int rc = pPager->errCode; - if( !MEMDB ){ - PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); - assert( assert_pager_state(pPager) ); - while( rc==SQLITE_OK && pList ){ - PgHdr *pNext = pList->pDirty; - if( pList->nRef==0 ){ - rc = pagerStress((void*)pPager, pList); - } - pList = pNext; - } - } - - return rc; -} /* ** Allocate and initialize a new Pager object and put a pointer to it @@ -48158,7 +44583,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( act_like_temp_file: tempFile = 1; pPager->eState = PAGER_READER; /* Pretend we already have a lock */ - pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE mode */ + pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */ pPager->noLock = 1; /* Do no locking */ readOnly = (vfsFlags&SQLITE_OPEN_READONLY); } @@ -48172,23 +44597,22 @@ act_like_temp_file: testcase( rc!=SQLITE_OK ); } - /* Initialize the PCache object. */ - if( rc==SQLITE_OK ){ - assert( nExtra<1000 ); - nExtra = ROUND8(nExtra); - rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, - !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); - } - - /* If an error occurred above, free the Pager structure and close the file. + /* If an error occurred in either of the blocks above, free the + ** Pager structure and close the file. */ if( rc!=SQLITE_OK ){ + assert( !pPager->pTmpSpace ); sqlite3OsClose(pPager->fd); - sqlite3PageFree(pPager->pTmpSpace); sqlite3_free(pPager); return rc; } + /* Initialize the PCache object. */ + assert( nExtra<1000 ); + nExtra = ROUND8(nExtra); + sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, + !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); + PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename)); IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) @@ -48375,7 +44799,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){ *pExists = (first!=0); }else if( rc==SQLITE_CANTOPEN ){ /* If we cannot open the rollback journal file in order to see if - ** it has a zero header, that might be due to an I/O error, or + ** its has a zero header, that might be due to an I/O error, or ** it might be due to the race condition described above and in ** ticket #3883. Either way, assume that the journal is hot. ** This might be a false positive. But if it is, then the @@ -48396,7 +44820,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){ /* ** This function is called to obtain a shared lock on the database file. -** It is illegal to call sqlite3PagerGet() until after this function +** It is illegal to call sqlite3PagerAcquire() until after this function ** has been successfully called. If a shared-lock is already held when ** this function is called, it is a no-op. ** @@ -48557,14 +44981,18 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ ); } - if( !pPager->tempFile && pPager->hasHeldSharedLock ){ - /* The shared-lock has just been acquired then check to - ** see if the database has been modified. If the database has changed, - ** flush the cache. The hasHeldSharedLock flag prevents this from - ** occurring on the very first access to a file, in order to save a - ** single unnecessary sqlite3OsRead() call at the start-up. + if( !pPager->tempFile && ( + pPager->pBackup + || sqlite3PcachePagecount(pPager->pPCache)>0 + || USEFETCH(pPager) + )){ + /* The shared-lock has just been acquired on the database file + ** and there are already pages in the cache (from a previous + ** read or write transaction). Check to see if the database + ** has been modified. If the database has changed, flush the + ** cache. ** - ** Database changes are detected by looking at 15 bytes beginning + ** Database changes is detected by looking at 15 bytes beginning ** at offset 24 into the file. The first 4 of these 16 bytes are ** a 32-bit counter that is incremented with each change. The ** other bytes change randomly with each file change when @@ -48630,7 +45058,6 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ assert( pPager->eState==PAGER_OPEN ); }else{ pPager->eState = PAGER_READER; - pPager->hasHeldSharedLock = 1; } return rc; } @@ -48699,7 +45126,7 @@ static void pagerUnlockIfUnused(Pager *pPager){ ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ -SQLITE_PRIVATE int sqlite3PagerGet( +SQLITE_PRIVATE int sqlite3PagerAcquire( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ @@ -48714,31 +45141,27 @@ SQLITE_PRIVATE int sqlite3PagerGet( ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY ** flag was specified by the caller. And so long as the db is not a ** temporary or in-memory database. */ - const int bMmapOk = (pgno>1 && USEFETCH(pPager) + const int bMmapOk = (pgno!=1 && USEFETCH(pPager) && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) #ifdef SQLITE_HAS_CODEC && pPager->xCodec==0 #endif ); - /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here - ** allows the compiler optimizer to reuse the results of the "pgno>1" - ** test in the previous statement, and avoid testing pgno==0 in the - ** common case where pgno is large. */ - if( pgno<=1 && pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); assert( noContent==0 || bMmapOk==0 ); - assert( pPager->hasHeldSharedLock==1 ); + if( pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } /* If the pager is in the error state, return an error immediately. ** Otherwise, request the page from the PCache layer. */ if( pPager->errCode!=SQLITE_OK ){ rc = pPager->errCode; }else{ + if( bMmapOk && pagerUseWal(pPager) ){ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); if( rc!=SQLITE_OK ) goto pager_acquire_err; @@ -48753,7 +45176,7 @@ SQLITE_PRIVATE int sqlite3PagerGet( if( rc==SQLITE_OK && pData ){ if( pPager->eState>PAGER_READER ){ - pPg = sqlite3PagerLookup(pPager, pgno); + (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); } if( pPg==0 ){ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); @@ -48771,21 +45194,7 @@ SQLITE_PRIVATE int sqlite3PagerGet( } } - { - sqlite3_pcache_page *pBase; - pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); - if( pBase==0 ){ - rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - if( pBase==0 ){ - pPg = *ppPage = 0; - rc = SQLITE_NOMEM; - goto pager_acquire_err; - } - } - pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); - assert( pPg!=0 ); - } + rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); } if( rc!=SQLITE_OK ){ @@ -48795,11 +45204,10 @@ SQLITE_PRIVATE int sqlite3PagerGet( pPg = 0; goto pager_acquire_err; } - assert( pPg==(*ppPage) ); - assert( pPg->pgno==pgno ); - assert( pPg->pPager==pPager || pPg->pPager==0 ); + assert( (*ppPage)->pgno==pgno ); + assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 ); - if( pPg->pPager && !noContent ){ + if( (*ppPage)->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); @@ -48810,6 +45218,7 @@ SQLITE_PRIVATE int sqlite3PagerGet( /* The pager cache has created a new page. Its content needs to ** be initialized. */ + pPg = *ppPage; pPg->pPager = pPager; /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page @@ -48882,14 +45291,13 @@ pager_acquire_err: ** has ever happened. */ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ - sqlite3_pcache_page *pPage; + PgHdr *pPg = 0; assert( pPager!=0 ); assert( pgno!=0 ); assert( pPager->pPCache!=0 ); - pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); - assert( pPage==0 || pPager->hasHeldSharedLock ); - if( pPage==0 ) return 0; - return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); + assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR ); + sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); + return pPg; } /* @@ -49045,7 +45453,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory if( rc!=SQLITE_OK ){ return rc; } - (void)sqlite3WalExclusiveMode(pPager->pWal, 1); + sqlite3WalExclusiveMode(pPager->pWal, 1); } /* Grab the write lock on the log file. If successful, upgrade to @@ -49092,59 +45500,6 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory return rc; } -/* -** Write page pPg onto the end of the rollback journal. -*/ -static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - int rc; - u32 cksum; - char *pData2; - i64 iOff = pPager->journalOff; - - /* We should never write to the journal file the page that - ** contains the database locks. The following assert verifies - ** that we do not. */ - assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); - - assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); - cksum = pager_cksum(pPager, (u8*)pData2); - - /* Even if an IO or diskfull error occurs while journalling the - ** page in the block above, set the need-sync flag for the page. - ** Otherwise, when the transaction is rolled back, the logic in - ** playback_one_page() will think that the page needs to be restored - ** in the database file. And if an IO error occurs while doing so, - ** then corruption may follow. - */ - pPg->flags |= PGHDR_NEED_SYNC; - - rc = write32bits(pPager->jfd, iOff, pPg->pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); - if( rc!=SQLITE_OK ) return rc; - rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); - if( rc!=SQLITE_OK ) return rc; - - IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, - pPager->journalOff, pPager->pageSize)); - PAGER_INCR(sqlite3_pager_writej_count); - PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); - - pPager->journalOff += 8 + pPager->pageSize; - pPager->nRec++; - assert( pPager->pInJournal!=0 ); - rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); - testcase( rc==SQLITE_NOMEM ); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - rc |= addToSavepointBitvecs(pPager, pPg->pgno); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - return rc; -} - /* ** Mark a single data page as writeable. The page is written into the ** main journal or sub-journal as required. If the page is written into @@ -49155,6 +45510,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ static int pager_write(PgHdr *pPg){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; + int inJournal; /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. @@ -49167,6 +45523,7 @@ static int pager_write(PgHdr *pPg){ assert( assert_pager_state(pPager) ); assert( pPager->errCode==0 ); assert( pPager->readOnly==0 ); + CHECK_PAGE(pPg); /* The journal file needs to be opened. Higher level routines have already @@ -49185,145 +45542,97 @@ static int pager_write(PgHdr *pPg){ assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); assert( assert_pager_state(pPager) ); - /* Mark the page that is about to be modified as dirty. */ - sqlite3PcacheMakeDirty(pPg); - - /* If a rollback journal is in use, them make sure the page that is about - ** to change is in the rollback journal, or if the page is a new page off - ** then end of the file, make sure it is marked as PGHDR_NEED_SYNC. + /* Mark the page as dirty. If the page has already been written + ** to the journal then we can return right away. */ - assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) ); - if( pPager->pInJournal!=0 - && sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0 - ){ - assert( pagerUseWal(pPager)==0 ); - if( pPg->pgno<=pPager->dbOrigSize ){ - rc = pagerAddPageToRollbackJournal(pPg); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - if( pPager->eState!=PAGER_WRITER_DBMOD ){ + sqlite3PcacheMakeDirty(pPg); + inJournal = pageInJournal(pPager, pPg); + if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){ + assert( !pagerUseWal(pPager) ); + }else{ + + /* The transaction journal now exists and we have a RESERVED or an + ** EXCLUSIVE lock on the main database file. Write the current page to + ** the transaction journal if it is not there already. + */ + if( !inJournal && !pagerUseWal(pPager) ){ + assert( pagerUseWal(pPager)==0 ); + if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ + u32 cksum; + char *pData2; + i64 iOff = pPager->journalOff; + + /* We should never write to the journal file the page that + ** contains the database locks. The following assert verifies + ** that we do not. */ + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + + assert( pPager->journalHdr<=pPager->journalOff ); + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + cksum = pager_cksum(pPager, (u8*)pData2); + + /* Even if an IO or diskfull error occurs while journalling the + ** page in the block above, set the need-sync flag for the page. + ** Otherwise, when the transaction is rolled back, the logic in + ** playback_one_page() will think that the page needs to be restored + ** in the database file. And if an IO error occurs while doing so, + ** then corruption may follow. + */ pPg->flags |= PGHDR_NEED_SYNC; + + rc = write32bits(pPager->jfd, iOff, pPg->pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); + if( rc!=SQLITE_OK ) return rc; + rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); + if( rc!=SQLITE_OK ) return rc; + + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, pPager->pageSize)); + PAGER_INCR(sqlite3_pager_writej_count); + PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, + ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); + + pPager->journalOff += 8 + pPager->pageSize; + pPager->nRec++; + assert( pPager->pInJournal!=0 ); + rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); + testcase( rc==SQLITE_NOMEM ); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + rc |= addToSavepointBitvecs(pPager, pPg->pgno); + if( rc!=SQLITE_OK ){ + assert( rc==SQLITE_NOMEM ); + return rc; + } + }else{ + if( pPager->eState!=PAGER_WRITER_DBMOD ){ + pPg->flags |= PGHDR_NEED_SYNC; + } + PAGERTRACE(("APPEND %d page %d needSync=%d\n", + PAGERID(pPager), pPg->pgno, + ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); } - PAGERTRACE(("APPEND %d page %d needSync=%d\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); + } + + /* If the statement journal is open and the page is not in it, + ** then write the current page to the statement journal. Note that + ** the statement journal format differs from the standard journal format + ** in that it omits the checksums and the header. + */ + if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){ + rc = subjournalPage(pPg); } } - /* The PGHDR_DIRTY bit is set above when the page was added to the dirty-list - ** and before writing the page into the rollback journal. Wait until now, - ** after the page has been successfully journalled, before setting the - ** PGHDR_WRITEABLE bit that indicates that the page can be safely modified. + /* Update the database size and return. */ - pPg->flags |= PGHDR_WRITEABLE; - - /* If the statement journal is open and the page is not in it, - ** then write the page into the statement journal. - */ - if( pPager->nSavepoint>0 ){ - rc = subjournalPageIfRequired(pPg); - } - - /* Update the database size and return. */ if( pPager->dbSizepgno ){ pPager->dbSize = pPg->pgno; } return rc; } -/* -** This is a variant of sqlite3PagerWrite() that runs when the sector size -** is larger than the page size. SQLite makes the (reasonable) assumption that -** all bytes of a sector are written together by hardware. Hence, all bytes of -** a sector need to be journalled in case of a power loss in the middle of -** a write. -** -** Usually, the sector size is less than or equal to the page size, in which -** case pages can be individually written. This routine only runs in the -** exceptional case where the page size is smaller than the sector size. -*/ -static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ - int rc = SQLITE_OK; /* Return code */ - Pgno nPageCount; /* Total number of pages in database file */ - Pgno pg1; /* First page of the sector pPg is located on. */ - int nPage = 0; /* Number of pages starting at pg1 to journal */ - int ii; /* Loop counter */ - int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - Pager *pPager = pPg->pPager; /* The pager that owns pPg */ - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - - /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow - ** a journal header to be written between the pages journaled by - ** this function. - */ - assert( !MEMDB ); - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); - pPager->doNotSpill |= SPILLFLAG_NOSYNC; - - /* This trick assumes that both the page-size and sector-size are - ** an integer power of 2. It sets variable pg1 to the identifier - ** of the first page of the sector pPg is located on. - */ - pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; - - nPageCount = pPager->dbSize; - if( pPg->pgno>nPageCount ){ - nPage = (pPg->pgno - pg1)+1; - }else if( (pg1+nPagePerSector-1)>nPageCount ){ - nPage = nPageCount+1-pg1; - }else{ - nPage = nPagePerSector; - } - assert(nPage>0); - assert(pg1<=pPg->pgno); - assert((pg1+nPage)>pPg->pgno); - - for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_MJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage, 0); - if( rc==SQLITE_OK ){ - rc = pager_write(pPage); - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){ - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages - ** starting at pg1, then it needs to be set for all of them. Because - ** writing to any of these nPage pages may damage the others, the - ** journal file must contain sync()ed copies of all of them - ** before any of them can be written out to the database file. - */ - if( rc==SQLITE_OK && needSync ){ - assert( !MEMDB ); - for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnrefNotNull(pPage); - } - } - } - - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); - pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; - return rc; -} - /* ** Mark a data page as writeable. This routine must be called before ** making changes to a page. The caller must check the return value @@ -49338,21 +45647,96 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ ** If an error occurs, SQLITE_NOMEM or an IO error code is returned ** as appropriate. Otherwise, SQLITE_OK. */ -SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ + int rc = SQLITE_OK; + + PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; + assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); + assert( pPager->eState!=PAGER_ERROR ); assert( assert_pager_state(pPager) ); - if( pPager->errCode ){ - return pPager->errCode; - }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ - if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); - return SQLITE_OK; - }else if( pPager->sectorSize > (u32)pPager->pageSize ){ - return pagerWriteLargeSector(pPg); + + if( pPager->sectorSize > (u32)pPager->pageSize ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage = 0; /* Number of pages starting at pg1 to journal */ + int ii; /* Loop counter */ + int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow + ** a journal header to be written between the pages journaled by + ** this function. + */ + assert( !MEMDB ); + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); + pPager->doNotSpill |= SPILLFLAG_NOSYNC; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = pPager->dbSize; + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + + /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( rc==SQLITE_OK && needSync ){ + assert( !MEMDB ); + for(ii=0; iiflags |= PGHDR_NEED_SYNC; + sqlite3PagerUnrefNotNull(pPage); + } + } + } + + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); + pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; }else{ - return pager_write(pPg); + rc = pager_write(pDbPage); } + return rc; } /* @@ -49362,7 +45746,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ */ #ifndef NDEBUG SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ - return pPg->flags & PGHDR_WRITEABLE; + return pPg->flags&PGHDR_DIRTY; } #endif @@ -49386,7 +45770,6 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) pPg->flags |= PGHDR_DONT_WRITE; - pPg->flags &= ~PGHDR_WRITEABLE; pager_set_pagehash(pPg); } } @@ -49445,7 +45828,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ assert( !pPager->tempFile && isOpen(pPager->fd) ); /* Open page 1 of the file for writing. */ - rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0); + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); assert( pPgHdr==0 || rc==SQLITE_OK ); /* If page one was fetched successfully, and this function is not @@ -49523,17 +45906,14 @@ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ ** returned. */ SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ - int rc = pPager->errCode; + int rc = SQLITE_OK; + assert( pPager->eState==PAGER_WRITER_CACHEMOD + || pPager->eState==PAGER_WRITER_DBMOD + || pPager->eState==PAGER_WRITER_LOCKED + ); assert( assert_pager_state(pPager) ); - if( rc==SQLITE_OK ){ - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_WRITER_LOCKED - ); - assert( assert_pager_state(pPager) ); - if( 0==pagerUseWal(pPager) ){ - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); - } + if( 0==pagerUseWal(pPager) ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } return rc; } @@ -49600,7 +45980,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( if( pList==0 ){ /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ - rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0); + rc = sqlite3PagerGet(pPager, 1, &pPageOne); pList = pPageOne; pList->pDirty = 0; } @@ -49772,7 +46152,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); - pPager->iDataVersion++; rc = pager_end_transaction(pPager, pPager->setMaster, 1); return pager_error(pPager, rc); } @@ -49856,14 +46235,12 @@ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){ return pPager->readOnly; } -#ifdef SQLITE_DEBUG /* -** Return the sum of the reference counts for all pages held by pPager. +** Return the number of references to the pager. */ SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){ return sqlite3PcacheRefCount(pPager->pPCache); } -#endif /* ** Return the approximate number of bytes of memory currently @@ -49946,62 +46323,54 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ ** occurs while opening the sub-journal file, then an IO error code is ** returned. Otherwise, SQLITE_OK. */ -static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){ +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ int rc = SQLITE_OK; /* Return code */ int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ - int ii; /* Iterator variable */ - PagerSavepoint *aNew; /* New Pager.aSavepoint array */ assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); - assert( nSavepoint>nCurrent && pPager->useJournal ); - /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM - ** if the allocation fails. Otherwise, zero the new portion in case a - ** malloc failure occurs while populating it in the for(...) loop below. - */ - aNew = (PagerSavepoint *)sqlite3Realloc( - pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint - ); - if( !aNew ){ - return SQLITE_NOMEM; - } - memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); - pPager->aSavepoint = aNew; + if( nSavepoint>nCurrent && pPager->useJournal ){ + int ii; /* Iterator variable */ + PagerSavepoint *aNew; /* New Pager.aSavepoint array */ - /* Populate the PagerSavepoint structures just allocated. */ - for(ii=nCurrent; iidbSize; - if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ - aNew[ii].iOffset = pPager->journalOff; - }else{ - aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); - } - aNew[ii].iSubRec = pPager->nSubRec; - aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); - if( !aNew[ii].pInSavepoint ){ + /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM + ** if the allocation fails. Otherwise, zero the new portion in case a + ** malloc failure occurs while populating it in the for(...) loop below. + */ + aNew = (PagerSavepoint *)sqlite3Realloc( + pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint + ); + if( !aNew ){ return SQLITE_NOMEM; } - if( pagerUseWal(pPager) ){ - sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); + memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); + pPager->aSavepoint = aNew; + + /* Populate the PagerSavepoint structures just allocated. */ + for(ii=nCurrent; iidbSize; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ + aNew[ii].iOffset = pPager->journalOff; + }else{ + aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); + } + aNew[ii].iSubRec = pPager->nSubRec; + aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); + if( !aNew[ii].pInSavepoint ){ + return SQLITE_NOMEM; + } + if( pagerUseWal(pPager) ){ + sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); + } + pPager->nSavepoint = ii+1; } - pPager->nSavepoint = ii+1; + assert( pPager->nSavepoint==nSavepoint ); + assertTruncateConstraint(pPager); } - assert( pPager->nSavepoint==nSavepoint ); - assertTruncateConstraint(pPager); + return rc; } -SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - - if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){ - return pagerOpenSavepoint(pPager, nSavepoint); - }else{ - return SQLITE_OK; - } -} - /* ** This function is called to rollback or release (commit) a savepoint. @@ -50097,7 +46466,7 @@ SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){ /* ** Return the VFS structure for the pager. */ -SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ return pPager->pVfs; } @@ -50110,18 +46479,6 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } -/* -** Return the file handle for the journal file (if it exists). -** This will be either the rollback journal or the WAL file. -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ -#if SQLITE_OMIT_WAL - return pPager->jfd; -#else - return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd; -#endif -} - /* ** Return the full pathname of the journal file. */ @@ -50244,8 +46601,9 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i ** one or more savepoint bitvecs. This is the reason this function ** may return SQLITE_NOMEM. */ - if( (pPg->flags & PGHDR_DIRTY)!=0 - && SQLITE_OK!=(rc = subjournalPageIfRequired(pPg)) + if( pPg->flags&PGHDR_DIRTY + && subjRequiresPage(pPg) + && SQLITE_OK!=(rc = subjournalPage(pPg)) ){ return rc; } @@ -50274,7 +46632,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i ** for the page moved there. */ pPg->flags &= ~PGHDR_NEED_SYNC; - pPgOld = sqlite3PagerLookup(pPager, pgno); + pPgOld = pager_lookup(pPager, pgno); assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); @@ -50317,7 +46675,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i ** the journal file twice, but that is not a problem. */ PgHdr *pPgHdr; - rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); if( rc!=SQLITE_OK ){ if( needSyncPgno<=pPager->dbOrigSize ){ assert( pPager->pTmpSpace!=0 ); @@ -50334,18 +46692,6 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i } #endif -/* -** The page handle passed as the first argument refers to a dirty page -** with a page number other than iNew. This function changes the page's -** page number to iNew and sets the value of the PgHdr.flags field to -** the value passed as the third parameter. -*/ -SQLITE_PRIVATE void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){ - assert( pPg->pgno!=iNew ); - pPg->flags = flags; - sqlite3PcacheMove(pPg, iNew); -} - /* ** Return a pointer to the data for the specified page. */ @@ -50491,8 +46837,6 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ } assert( state==pPager->eState ); } - }else if( eMode==PAGER_JOURNALMODE_OFF ){ - sqlite3OsClose(pPager->jfd); } } @@ -50564,8 +46908,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int rc = SQLITE_OK; if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, eMode, - (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), - pPager->pBusyHandlerArg, + pPager->xBusyHandler, pPager->pBusyHandlerArg, pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); @@ -50731,34 +47074,6 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ return rc; } -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** If this is a WAL database, obtain a snapshot handle for the snapshot -** currently open. Otherwise, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ - int rc = SQLITE_ERROR; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot); - } - return rc; -} - -/* -** If this is a WAL database, store a pointer to pSnapshot. Next time a -** read transaction is opened, attempt to read from the snapshot it -** identifies. If this is not a WAL database, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){ - int rc = SQLITE_OK; - if( pPager->pWal ){ - sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); - }else{ - rc = SQLITE_ERROR; - } - return rc; -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS @@ -50770,12 +47085,11 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSn ** is empty, return 0. */ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ - assert( pPager->eState>=PAGER_READER ); + assert( pPager->eState==PAGER_READER ); return sqlite3WalFramesize(pPager->pWal); } #endif - #endif /* SQLITE_OMIT_DISKIO */ /************** End of pager.c ***********************************************/ @@ -51024,7 +47338,6 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ */ #ifndef SQLITE_OMIT_WAL -/* #include "wal.h" */ /* ** Trace output macros @@ -51054,8 +47367,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; /* ** Indices of various locking bytes. WAL_NREADER is the number -** of available reader locks and should be at least 3. The default -** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5. +** of available reader locks and should be at least 3. */ #define WAL_WRITE_LOCK 0 #define WAL_ALL_BUT_WRITE 1 @@ -51075,10 +47387,7 @@ typedef struct WalCkptInfo WalCkptInfo; ** The following object holds a copy of the wal-index header content. ** ** The actual header in the wal-index consists of two copies of this -** object followed by one instance of the WalCkptInfo object. -** For all versions of SQLite through 3.10.0 and probably beyond, -** the locking bytes (WalCkptInfo.aLock) start at offset 120 and -** the total header size is 136 bytes. +** object. ** ** The szPage value can be any power of 2 between 512 and 32768, inclusive. ** Or it can be 1 to represent a 65536-byte page. The latter case was @@ -51111,16 +47420,6 @@ struct WalIndexHdr { ** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from ** mxFrame back to zero when the WAL is reset. ** -** nBackfillAttempted is the largest value of nBackfill that a checkpoint -** has attempted to achieve. Normally nBackfill==nBackfillAtempted, however -** the nBackfillAttempted is set before any backfilling is done and the -** nBackfill is only set after all backfilling completes. So if a checkpoint -** crashes, nBackfillAttempted might be larger than nBackfill. The -** WalIndexHdr.mxFrame must never be less than nBackfillAttempted. -** -** The aLock[] field is a set of bytes used for locking. These bytes should -** never be read or written. -** ** There is one entry in aReadMark[] for each reader lock. If a reader ** holds read-lock K, then the value in aReadMark[K] is no greater than ** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) @@ -51160,9 +47459,6 @@ struct WalIndexHdr { struct WalCkptInfo { u32 nBackfill; /* Number of WAL frames backfilled into DB */ u32 aReadMark[WAL_NREADER]; /* Reader marks */ - u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */ - u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */ - u32 notUsed0; /* Available for future enhancements */ }; #define READMARK_NOT_USED 0xffffffff @@ -51172,8 +47468,9 @@ struct WalCkptInfo { ** only support mandatory file-locks, we do not read or write data ** from the region of the file on which locks are applied. */ -#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock)) -#define WALINDEX_HDR_SIZE (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo)) +#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo)) +#define WALINDEX_LOCK_RESERVED 16 +#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED) /* Size of header before each frame in wal */ #define WAL_FRAME_HDRSIZE 24 @@ -51226,15 +47523,11 @@ struct Wal { u8 syncHeader; /* Fsync the WAL header if true */ u8 padToSectorBoundary; /* Pad transactions out to the next sector */ WalIndexHdr hdr; /* Wal-index header for current transaction */ - u32 minFrame; /* Ignore wal frames before this one */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ #ifdef SQLITE_DEBUG u8 lockError; /* True if a locking error has occurred */ #endif -#ifdef SQLITE_ENABLE_SNAPSHOT - WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ -#endif }; /* @@ -51324,7 +47617,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ if( pWal->nWiData<=iPage ){ int nByte = sizeof(u32*)*(iPage+1); volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); + apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM; @@ -51376,7 +47669,7 @@ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ ** The argument to this macro must be of type u32. On a little-endian ** architecture, it returns the u32 value that results from interpreting ** the 4 bytes as a big-endian value. On a big-endian architecture, it -** returns the value that would be produced by interpreting the 4 bytes +** returns the value that would be produced by intepreting the 4 bytes ** of the input value as a little-endian integer. */ #define BYTESWAP32(x) ( \ @@ -51450,9 +47743,9 @@ static void walIndexWriteHdr(Wal *pWal){ pWal->hdr.isInit = 1; pWal->hdr.iVersion = WALINDEX_MAX_VERSION; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); - memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); + memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr)); walShmBarrier(pWal); - memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); + memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr)); } /* @@ -51753,13 +48046,13 @@ static void walCleanupHash(Wal *pWal){ ** via the hash table even after the cleanup. */ if( iLimit ){ - int j; /* Loop counter */ + int i; /* Loop counter */ int iKey; /* Hash key */ - for(j=1; j<=iLimit; j++){ - for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){ - if( aHash[iKey]==j ) break; + for(i=1; i<=iLimit; i++){ + for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){ + if( aHash[iKey]==i ) break; } - assert( aHash[iKey]==j ); + assert( aHash[iKey]==i ); } } #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ @@ -51790,7 +48083,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ assert( idx <= HASHTABLE_NSLOT/2 + 1 ); /* If this is the first entry to be added to this hash-table, zero the - ** entire hash table and aPgno[] array before proceeding. + ** entire hash table and aPgno[] array before proceding. */ if( idx==1 ){ int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); @@ -51948,7 +48241,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc64(szFrame); + aFrame = (u8 *)sqlite3_malloc(szFrame); if( !aFrame ){ rc = SQLITE_NOMEM; goto recovery_error; @@ -51999,7 +48292,6 @@ finished: */ pInfo = walCkptInfo(pWal); pInfo->nBackfill = 0; - pInfo->nBackfillAttempted = pWal->hdr.mxFrame; pInfo->aReadMark[0] = 0; for(i=1; iaReadMark[i] = READMARK_NOT_USED; if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame; @@ -52071,11 +48363,7 @@ SQLITE_PRIVATE int sqlite3WalOpen( /* In the amalgamation, the os_unix.c and os_win.c source files come before ** this source file. Verify that the #defines of the locking byte offsets ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. - ** For that matter, if the lock offset ever changes from its initial design - ** value of 120, we need to know that so there is an assert() to check it. */ - assert( 120==WALINDEX_LOCK_OFFSET ); - assert( 136==WALINDEX_HDR_SIZE ); #ifdef WIN_SHM_BASE assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); #endif @@ -52266,7 +48554,7 @@ static void walMergesort( int nMerge = 0; /* Number of elements in list aMerge */ ht_slot *aMerge = 0; /* List to be merged */ int iList; /* Index into input list */ - u32 iSub = 0; /* Index into aSub array */ + int iSub = 0; /* Index into aSub array */ struct Sublist aSub[13]; /* Array of sub-lists */ memset(aSub, 0, sizeof(aSub)); @@ -52277,9 +48565,7 @@ static void walMergesort( nMerge = 1; aMerge = &aList[iList]; for(iSub=0; iList & (1<aList && p->nList<=(1<aList==&aList[iList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); @@ -52290,9 +48576,7 @@ static void walMergesort( for(iSub++; iSubnList<=(1<aList==&aList[nList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); @@ -52315,7 +48599,7 @@ static void walMergesort( ** Free an iterator allocated by walIteratorInit(). */ static void walIteratorFree(WalIterator *p){ - sqlite3_free(p); + sqlite3ScratchFree(p); } /* @@ -52350,7 +48634,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte); + p = (WalIterator *)sqlite3ScratchMalloc(nByte); if( !p ){ return SQLITE_NOMEM; } @@ -52360,7 +48644,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ /* 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( + aTmp = (ht_slot *)sqlite3ScratchMalloc( sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !aTmp ){ @@ -52397,7 +48681,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ p->aSegment[i].aPgno = (u32 *)aPgno; } } - sqlite3_free(aTmp); + sqlite3ScratchFree(aTmp); if( rc!=SQLITE_OK ){ walIteratorFree(p); @@ -52434,39 +48718,6 @@ static int walPagesize(Wal *pWal){ return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); } -/* -** The following is guaranteed when this function is called: -** -** a) the WRITER lock is held, -** b) the entire log file has been checkpointed, and -** c) any existing readers are reading exclusively from the database -** file - there are no readers that may attempt to read a frame from -** the log file. -** -** This function updates the shared-memory structures so that the next -** client to write to the database (which may be this one) does so by -** writing frames into the start of the log file. -** -** The value of parameter salt1 is used as the aSalt[1] value in the -** new wal-index header. It should be passed a pseudo-random value (i.e. -** one obtained from sqlite3_randomness()). -*/ -static void walRestartHdr(Wal *pWal, u32 salt1){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int i; /* Loop counter */ - u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ - pWal->nCkpt++; - pWal->hdr.mxFrame = 0; - sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); - memcpy(&pWal->hdr.aSalt[1], &salt1, 4); - walIndexWriteHdr(pWal); - pInfo->nBackfill = 0; - pInfo->nBackfillAttempted = 0; - pInfo->aReadMark[1] = 0; - for(i=2; iaReadMark[i] = READMARK_NOT_USED; - assert( pInfo->aReadMark[0]==0 ); -} - /* ** Copy as much content as we can from the WAL back into the database file ** in response to an sqlite3_wal_checkpoint() request or the equivalent. @@ -52490,7 +48741,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ ** database file. ** ** This routine uses and updates the nBackfill field of the wal-index header. -** This is the only routine that will increase the value of nBackfill. +** This is the only routine tha will increase the value of nBackfill. ** (A WAL reset or recovery will revert nBackfill to zero, but not increase ** its value.) ** @@ -52501,12 +48752,12 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ static int walCheckpoint( Wal *pWal, /* Wal connection */ int eMode, /* One of PASSIVE, FULL or RESTART */ - int (*xBusy)(void*), /* Function to call when busy */ + int (*xBusyCall)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags for OsSync() (or 0) */ u8 *zBuf /* Temporary buffer to use */ ){ - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ int szPage; /* Database page-size */ WalIterator *pIter = 0; /* Wal iterator context */ u32 iDbpage = 0; /* Next database page to write */ @@ -52515,156 +48766,123 @@ static int walCheckpoint( u32 mxPage; /* Max database page to write */ int i; /* Loop counter */ volatile WalCkptInfo *pInfo; /* The checkpoint status information */ + int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ szPage = walPagesize(pWal); testcase( szPage<=32768 ); testcase( szPage>=65536 ); pInfo = walCkptInfo(pWal); - if( pInfo->nBackfillhdr.mxFrame ){ + if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK; - /* Allocate the iterator */ - rc = walIteratorInit(pWal, &pIter); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pIter ); + /* Allocate the iterator */ + rc = walIteratorInit(pWal, &pIter); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pIter ); - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked - ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; - /* Compute in mxSafeFrame the index of the last frame of the WAL that is - ** safe to write into the database. Frames beyond mxSafeFrame might - ** overwrite database pages that are in use by active readers and thus - ** cannot be backfilled from the WAL. - */ - mxSafeFrame = pWal->hdr.mxFrame; - mxPage = pWal->hdr.nPage; - for(i=1; iaReadMark[i]; - if( mxSafeFrame>y ){ - assert( y<=pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); - if( rc==SQLITE_OK ){ - pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc==SQLITE_BUSY ){ - mxSafeFrame = y; - xBusy = 0; - }else{ - goto walcheckpoint_out; - } - } - } - - if( pInfo->nBackfillnBackfill; - - pInfo->nBackfillAttempted = mxSafeFrame; - - /* Sync the WAL to disk */ - if( sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags); - } - - /* If the database may grow as a result of this checkpoint, hint - ** about the eventual size of the db file to the VFS layer. - */ + /* Compute in mxSafeFrame the index of the last frame of the WAL that is + ** safe to write into the database. Frames beyond mxSafeFrame might + ** overwrite database pages that are in use by active readers and thus + ** cannot be backfilled from the WAL. + */ + mxSafeFrame = pWal->hdr.mxFrame; + mxPage = pWal->hdr.nPage; + for(i=1; iaReadMark[i]; + if( mxSafeFrame>y ){ + assert( y<=pWal->hdr.mxFrame ); + rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ - i64 nReq = ((i64)mxPage * szPage); - rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); - if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); - } + pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + }else if( rc==SQLITE_BUSY ){ + mxSafeFrame = y; + xBusy = 0; + }else{ + goto walcheckpoint_out; } - - - /* Iterate through the contents of the WAL, copying data to the db file */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ - i64 iOffset; - assert( walFramePgno(pWal, iFrame)==iDbpage ); - if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ - continue; - } - iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ - rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - iOffset = (iDbpage-1)*(i64)szPage; - testcase( IS_BIG_INT(iOffset) ); - rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - } - - /* If work was actually accomplished... */ - if( rc==SQLITE_OK ){ - if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ - i64 szDb = pWal->hdr.nPage*(i64)szPage; - testcase( IS_BIG_INT(szDb) ); - rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK && sync_flags ){ - rc = sqlite3OsSync(pWal->pDbFd, sync_flags); - } - } - if( rc==SQLITE_OK ){ - pInfo->nBackfill = mxSafeFrame; - } - } - - /* Release the reader lock held while backfilling */ - walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); - } - - if( rc==SQLITE_BUSY ){ - /* Reset the return code so as not to report a checkpoint failure - ** just because there are active readers. */ - rc = SQLITE_OK; } } - /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the - ** entire wal file has been copied into the database file, then block - ** until all readers have finished using the wal file. This ensures that - ** the next process to write to the database restarts the wal file. + if( pInfo->nBackfillnBackfill; + + /* Sync the WAL to disk */ + if( sync_flags ){ + rc = sqlite3OsSync(pWal->pWalFd, sync_flags); + } + + /* If the database may grow as a result of this checkpoint, hint + ** about the eventual size of the db file to the VFS layer. + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); + } + } + + + /* Iterate through the contents of the WAL, copying data to the db file. */ + while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ + i64 iOffset; + assert( walFramePgno(pWal, iFrame)==iDbpage ); + if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue; + iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; + /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ + rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + iOffset = (iDbpage-1)*(i64)szPage; + testcase( IS_BIG_INT(iOffset) ); + rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); + if( rc!=SQLITE_OK ) break; + } + + /* If work was actually accomplished... */ + if( rc==SQLITE_OK ){ + if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ + i64 szDb = pWal->hdr.nPage*(i64)szPage; + testcase( IS_BIG_INT(szDb) ); + rc = sqlite3OsTruncate(pWal->pDbFd, szDb); + if( rc==SQLITE_OK && sync_flags ){ + rc = sqlite3OsSync(pWal->pDbFd, sync_flags); + } + } + if( rc==SQLITE_OK ){ + pInfo->nBackfill = mxSafeFrame; + } + } + + /* Release the reader lock held while backfilling */ + walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); + } + + if( rc==SQLITE_BUSY ){ + /* Reset the return code so as not to report a checkpoint failure + ** just because there are active readers. */ + rc = SQLITE_OK; + } + + /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal + ** file has been copied into the database file, then block until all + ** readers have finished using the wal file. This ensures that the next + ** process to write to the database restarts the wal file. */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; - }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ - u32 salt1; - sqlite3_randomness(4, &salt1); - assert( pInfo->nBackfill==pWal->hdr.mxFrame ); + }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ + assert( mxSafeFrame==pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); if( rc==SQLITE_OK ){ - if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ - /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as - ** SQLITE_CHECKPOINT_RESTART with the addition that it also - ** truncates the log file to zero bytes just prior to a - ** successful return. - ** - ** In theory, it might be safe to do this without updating the - ** wal-index header in shared memory, as all subsequent reader or - ** writer clients should see that the entire log file has been - ** checkpointed and behave accordingly. This seems unsafe though, - ** as it would leave the system in a state where the contents of - ** the wal-index header do not match the contents of the - ** file-system. To avoid this, update the wal-index header to - ** indicate that the log file contains zero valid frames. */ - walRestartHdr(pWal, salt1); - rc = sqlite3OsTruncate(pWal->pWalFd, 0); - } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); } } @@ -52827,7 +49045,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){ ** wal-index from the WAL before returning. ** ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is -** changed by this operation. If pWal->hdr is unchanged, set *pChanged +** changed by this opertion. If pWal->hdr is unchanged, set *pChanged ** to 0. ** ** If the wal-index header is successfully read, return SQLITE_OK. @@ -52956,7 +49174,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ int mxI; /* Index of largest aReadMark[] value */ int i; /* Loop counter */ int rc = SQLITE_OK; /* Return code */ - u32 mxFrame; /* Wal frame to lock to */ assert( pWal->readLock<0 ); /* Not currently locked */ @@ -52974,8 +49191,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this ** is more of a scheduler yield than an actual delay. But on the 10th ** an subsequent retries, the delays start becoming longer and longer, - ** 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. + ** so that on the 100th (and last) RETRY we delay for 21 milliseconds. + ** The total delay time before giving up is less than 1 second. */ if( cnt>5 ){ int nDelay = 1; /* Pause time in microseconds */ @@ -52983,7 +49200,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ VVA_ONLY( pWal->lockError = 1; ) return SQLITE_PROTOCOL; } - if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; + if( cnt>=10 ) nDelay = (cnt-9)*238; /* Max delay 21ms. Total delay 996ms */ sqlite3OsSleep(pWal->pVfs, nDelay); } @@ -53020,12 +49237,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } pInfo = walCkptInfo(pWal); - if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame -#ifdef SQLITE_ENABLE_SNAPSHOT - && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0 - || 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr))) -#endif - ){ + if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){ /* The WAL has been completely backfilled (or it is empty). ** and can be safely ignored. */ @@ -53037,7 +49249,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** 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 + ** 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 @@ -53063,88 +49275,70 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ */ 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 ){ + if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){ assert( thisMark!=READMARK_NOT_USED ); mxReadMark = thisMark; mxI = i; } } - if( (pWal->readOnly & WAL_SHM_RDONLY)==0 - && (mxReadMarkaReadMark[i] = mxFrame; - mxI = i; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - break; - }else if( rc!=SQLITE_BUSY ){ - return rc; + /* There was once an "if" here. The extra "{" is to preserve indentation. */ + { + if( (pWal->readOnly & WAL_SHM_RDONLY)==0 + && (mxReadMarkhdr.mxFrame || mxI==0) + ){ + for(i=1; iaReadMark[i] = pWal->hdr.mxFrame; + mxI = i; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + break; + }else if( rc!=SQLITE_BUSY ){ + return rc; + } } } - } - if( mxI==0 ){ - assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); - return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; - } + if( mxI==0 ){ + assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); + return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; + } - rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); - if( rc ){ - return rc==SQLITE_BUSY ? WAL_RETRY : rc; - } - /* Now that the read-lock has been obtained, check that neither the - ** value in the aReadMark[] array or the contents of the wal-index - ** header have changed. - ** - ** It is necessary to check that the wal-index header did not change - ** between the time it was read and when the shared-lock was obtained - ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility - ** that the log file may have been wrapped by a writer, or that frames - ** that occur later in the log than pWal->hdr.mxFrame may have been - ** copied into the database by a checkpointer. If either of these things - ** happened, then reading the database with the current value of - ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry - ** instead. - ** - ** Before checking that the live wal-index header has not changed - ** since it was read, set Wal.minFrame to the first frame in the wal - ** file that has not yet been checkpointed. This client will not need - ** to read any frames earlier than minFrame from the wal file - they - ** can be safely read directly from the database file. - ** - ** Because a ShmBarrier() call is made between taking the copy of - ** nBackfill and checking that the wal-header in shared-memory still - ** matches the one cached in pWal->hdr, it is guaranteed that the - ** checkpointer that set nBackfill was not working with a wal-index - ** header newer than that cached in pWal->hdr. If it were, that could - ** cause a problem. The checkpointer could omit to checkpoint - ** a version of page X that lies before pWal->minFrame (call that version - ** A) on the basis that there is a newer version (version B) of the same - ** page later in the wal file. But if version B happens to like past - ** frame pWal->hdr.mxFrame - then the client would incorrectly assume - ** that it can read version A from the database file. However, since - ** we can guarantee that the checkpointer that set nBackfill could not - ** see any pages past pWal->hdr.mxFrame, this problem does not come up. - */ - pWal->minFrame = pInfo->nBackfill+1; - walShmBarrier(pWal); - if( pInfo->aReadMark[mxI]!=mxReadMark - || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) - ){ - walUnlockShared(pWal, WAL_READ_LOCK(mxI)); - return WAL_RETRY; - }else{ - assert( mxReadMark<=pWal->hdr.mxFrame ); - pWal->readLock = (i16)mxI; + 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. + ** + ** This does not guarantee that the copy of the wal-index header is up to + ** date before proceeding. That would not be possible without somehow + ** blocking writers. It only guarantees that a dangerous checkpoint or + ** log-wrap (either of which would require an exclusive lock on + ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid. + */ + walShmBarrier(pWal); + if( pInfo->aReadMark[mxI]!=mxReadMark + || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) + ){ + walUnlockShared(pWal, WAL_READ_LOCK(mxI)); + return WAL_RETRY; + }else{ + assert( mxReadMark<=pWal->hdr.mxFrame ); + pWal->readLock = (i16)mxI; + } } return rc; } @@ -53167,14 +49361,6 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ -#ifdef SQLITE_ENABLE_SNAPSHOT - int bChanged = 0; - WalIndexHdr *pSnapshot = pWal->pSnapshot; - if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - bChanged = 1; - } -#endif - do{ rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); }while( rc==WAL_RETRY ); @@ -53182,66 +49368,6 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ testcase( (rc&0xff)==SQLITE_IOERR ); testcase( rc==SQLITE_PROTOCOL ); testcase( rc==SQLITE_OK ); - -#ifdef SQLITE_ENABLE_SNAPSHOT - if( rc==SQLITE_OK ){ - if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - /* At this point the client has a lock on an aReadMark[] slot holding - ** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr - ** is populated with the wal-index header corresponding to the head - ** of the wal file. Verify that pSnapshot is still valid before - ** continuing. Reasons why pSnapshot might no longer be valid: - ** - ** (1) The WAL file has been reset since the snapshot was taken. - ** In this case, the salt will have changed. - ** - ** (2) A checkpoint as been attempted that wrote frames past - ** pSnapshot->mxFrame into the database file. Note that the - ** checkpoint need not have completed for this to cause problems. - */ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - - assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 ); - assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame ); - - /* It is possible that there is a checkpointer thread running - ** concurrent with this code. If this is the case, it may be that the - ** checkpointer has already determined that it will checkpoint - ** snapshot X, where X is later in the wal file than pSnapshot, but - ** has not yet set the pInfo->nBackfillAttempted variable to indicate - ** its intent. To avoid the race condition this leads to, ensure that - ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. */ - rc = walLockShared(pWal, WAL_CKPT_LOCK); - - if( rc==SQLITE_OK ){ - /* Check that the wal file has not been wrapped. Assuming that it has - ** not, also check that no checkpointer has attempted to checkpoint any - ** frames beyond pSnapshot->mxFrame. If either of these conditions are - ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr - ** with *pSnapshot and set *pChanged as appropriate for opening the - ** snapshot. */ - if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - && pSnapshot->mxFrame>=pInfo->nBackfillAttempted - ){ - assert( pWal->readLock>0 ); - memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); - *pChanged = bChanged; - }else{ - rc = SQLITE_BUSY_SNAPSHOT; - } - - /* Release the shared CKPT lock obtained above. */ - walUnlockShared(pWal, WAL_CKPT_LOCK); - } - - - if( rc!=SQLITE_OK ){ - sqlite3WalEndReadTransaction(pWal); - } - } - } -#endif return rc; } @@ -53273,7 +49399,6 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( u32 iRead = 0; /* If !=0, WAL frame to return data from */ u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ int iHash; /* Used to loop through N hash tables */ - int iMinHash; /* This routine is only be called from within a read transaction. */ assert( pWal->readLock>=0 || pWal->lockError ); @@ -53314,8 +49439,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( ** This condition filters out entries that were added to the hash ** table after the current read-transaction had started. */ - iMinHash = walFramePage(pWal->minFrame); - for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){ + for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){ volatile ht_slot *aHash; /* Pointer to hash table */ volatile u32 *aPgno; /* Pointer to array of page numbers */ u32 iZero; /* Frame number corresponding to aPgno[0] */ @@ -53330,8 +49454,8 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( nCollide = HASHTABLE_NSLOT; for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ u32 iFrame = aHash[iKey] + iZero; - if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){ - assert( iFrame>iRead || CORRUPT_DB ); + if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ + /* assert( iFrame>iRead ); -- not true if there is corruption */ iRead = iFrame; } if( (nCollide--)==0 ){ @@ -53347,8 +49471,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( { u32 iRead2 = 0; u32 iTest; - assert( pWal->minFrame>0 ); - for(iTest=iLast; iTest>=pWal->minFrame; iTest--){ + for(iTest=iLast; iTest>0; iTest--){ if( walFramePgno(pWal, iTest)==pgno ){ iRead2 = iTest; break; @@ -53497,6 +49620,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } + assert( rc==SQLITE_OK ); return rc; } @@ -53545,6 +49669,7 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ return rc; } + /* ** This function is called just before writing a set of frames to the log ** file (see sqlite3WalFrames()). It checks to see if, instead of appending @@ -53577,8 +49702,20 @@ static int walRestartLog(Wal *pWal){ ** In theory it would be Ok to update the cache of the header only ** at this point. But updating the actual wal-index header is also ** safe and means there is no special case for sqlite3WalUndo() - ** to handle if this transaction is rolled back. */ - walRestartHdr(pWal, salt1); + ** to handle if this transaction is rolled back. + */ + int i; /* Loop counter */ + u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ + + pWal->nCkpt++; + pWal->hdr.mxFrame = 0; + sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); + aSalt[1] = salt1; + walIndexWriteHdr(pWal); + pInfo->nBackfill = 0; + pInfo->aReadMark[1] = 0; + for(i=2; iaReadMark[i] = READMARK_NOT_USED; + assert( pInfo->aReadMark[0]==0 ); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); }else if( rc!=SQLITE_BUSY ){ return rc; @@ -53780,7 +49917,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( ** ** Padding and syncing only occur if this set of frames complete a ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL - ** or synchronous==OFF, then no padding or syncing are needed. + ** or synchonous==OFF, then no padding or syncing are needed. ** ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not ** needed and only the sync is done. If padding is needed, then the @@ -53866,7 +50003,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Wal connection */ - int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ + int eMode, /* PASSIVE, FULL or RESTART */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags to sync db file with (or 0) */ @@ -53878,42 +50015,29 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( int rc; /* Return code */ int isChanged = 0; /* True if a new wal-index header is loaded */ int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ - int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked - ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); - if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - - /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive - ** "checkpoint" lock on the database file. */ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc ){ - /* EVIDENCE-OF: R-10421-19736 If any other process is running a - ** checkpoint operation at the same time, the lock cannot be obtained and - ** SQLITE_BUSY is returned. - ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, - ** it will not be invoked in this case. - */ - testcase( rc==SQLITE_BUSY ); - testcase( xBusy!=0 ); + /* Usually this is SQLITE_BUSY meaning that another thread or process + ** is already running a checkpoint, or maybe a recovery. But it might + ** also be SQLITE_IOERR. */ return rc; } pWal->ckptLock = 1; - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and - ** TRUNCATE modes also obtain the exclusive "writer" lock on the database - ** file. + /* If this is a blocking-checkpoint, then obtain the write-lock as well + ** to prevent any writers from running while the checkpoint is underway. + ** This has to be done before the call to walIndexReadHdr() below. ** - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained - ** immediately, and a busy-handler is configured, it is invoked and the - ** writer lock retried until either the busy-handler returns 0 or the - ** lock is successfully obtained. + ** If the writer lock cannot be obtained, then a passive checkpoint is + ** run instead. Since the checkpointer is not holding the writer lock, + ** there is no point in blocking waiting for any readers. Assuming no + ** other error occurs, this function will return SQLITE_BUSY to the caller. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); @@ -53921,7 +50045,6 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( pWal->writeLock = 1; }else if( rc==SQLITE_BUSY ){ eMode2 = SQLITE_CHECKPOINT_PASSIVE; - xBusy2 = 0; rc = SQLITE_OK; } } @@ -53939,7 +50062,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); } /* If no error occurred, set the output variables. */ @@ -54051,35 +50174,6 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); } -#ifdef SQLITE_ENABLE_SNAPSHOT -/* Create a snapshot object. The content of a snapshot is opaque to -** every other subsystem, so the WAL module can put whatever it needs -** in the object. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ - int rc = SQLITE_OK; - WalIndexHdr *pRet; - - assert( pWal->readLock>=0 && pWal->writeLock==0 ); - - pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); - if( pRet==0 ){ - rc = SQLITE_NOMEM; - }else{ - memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); - *ppSnapshot = (sqlite3_snapshot*)pRet; - } - - return rc; -} - -/* Try to open on pSnapshot when the next read-transaction starts -*/ -SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){ - pWal->pSnapshot = (WalIndexHdr*)pSnapshot; -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ - #ifdef SQLITE_ENABLE_ZIPVFS /* ** If the argument is not NULL, it points to a Wal object that holds a @@ -54092,12 +50186,6 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ } #endif -/* Return the sqlite3_file object for the WAL file -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ - return pWal->pWalFd; -} - #endif /* #ifndef SQLITE_OMIT_WAL */ /************** End of wal.c *************************************************/ @@ -54132,7 +50220,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file implements an external (disk-based) database using BTrees. +** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -54258,7 +50346,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ ** ** The flags define the format of this btree page. The leaf flag means that ** this page has no children. The zerodata flag means that this page carries -** only keys and no data. The intkey flag means that the key is an integer +** only keys and no data. The intkey flag means that the key is a integer ** which is stored in the key size entry of the cell header rather than in ** the payload area. ** @@ -54336,7 +50424,6 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ ** 4 Number of leaf pointers on this page ** * zero or more pages numbers of leaves */ -/* #include "sqliteInt.h" */ /* The following value is the maximum cell size assuming a maximum page @@ -54354,7 +50441,6 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ /* Forward declarations */ typedef struct MemPage MemPage; typedef struct BtLock BtLock; -typedef struct CellInfo CellInfo; /* ** This is a magic string that appears at the beginning of every @@ -54397,14 +50483,12 @@ typedef struct CellInfo CellInfo; struct MemPage { u8 isInit; /* True if previously initialized. MUST BE FIRST! */ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ - u8 intKey; /* True if table b-trees. False for index b-trees */ - u8 intKeyLeaf; /* True if the leaf of an intKey table */ - u8 noPayload; /* True if internal intKey page (thus w/o data) */ - u8 leaf; /* True if a leaf page */ + u8 intKey; /* True if intkey flag is set */ + u8 leaf; /* True if leaf flag is set */ + u8 hasData; /* True if this page stores data */ u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ - u8 bBusy; /* Prevent endless loops on corrupt database files */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ @@ -54418,10 +50502,7 @@ struct MemPage { u8 *aData; /* Pointer to disk image of the page data */ u8 *aDataEnd; /* One byte past the end of usable data */ u8 *aCellIdx; /* The cell index area */ - u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */ DbPage *pDbPage; /* Pager page handle */ - u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ - void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ Pgno pgno; /* Page number for this page */ }; @@ -54477,10 +50558,8 @@ struct Btree { u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ u8 sharable; /* True if we can share pBt with another db */ u8 locked; /* True if db currently has pBt locked */ - u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */ int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ int nBackup; /* Number of backup operations reading this btree */ - u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ Btree *pNext; /* List of other sharable Btrees from the same db */ Btree *pPrev; /* Back pointer of the same list */ #ifndef SQLITE_OMIT_SHARED_CACHE @@ -54547,9 +50626,6 @@ struct BtShared { #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ -#ifdef SQLITE_HAS_CODEC - u8 optimalReserve; /* Desired amount of reserved space per page */ -#endif u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ @@ -54569,7 +50645,7 @@ struct BtShared { BtLock *pLock; /* List of locks held on this shared-btree struct */ Btree *pWriter; /* Btree with currently open write transaction */ #endif - u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */ + u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ }; /* @@ -54588,11 +50664,15 @@ struct BtShared { ** about a cell. The parseCellPtr() function fills in this structure ** based on information extract from the raw disk page. */ +typedef struct CellInfo CellInfo; struct CellInfo { - i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */ - u8 *pPayload; /* Pointer to the start of payload */ - u32 nPayload; /* Bytes of payload */ - u16 nLocal; /* Amount of payload held locally, not on overflow */ + i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ + u8 *pCell; /* Pointer to the start of cell content */ + u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ + u16 nHeader; /* Size of the cell content header in bytes */ + u16 nLocal; /* Amount of payload held locally */ + u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ u16 nSize; /* Size of the cell content on the main b-tree page */ }; @@ -54620,35 +50700,23 @@ struct CellInfo { ** ** Fields in this structure are accessed under the BtShared.mutex ** found at self->pBt->mutex. -** -** skipNext meaning: -** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op. -** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op. -** eState==FAULT: Cursor fault with skipNext as error code. */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext; /* Forms a linked list of all cursors */ + BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ + struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno *aOverflow; /* Cache of overflow page locations */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor last known position */ Pgno pgnoRoot; /* The root page of this tree */ int nOvflAlloc; /* Allocated size of aOverflow[] array */ - int skipNext; /* Prev() is noop if negative. Next() is noop if positive. - ** Error code if eState==CURSOR_FAULT */ + int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ u8 curFlags; /* zero or more BTCF_* flags defined below */ - u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ - u8 hints; /* As configured by CursorSetHints() */ - /* All fields above are zeroed when the cursor is allocated. See - ** sqlite3BtreeCursorZero(). Fields that follow must be manually - ** initialized. */ - i8 iPage; /* Index of current page in apPage */ - u8 curIntKey; /* Value of apPage[0]->intKey */ - struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ - void *padding1; /* Make object size a multiple of 16 */ + u8 hints; /* As configured by CursorSetHints() */ + i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; @@ -54661,7 +50729,6 @@ struct BtCursor { #define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ #define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ #define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ -#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */ /* ** Potential values for BtCursor.eState. @@ -54687,11 +50754,11 @@ struct BtCursor { ** seek the cursor to the saved position. ** ** CURSOR_FAULT: -** An unrecoverable error (an I/O error or a malloc failure) has occurred +** A unrecoverable error (an I/O error or a malloc failure) has occurred ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor -** should return the error code stored in BtCursor.skipNext +** should return the error code stored in BtCursor.skip */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 @@ -54801,10 +50868,7 @@ struct IntegrityCk { int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ - const char *zPfx; /* Error message prefix */ - int v1, v2; /* Values for up to two %d fields in zPfx */ StrAccum errMsg; /* Accumulate the error message text here */ - u32 *heap; /* Min-heap used for analyzing cell coverage */ }; /* @@ -54815,23 +50879,6 @@ struct IntegrityCk { #define get4byte sqlite3Get4byte #define put4byte sqlite3Put4byte -/* -** get2byteAligned(), unlike get2byte(), requires that its argument point to a -** two-byte aligned address. get2bytea() is only used for accessing the -** cell addresses in a btree header. -*/ -#if SQLITE_BYTEORDER==4321 -# define get2byteAligned(x) (*(u16*)(x)) -#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ - && GCC_VERSION>=4008000 -# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x)) -#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ - && defined(_MSC_VER) && _MSC_VER>=1300 -# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x)) -#else -# define get2byteAligned(x) ((x)[0]<<8 | (x)[1]) -#endif - /************** End of btreeInt.h ********************************************/ /************** Continuing where we left off in btmutex.c ********************/ #ifndef SQLITE_OMIT_SHARED_CACHE @@ -54856,7 +50903,7 @@ static void lockBtreeMutex(Btree *p){ ** Release the BtShared mutex associated with B-Tree handle p and ** clear the p->locked boolean. */ -static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ +static void unlockBtreeMutex(Btree *p){ BtShared *pBt = p->pBt; assert( p->locked==1 ); assert( sqlite3_mutex_held(pBt->mutex) ); @@ -54867,9 +50914,6 @@ static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ p->locked = 0; } -/* Forward reference */ -static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); - /* ** Enter a mutex on the given BTree object. ** @@ -54887,6 +50931,8 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); ** subsequent Btrees that desire a lock. */ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ + Btree *pLater; + /* Some basic sanity checking on the Btree. The list of Btrees ** connected by pNext and pPrev should be in sorted order by ** Btree.pBt value. All elements of the list should belong to @@ -54911,20 +50957,9 @@ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; - btreeLockCarefully(p); -} - -/* This is a helper function for sqlite3BtreeLock(). By moving -** complex, but seldom used logic, out of sqlite3BtreeLock() and -** into this routine, we avoid unnecessary stack pointer changes -** and thus help the sqlite3BtreeLock() routine to run much faster -** in the common case. -*/ -static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ - Btree *pLater; /* In most cases, we should be able to acquire the lock we - ** want without having to go through the ascending lock + ** want without having to go throught the ascending lock ** procedure that follows. Just be sure not to block. */ if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ @@ -54954,12 +50989,10 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ } } - /* ** Exit the recursive mutex on a Btree. */ SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){ - assert( sqlite3_mutex_held(p->db->mutex) ); if( p->sharable ){ assert( p->wantToLock>0 ); p->wantToLock--; @@ -55131,11 +51164,10 @@ SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file implements an external (disk-based) database using BTrees. +** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ -/* #include "btreeInt.h" */ /* ** The header string that appears at the beginning of every @@ -55208,7 +51240,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){ +SQLITE_API int sqlite3_enable_shared_cache(int enable){ sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; } @@ -55284,7 +51316,7 @@ static int hasSharedCacheTableLock( ** the correct locks are held. So do not bother - just return true. ** This case does not come up very often anyhow. */ - if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){ + if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){ return 1; } @@ -55297,12 +51329,6 @@ static int hasSharedCacheTableLock( for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ Index *pIdx = (Index *)sqliteHashData(p); if( pIdx->tnum==(int)iRoot ){ - if( iTab ){ - /* Two or more indexes share the same root page. There must - ** be imposter tables. So just return true. The assert is not - ** useful in that case. */ - return 1; - } iTab = pIdx->pTable->tnum; } } @@ -55612,15 +51638,11 @@ static void invalidateIncrblobCursors( int isClearTable /* True if all rows are being deleted */ ){ BtCursor *p; - if( pBtree->hasIncrblobCur==0 ) return; + BtShared *pBt = pBtree->pBt; assert( sqlite3BtreeHoldsMutex(pBtree) ); - pBtree->hasIncrblobCur = 0; - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( (p->curFlags & BTCF_Incrblob)!=0 ){ - pBtree->hasIncrblobCur = 1; - if( isClearTable || p->info.nKey==iRow ){ - p->eState = CURSOR_INVALID; - } + for(p=pBt->pCursor; p; p=p->pNext){ + if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){ + p->eState = CURSOR_INVALID; } } } @@ -55713,49 +51735,6 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ pCur->iPage = -1; } -/* -** The cursor passed as the only argument must point to a valid entry -** when this function is called (i.e. have eState==CURSOR_VALID). This -** function saves the current cursor key in variables pCur->nKey and -** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error -** code otherwise. -** -** If the cursor is open on an intkey table, then the integer key -** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to -** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is -** set to point to a malloced buffer pCur->nKey bytes in size containing -** the key. -*/ -static int saveCursorKey(BtCursor *pCur){ - int rc; - assert( CURSOR_VALID==pCur->eState ); - assert( 0==pCur->pKey ); - assert( cursorHoldsMutex(pCur) ); - - rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); - assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ - - /* If this is an intKey table, then the above call to BtreeKeySize() - ** stores the integer key in pCur->nKey. In this case this value is - ** all that is required. Otherwise, if pCur is not open on an intKey - ** table, then malloc space for and store the pCur->nKey bytes of key - ** data. */ - if( 0==pCur->curIntKey ){ - void *pKey = sqlite3Malloc( pCur->nKey ); - if( pKey ){ - rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); - if( rc==SQLITE_OK ){ - pCur->pKey = pKey; - }else{ - sqlite3_free(pKey); - } - }else{ - rc = SQLITE_NOMEM; - } - } - assert( !pCur->curIntKey || !pCur->pKey ); - return rc; -} /* ** Save the current cursor position in the variables BtCursor.nKey @@ -55767,75 +51746,55 @@ static int saveCursorKey(BtCursor *pCur){ static int saveCursorPosition(BtCursor *pCur){ int rc; - assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); + assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); - if( pCur->eState==CURSOR_SKIPNEXT ){ - pCur->eState = CURSOR_VALID; - }else{ - pCur->skipNext = 0; - } + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ + + /* If this is an intKey table, then the above call to BtreeKeySize() + ** stores the integer key in pCur->nKey. In this case this value is + ** all that is required. Otherwise, if pCur is not open on an intKey + ** table, then malloc space for and store the pCur->nKey bytes of key + ** data. + */ + if( 0==pCur->apPage[0]->intKey ){ + void *pKey = sqlite3Malloc( (int)pCur->nKey ); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqlite3_free(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->apPage[0]->intKey || !pCur->pKey ); - rc = saveCursorKey(pCur); if( rc==SQLITE_OK ){ btreeReleaseAllCursorPages(pCur); pCur->eState = CURSOR_REQUIRESEEK; } - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast); + invalidateOverflowCache(pCur); return rc; } -/* Forward reference */ -static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); - /* ** Save the positions of all cursors (except pExcept) that are open on -** the table with root-page iRoot. "Saving the cursor position" means that -** the location in the btree is remembered in such a way that it can be -** moved back to the same spot after the btree has been modified. This -** routine is called just before cursor pExcept is used to modify the -** table, for example in BtreeDelete() or BtreeInsert(). -** -** If there are two or more cursors on the same btree, then all such -** cursors should have their BTCF_Multiple flag set. The btreeCursor() -** routine enforces that rule. This routine only needs to be called in -** the uncommon case when pExpect has the BTCF_Multiple flag set. -** -** If pExpect!=NULL and if no other cursors are found on the same root-page, -** then the BTCF_Multiple flag on pExpect is cleared, to avoid another -** pointless call to this routine. -** -** Implementation note: This routine merely checks to see if any cursors -** need to be saved. It calls out to saveCursorsOnList() in the (unusual) -** event that cursors are in need to being saved. +** the table with root-page iRoot. Usually, this is called just before cursor +** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ - if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; - } - if( p ) return saveCursorsOnList(p, iRoot, pExcept); - if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple; - return SQLITE_OK; -} - -/* This helper routine to saveAllCursors does the actual work of saving -** the cursors if and when a cursor is found that actually requires saving. -** The common case is that no cursors need to be saved, so this routine is -** broken out from its caller to avoid unnecessary stack pointer movement. -*/ -static int SQLITE_NOINLINE saveCursorsOnList( - BtCursor *p, /* The first cursor that needs saving */ - Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */ - BtCursor *pExcept /* Do not save this cursor */ -){ - do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ + if( p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; @@ -55845,8 +51804,7 @@ static int SQLITE_NOINLINE saveCursorsOnList( btreeReleaseAllCursorPages(p); } } - p = p->pNext; - }while( p ); + } return SQLITE_OK; } @@ -55907,19 +51865,17 @@ static int btreeMoveto( */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; - int skipNext; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); - pCur->skipNext |= skipNext; if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; } @@ -55933,73 +51889,41 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){ SQLITE_OK) /* -** Determine whether or not a cursor has moved from the position where -** it was last placed, or has been invalidated for any other reason. -** Cursors can move when the row they are pointing at is deleted out -** from under them, for example. Cursor might also move if a btree -** is rebalanced. +** Determine whether or not a cursor has moved from the position it +** was last placed at. Cursors can move when the row they are pointing +** at is deleted out from under them. ** -** Calling this routine with a NULL cursor pointer returns false. +** This routine returns an error code if something goes wrong. The +** integer *pHasMoved is set as follows: ** -** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor -** back to where it ought to be if this routine returns true. +** 0: The cursor is unchanged +** 1: The cursor is still pointing at the same row, but the pointers +** returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch() +** might now be invalid because of a balance() or other change to the +** b-tree. +** 2: The cursor is no longer pointing to the row. The row might have +** been deleted out from under the cursor. */ -SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ - return pCur->eState!=CURSOR_VALID; -} - -/* -** This routine restores a cursor back to its original position after it -** has been moved by some outside activity (such as a btree rebalance or -** a row having been deleted out from under the cursor). -** -** On success, the *pDifferentRow parameter is false if the cursor is left -** pointing at exactly the same row. *pDifferntRow is the row the cursor -** was pointing to has been deleted, forcing the cursor to point to some -** nearby row. -** -** This routine should only be called for a cursor that just returned -** TRUE from sqlite3BtreeCursorHasMoved(). -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ int rc; - assert( pCur!=0 ); - assert( pCur->eState!=CURSOR_VALID ); + if( pCur->eState==CURSOR_VALID ){ + *pHasMoved = 0; + return SQLITE_OK; + } rc = restoreCursorPosition(pCur); if( rc ){ - *pDifferentRow = 1; + *pHasMoved = 2; return rc; } - if( pCur->eState!=CURSOR_VALID ){ - *pDifferentRow = 1; + if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ + *pHasMoved = 2; }else{ - assert( pCur->skipNext==0 ); - *pDifferentRow = 0; + *pHasMoved = 1; } return SQLITE_OK; } -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Provide hints to the cursor. The particular hint given (and the type -** and number of the varargs parameters) is determined by the eHintType -** parameter. See the definitions of the BTREE_HINT_* macros for details. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){ - /* Used only by system that substitute their own storage engine */ -} -#endif - -/* -** Provide flag hints to the cursor. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ - assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 ); - pCur->hints = x; -} - - #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page @@ -56053,7 +51977,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ return; } iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=SQLITE_OK ){ *pRC = rc; return; @@ -56096,7 +52020,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ assert( sqlite3_mutex_held(pBt->mutex) ); iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=0 ){ return rc; } @@ -56128,218 +52052,128 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ ** the page, 1 means the second cell, and so forth) return a pointer ** to the cell content. ** -** findCellPastPtr() does the same except it skips past the initial -** 4-byte child pointer found on interior pages, if there is one. -** ** This routine works only for pages that do not contain overflow cells. */ #define findCell(P,I) \ - ((P)->aData + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) -#define findCellPastPtr(P,I) \ - ((P)->aDataOfst + ((P)->maskPage & get2byteAligned(&(P)->aCellIdx[2*(I)]))) + ((P)->aData + ((P)->maskPage & get2byte(&(P)->aCellIdx[2*(I)]))) +#define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I))))) /* -** This is common tail processing for btreeParseCellPtr() and -** btreeParseCellPtrIndex() for the case when the cell does not fit entirely -** on a single B-tree page. Make necessary adjustments to the CellInfo -** structure. +** This a more complex version of findCell() that works for +** pages that do contain overflow cells. */ -static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - /* If the payload will not fit completely on the local page, we have - ** to decide how much to store locally and how much to spill onto - ** overflow pages. The strategy is to minimize the amount of unused - ** space on overflow pages while keeping the amount of local storage - ** in between minLocal and maxLocal. - ** - ** Warning: changing the way overflow payload is distributed in any - ** way will result in an incompatible file format. - */ - int minLocal; /* Minimum amount of payload held locally */ - int maxLocal; /* Maximum amount of payload held locally */ - int surplus; /* Overflow payload available for local storage */ - - minLocal = pPage->minLocal; - maxLocal = pPage->maxLocal; - surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4); - testcase( surplus==maxLocal ); - testcase( surplus==maxLocal+1 ); - if( surplus <= maxLocal ){ - pInfo->nLocal = (u16)surplus; - }else{ - pInfo->nLocal = (u16)minLocal; - } - pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4; -} - -/* -** The following routines are implementations of the MemPage.xParseCell() -** method. -** -** Parse a cell content block and fill in the CellInfo structure. -** -** btreeParseCellPtr() => table btree leaf nodes -** btreeParseCellNoPayload() => table btree internal nodes -** btreeParseCellPtrIndex() => index btree nodes -** -** There is also a wrapper function btreeParseCell() that works for -** all MemPage types and that references the cell by index rather than -** by pointer. -*/ -static void btreeParseCellPtrNoPayload( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ +static u8 *findOverflowCell(MemPage *pPage, int iCell){ + int i; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->leaf==0 ); - assert( pPage->noPayload ); - assert( pPage->childPtrSize==4 ); -#ifndef SQLITE_DEBUG - UNUSED_PARAMETER(pPage); -#endif - pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey); - pInfo->nPayload = 0; - pInfo->nLocal = 0; - pInfo->pPayload = 0; - return; + for(i=pPage->nOverflow-1; i>=0; i--){ + int k; + k = pPage->aiOvfl[i]; + if( k<=iCell ){ + if( k==iCell ){ + return pPage->apOvfl[i]; + } + iCell--; + } + } + return findCell(pPage, iCell); } + +/* +** Parse a cell content block and fill in the CellInfo structure. There +** are two versions of this function. btreeParseCell() takes a +** cell index as the second argument and btreeParseCellPtr() +** takes a pointer to the body of the cell as its second argument. +** +** Within this file, the parseCell() macro can be called instead of +** btreeParseCellPtr(). Using some compilers, this will be faster. +*/ static void btreeParseCellPtr( MemPage *pPage, /* Page containing the cell */ u8 *pCell, /* Pointer to the cell text. */ CellInfo *pInfo /* Fill in this structure */ ){ - u8 *pIter; /* For scanning through pCell */ + u16 n; /* Number bytes in cell content header */ u32 nPayload; /* Number of bytes of cell payload */ - u64 iKey; /* Extracted Key value */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + pInfo->pCell = pCell; assert( pPage->leaf==0 || pPage->leaf==1 ); - assert( pPage->intKeyLeaf || pPage->noPayload ); - assert( pPage->noPayload==0 ); - assert( pPage->intKeyLeaf ); - assert( pPage->childPtrSize==0 ); - pIter = pCell; - - /* The next block of code is equivalent to: - ** - ** pIter += getVarint32(pIter, nPayload); - ** - ** The code is inlined to avoid a function call. - */ - nPayload = *pIter; - if( nPayload>=0x80 ){ - u8 *pEnd = &pIter[8]; - nPayload &= 0x7f; - do{ - nPayload = (nPayload<<7) | (*++pIter & 0x7f); - }while( (*pIter)>=0x80 && pIternKey); - ** - ** The code is inlined to avoid a function call. - */ - iKey = *pIter; - if( iKey>=0x80 ){ - u8 *pEnd = &pIter[7]; - iKey &= 0x7f; - while(1){ - iKey = (iKey<<7) | (*++pIter & 0x7f); - if( (*pIter)<0x80 ) break; - if( pIter>=pEnd ){ - iKey = (iKey<<8) | *++pIter; - break; - } + n = pPage->childPtrSize; + assert( n==4-4*pPage->leaf ); + if( pPage->intKey ){ + if( pPage->hasData ){ + assert( n==0 ); + n = getVarint32(pCell, nPayload); + }else{ + nPayload = 0; } + n += getVarint(&pCell[n], (u64*)&pInfo->nKey); + pInfo->nData = nPayload; + }else{ + pInfo->nData = 0; + n += getVarint32(&pCell[n], nPayload); + pInfo->nKey = nPayload; } - pIter++; - - pInfo->nKey = *(i64*)&iKey; pInfo->nPayload = nPayload; - pInfo->pPayload = pIter; + pInfo->nHeader = n; testcase( nPayload==pPage->maxLocal ); testcase( nPayload==pPage->maxLocal+1 ); - if( nPayload<=pPage->maxLocal ){ + if( likely(nPayload<=pPage->maxLocal) ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. */ - pInfo->nSize = nPayload + (u16)(pIter - pCell); - if( pInfo->nSize<4 ) pInfo->nSize = 4; + if( (pInfo->nSize = (u16)(n+nPayload))<4 ) pInfo->nSize = 4; pInfo->nLocal = (u16)nPayload; + pInfo->iOverflow = 0; }else{ - btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); - } -} -static void btreeParseCellPtrIndex( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - u8 *pIter; /* For scanning through pCell */ - u32 nPayload; /* Number of bytes of cell payload */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->leaf==0 || pPage->leaf==1 ); - assert( pPage->intKeyLeaf==0 ); - assert( pPage->noPayload==0 ); - pIter = pCell + pPage->childPtrSize; - nPayload = *pIter; - if( nPayload>=0x80 ){ - u8 *pEnd = &pIter[8]; - nPayload &= 0x7f; - do{ - nPayload = (nPayload<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pIternKey = nPayload; - pInfo->nPayload = nPayload; - pInfo->pPayload = pIter; - testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); - if( nPayload<=pPage->maxLocal ){ - /* This is the (easy) common case where the entire payload fits - ** on the local page. No overflow is required. + /* If the payload will not fit completely on the local page, we have + ** to decide how much to store locally and how much to spill onto + ** overflow pages. The strategy is to minimize the amount of unused + ** space on overflow pages while keeping the amount of local storage + ** in between minLocal and maxLocal. + ** + ** Warning: changing the way overflow payload is distributed in any + ** way will result in an incompatible file format. */ - pInfo->nSize = nPayload + (u16)(pIter - pCell); - if( pInfo->nSize<4 ) pInfo->nSize = 4; - pInfo->nLocal = (u16)nPayload; - }else{ - btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); + int minLocal; /* Minimum amount of payload held locally */ + int maxLocal; /* Maximum amount of payload held locally */ + int surplus; /* Overflow payload available for local storage */ + + minLocal = pPage->minLocal; + maxLocal = pPage->maxLocal; + surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); + testcase( surplus==maxLocal ); + testcase( surplus==maxLocal+1 ); + if( surplus <= maxLocal ){ + pInfo->nLocal = (u16)surplus; + }else{ + pInfo->nLocal = (u16)minLocal; + } + pInfo->iOverflow = (u16)(pInfo->nLocal + n); + pInfo->nSize = pInfo->iOverflow + 4; } } +#define parseCell(pPage, iCell, pInfo) \ + btreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) static void btreeParseCell( MemPage *pPage, /* Page containing the cell */ int iCell, /* The cell index. First cell is 0 */ CellInfo *pInfo /* Fill in this structure */ ){ - pPage->xParseCell(pPage, findCell(pPage, iCell), pInfo); + parseCell(pPage, iCell, pInfo); } /* -** The following routines are implementations of the MemPage.xCellSize -** method. -** ** Compute the total number of bytes that a Cell needs in the cell ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. -** -** cellSizePtrNoPayload() => table internal nodes -** cellSizePtr() => all index nodes & table leaf nodes */ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */ - u8 *pEnd; /* End mark for a varint */ - u32 nSize; /* Size value to return */ + u8 *pIter = &pCell[pPage->childPtrSize]; + u32 nSize; #ifdef SQLITE_DEBUG /* The value returned by this function should always be the same as @@ -56347,32 +52181,29 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ ** 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); + btreeParseCellPtr(pPage, pCell, &debuginfo); #endif - assert( pPage->noPayload==0 ); - nSize = *pIter; - if( nSize>=0x80 ){ - pEnd = &pIter[8]; - nSize &= 0x7f; - do{ - nSize = (nSize<<7) | (*++pIter & 0x7f); - }while( *(pIter)>=0x80 && pIterintKey ){ + u8 *pEnd; + if( pPage->hasData ){ + pIter += getVarint32(pIter, nSize); + }else{ + nSize = 0; + } + /* pIter now points at the 64-bit integer key value, a variable length ** integer. The following block moves pIter to point at the first byte ** past the end of the key value. */ pEnd = &pIter[9]; while( (*pIter++)&0x80 && pItermaxLocal ); testcase( nSize==pPage->maxLocal+1 ); - if( nSize<=pPage->maxLocal ){ - nSize += (u32)(pIter - pCell); - if( nSize<4 ) nSize = 4; - }else{ + if( nSize>pPage->maxLocal ){ int minLocal = pPage->minLocal; nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); testcase( nSize==pPage->maxLocal ); @@ -56380,39 +52211,24 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ if( nSize>pPage->maxLocal ){ nSize = minLocal; } - nSize += 4 + (u16)(pIter - pCell); + nSize += 4; } - assert( nSize==debuginfo.nSize || CORRUPT_DB ); + nSize += (u32)(pIter - pCell); + + /* The minimum size of any cell is 4 bytes. */ + if( nSize<4 ){ + nSize = 4; + } + + assert( nSize==debuginfo.nSize ); return (u16)nSize; } -static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){ - u8 *pIter = pCell + 4; /* For looping over bytes of pCell */ - u8 *pEnd; /* End mark for a varint */ - -#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); -#else - UNUSED_PARAMETER(pPage); -#endif - - assert( pPage->childPtrSize==4 ); - pEnd = pIter + 9; - while( (*pIter++)&0x80 && pIterxCellSize(pPage, findCell(pPage, iCell)); + return cellSizePtr(pPage, findCell(pPage, iCell)); } #endif @@ -56426,9 +52242,10 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ CellInfo info; if( *pRC ) return; assert( pCell!=0 ); - pPage->xParseCell(pPage, pCell, &info); - if( info.nLocalintKey?0:info.nKey))==info.nPayload ); + if( info.iOverflow ){ + Pgno ovfl = get4byte(&pCell[info.iOverflow]); ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); } } @@ -56440,15 +52257,10 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ ** end of the page and all free space is collected into one ** big FreeBlk that occurs in between the header and cell ** pointer array and the cell content area. -** -** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a -** b-tree page so that there are no freeblocks or fragment bytes, all -** unused bytes are contained in the unallocated space region, and all -** cells are packed tightly at the end of the page. */ static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ - int pc; /* Address of the i-th cell */ + int pc; /* Address of a i-th cell */ int hdr; /* Offset to the page header */ int size; /* Size of a cell */ int usableSize; /* Number of usable bytes on a page */ @@ -56457,7 +52269,6 @@ static int defragmentPage(MemPage *pPage){ int nCell; /* Number of cells on the page */ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ - unsigned char *src; /* Source of content */ int iCellFirst; /* First allowable cell index */ int iCellLast; /* Last possible cell index */ @@ -56467,13 +52278,15 @@ static int defragmentPage(MemPage *pPage){ assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - temp = 0; - src = data = pPage->aData; + temp = sqlite3PagerTempSpace(pPage->pBt->pPager); + data = pPage->aData; hdr = pPage->hdrOffset; cellOffset = pPage->cellOffset; nCell = pPage->nCell; assert( nCell==get2byte(&data[hdr+3]) ); usableSize = pPage->pBt->usableSize; + cbrk = get2byte(&data[hdr+5]); + memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk); cbrk = usableSize; iCellFirst = cellOffset + 2*nCell; iCellLast = usableSize - 4; @@ -56483,31 +52296,31 @@ static int defragmentPage(MemPage *pPage){ pc = get2byte(pAddr); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); +#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) /* These conditions have already been verified in btreeInitPage() - ** if PRAGMA cell_size_check=ON. + ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined */ if( pciCellLast ){ return SQLITE_CORRUPT_BKPT; } +#endif assert( pc>=iCellFirst && pc<=iCellLast ); - size = pPage->xCellSize(pPage, &src[pc]); + size = cellSizePtr(pPage, &temp[pc]); cbrk -= size; +#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) + if( cbrkusableSize ){ return SQLITE_CORRUPT_BKPT; } +#endif assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); testcase( cbrk+size==usableSize ); testcase( pc+size==usableSize ); + memcpy(&data[cbrk], &temp[pc], size); put2byte(pAddr, cbrk); - if( temp==0 ){ - int x; - if( cbrk==pc ) continue; - temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - x = get2byte(&data[hdr+5]); - memcpy(&temp[x], &data[x], (cbrk+size) - x); - src = temp; - } - memcpy(&data[cbrk], &src[pc], size); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -56522,70 +52335,6 @@ static int defragmentPage(MemPage *pPage){ return SQLITE_OK; } -/* -** Search the free-list on page pPg for space to store a cell nByte bytes in -** size. If one can be found, return a pointer to the space and remove it -** from the free-list. -** -** If no suitable space can be found on the free-list, return NULL. -** -** This function may detect corruption within pPg. If corruption is -** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned. -** -** Slots on the free list that are between 1 and 3 bytes larger than nByte -** will be ignored if adding the extra space to the fragmentation count -** causes the fragmentation count to exceed 60. -*/ -static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ - const int hdr = pPg->hdrOffset; - u8 * const aData = pPg->aData; - int iAddr = hdr + 1; - int pc = get2byte(&aData[iAddr]); - int x; - int usableSize = pPg->pBt->usableSize; - - assert( pc>0 ); - do{ - int size; /* Size of the free slot */ - /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of - ** increasing offset. */ - if( pc>usableSize-4 || pc=0 ){ - testcase( x==4 ); - testcase( x==3 ); - if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_BKPT; - return 0; - }else if( x<4 ){ - /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total - ** number of bytes in fragments may not exceed 60. */ - if( aData[hdr+7]>57 ) return 0; - - /* Remove the slot from the free-list. Update the number of - ** fragmented bytes within the page. */ - memcpy(&aData[iAddr], &aData[pc], 2); - aData[hdr+7] += (u8)x; - }else{ - /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ - put2byte(&aData[pc+2], x); - } - return &aData[pc + x]; - } - iAddr = pc; - pc = get2byte(&aData[pc]); - }while( pc ); - - return 0; -} - /* ** Allocate nByte bytes of space from within the B-Tree page passed ** as the first argument. Write into *pIdx the index into pPage->aData[] @@ -56602,9 +52351,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ + int nFrag; /* Number of fragmented bytes on pPage */ int top; /* First byte of cell content area */ - int rc = SQLITE_OK; /* Integer return code */ int gap; /* First byte of gap between cell pointers and cell content */ + int rc; /* Integer return code */ + int usableSize; /* Usable size of the page */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); @@ -56612,50 +52363,62 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ assert( nByte>=0 ); /* Minimum cell size is 4 */ assert( pPage->nFree>=nByte ); assert( pPage->nOverflow==0 ); - assert( nByte < (int)(pPage->pBt->usableSize-8) ); + usableSize = pPage->pBt->usableSize; + assert( nByte < usableSize-8 ); + nFrag = data[hdr+7]; assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); gap = pPage->cellOffset + 2*pPage->nCell; - assert( gap<=65536 ); - /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size - ** and the reserved space is zero (the usual value for reserved space) - ** then the cell content offset of an empty page wants to be 65536. - ** However, that integer is too large to be stored in a 2-byte unsigned - ** integer, so a value of 0 is used in its place. */ - top = get2byte(&data[hdr+5]); - assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */ - if( gap>top ){ - if( top==0 && pPage->pBt->usableSize==65536 ){ - top = 65536; - }else{ - return SQLITE_CORRUPT_BKPT; - } - } - - /* If there is enough space between gap and top for one more cell pointer - ** array entry offset, and if the freelist is not empty, then search the - ** freelist looking for a free slot big enough to satisfy the request. - */ + top = get2byteNotZero(&data[hdr+5]); + if( gap>top ) return SQLITE_CORRUPT_BKPT; testcase( gap+2==top ); testcase( gap+1==top ); testcase( gap==top ); - if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ - u8 *pSpace = pageFindSlot(pPage, nByte, &rc); - if( pSpace ){ - assert( pSpace>=data && (pSpace - data)<65536 ); - *pIdx = (int)(pSpace - data); - return SQLITE_OK; - }else if( rc ){ - return rc; + + if( nFrag>=60 ){ + /* Always defragment highly fragmented pages */ + rc = defragmentPage(pPage); + if( rc ) return rc; + top = get2byteNotZero(&data[hdr+5]); + }else if( gap+2<=top ){ + /* Search the freelist looking for a free slot big enough to satisfy + ** the request. The allocation is made from the first free slot in + ** the list that is large enough to accommodate it. + */ + int pc, addr; + for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ + int size; /* Size of the free slot */ + if( pc>usableSize-4 || pc=nByte ){ + int x = size - nByte; + testcase( x==4 ); + testcase( x==3 ); + if( x<4 ){ + /* Remove the slot from the free-list. Update the number of + ** fragmented bytes within the page. */ + memcpy(&data[addr], &data[pc], 2); + data[hdr+7] = (u8)(nFrag + x); + }else if( size+pc > usableSize ){ + return SQLITE_CORRUPT_BKPT; + }else{ + /* The slot remains on the free-list. Reduce its size to account + ** for the portion used by the new allocation. */ + put2byte(&data[pc+2], x); + } + *pIdx = pc + x; + return SQLITE_OK; + } } } - /* The request could not be fulfilled using a freelist slot. Check - ** to see if defragmentation is necessary. + /* Check to make sure there is enough space in the gap to satisfy + ** the allocation. If not, defragment. */ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ - assert( pPage->nCell>0 || CORRUPT_DB ); rc = defragmentPage(pPage); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); @@ -56678,101 +52441,90 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ /* ** Return a section of the pPage->aData to the freelist. -** The first byte of the new free block is pPage->aData[iStart] -** and the size of the block is iSize bytes. +** The first byte of the new free block is pPage->aDisk[start] +** and the size of the block is "size" bytes. ** -** Adjacent freeblocks are coalesced. -** -** Note that even though the freeblock list was checked by btreeInitPage(), -** that routine will not detect overlap between cells or freeblocks. Nor -** does it detect cells or freeblocks that encrouch into the reserved bytes -** at the end of the page. So do additional corruption checks inside this -** routine and return SQLITE_CORRUPT if any problems are found. +** Most of the effort here is involved in coalesing adjacent +** free blocks into a single big free block. */ -static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ - u16 iPtr; /* Address of ptr to next freeblock */ - u16 iFreeBlk; /* Address of the next freeblock */ - u8 hdr; /* Page header size. 0 or 100 */ - u8 nFrag = 0; /* Reduction in fragmentation */ - u16 iOrigSize = iSize; /* Original value of iSize */ - u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ - u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ - unsigned char *data = pPage->aData; /* Page content */ +static int freeSpace(MemPage *pPage, int start, int size){ + int addr, pbegin, hdr; + int iLast; /* Largest possible freeblock offset */ + unsigned char *data = pPage->aData; assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); + assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); + assert( (start + size) <= (int)pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( iSize>=4 ); /* Minimum cell size is 4 */ - assert( iStart<=iLast ); + assert( size>=0 ); /* Minimum cell size is 4 */ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ - memset(&data[iStart], 0, iSize); + /* Overwrite deleted information with zeros when the secure_delete + ** option is enabled */ + memset(&data[start], 0, size); } - /* The list of freeblocks must be in ascending order. Find the - ** spot on the list where iStart should be inserted. + /* Add the space back into the linked list of freeblocks. Note that + ** even though the freeblock list was checked by btreeInitPage(), + ** btreeInitPage() did not detect overlapping cells or + ** freeblocks that overlapped cells. Nor does it detect when the + ** cell content area exceeds the value in the page header. If these + ** situations arise, then subsequent insert operations might corrupt + ** the freelist. So we do need to check for corruption while scanning + ** the freelist. */ hdr = pPage->hdrOffset; - iPtr = hdr + 1; - if( data[iPtr+1]==0 && data[iPtr]==0 ){ - iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ - }else{ - while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlkpBt->usableSize - 4; + assert( start<=iLast ); + while( (pbegin = get2byte(&data[addr]))0 ){ + if( pbeginiLast ) return SQLITE_CORRUPT_BKPT; - assert( iFreeBlk>iPtr || iFreeBlk==0 ); - - /* At this point: - ** iFreeBlk: First freeblock after iStart, or zero if none - ** iPtr: The address of a pointer to iFreeBlk - ** - ** Check to see if iFreeBlk should be coalesced onto the end of iStart. - */ - if( iFreeBlk && iEnd+3>=iFreeBlk ){ - nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; - iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); - if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT; - iSize = iEnd - iStart; - iFreeBlk = get2byte(&data[iFreeBlk]); - } - - /* If iPtr is another freeblock (that is, if iPtr is not the freelist - ** pointer in the page header) then check to see if iStart should be - ** coalesced onto the end of iPtr. - */ - if( iPtr>hdr+1 ){ - int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); - if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; - nFrag += iStart - iPtrEnd; - iSize = iEnd - iPtr; - iStart = iPtr; + addr = pbegin; + } + if( pbegin>iLast ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pbegin>addr || pbegin==0 ); + put2byte(&data[addr], start); + put2byte(&data[start], pbegin); + put2byte(&data[start+2], size); + pPage->nFree = pPage->nFree + (u16)size; + + /* Coalesce adjacent free blocks */ + addr = hdr + 1; + while( (pbegin = get2byte(&data[addr]))>0 ){ + int pnext, psize, x; + assert( pbegin>addr ); + assert( pbegin <= (int)pPage->pBt->usableSize-4 ); + pnext = get2byte(&data[pbegin]); + psize = get2byte(&data[pbegin+2]); + if( pbegin + psize + 3 >= pnext && pnext>0 ){ + int frag = pnext - (pbegin+psize); + if( (frag<0) || (frag>(int)data[hdr+7]) ){ + return SQLITE_CORRUPT_BKPT; } + data[hdr+7] -= (u8)frag; + x = get2byte(&data[pnext]); + put2byte(&data[pbegin], x); + x = pnext + get2byte(&data[pnext+2]) - pbegin; + put2byte(&data[pbegin+2], x); + }else{ + addr = pbegin; } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; - data[hdr+7] -= nFrag; } - if( iStart==get2byte(&data[hdr+5]) ){ - /* The new freeblock is at the beginning of the cell content area, - ** so just extend the cell content area rather than create another - ** freelist entry */ - if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT; - put2byte(&data[hdr+1], iFreeBlk); - put2byte(&data[hdr+5], iEnd); - }else{ - /* Insert the new freeblock into the freelist */ - put2byte(&data[iPtr], iStart); - put2byte(&data[iStart], iFreeBlk); - put2byte(&data[iStart+2], iSize); + + /* If the cell content area begins with a freeblock, remove it. */ + if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ + int top; + pbegin = get2byte(&data[hdr+1]); + memcpy(&data[hdr+1], &data[pbegin], 2); + top = get2byte(&data[hdr+5]) + get2byte(&data[pbegin+2]); + put2byte(&data[hdr+5], top); } - pPage->nFree += iOrigSize; + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); return SQLITE_OK; } @@ -56796,44 +52548,18 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); flagByte &= ~PTF_LEAF; pPage->childPtrSize = 4-4*pPage->leaf; - pPage->xCellSize = cellSizePtr; pBt = pPage->pBt; if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ - /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior - ** table b-tree page. */ - assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); - /* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf - ** table b-tree page. */ - assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); pPage->intKey = 1; - if( pPage->leaf ){ - pPage->intKeyLeaf = 1; - pPage->noPayload = 0; - pPage->xParseCell = btreeParseCellPtr; - }else{ - pPage->intKeyLeaf = 0; - pPage->noPayload = 1; - pPage->xCellSize = cellSizePtrNoPayload; - pPage->xParseCell = btreeParseCellPtrNoPayload; - } + pPage->hasData = pPage->leaf; pPage->maxLocal = pBt->maxLeaf; pPage->minLocal = pBt->minLeaf; }else if( flagByte==PTF_ZERODATA ){ - /* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior - ** index b-tree page. */ - assert( (PTF_ZERODATA)==2 ); - /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf - ** index b-tree page. */ - assert( (PTF_ZERODATA|PTF_LEAF)==10 ); pPage->intKey = 0; - pPage->intKeyLeaf = 0; - pPage->noPayload = 0; - pPage->xParseCell = btreeParseCellPtrIndex; + pPage->hasData = 0; pPage->maxLocal = pBt->maxLocal; pPage->minLocal = pBt->minLocal; }else{ - /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is - ** an error. */ return SQLITE_CORRUPT_BKPT; } pPage->max1bytePayload = pBt->max1bytePayload; @@ -56852,7 +52578,6 @@ static int decodeFlags(MemPage *pPage, int flagByte){ static int btreeInitPage(MemPage *pPage){ assert( pPage->pBt!=0 ); - assert( pPage->pBt->db!=0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); @@ -56874,34 +52599,21 @@ static int btreeInitPage(MemPage *pPage){ hdr = pPage->hdrOffset; data = pPage->aData; - /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating - ** the b-tree page type. */ if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); pPage->nOverflow = 0; usableSize = pBt->usableSize; - pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize; + pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; pPage->aDataEnd = &data[usableSize]; pPage->aCellIdx = &data[cellOffset]; - pPage->aDataOfst = &data[pPage->childPtrSize]; - /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates - ** the start of the cell content area. A zero value for this integer is - ** interpreted as 65536. */ top = get2byteNotZero(&data[hdr+5]); - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ return SQLITE_CORRUPT_BKPT; } testcase( pPage->nCell==MX_CELL(pBt) ); - /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only - ** possible for a root page of a table that contains no rows) then the - ** offset to the cell content area will equal the page size minus the - ** bytes of reserved space. */ - assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB ); /* A malformed database page might cause us to read past the end ** of page when parsing a cell. @@ -56912,19 +52624,20 @@ static int btreeInitPage(MemPage *pPage){ */ iCellFirst = cellOffset + 2*pPage->nCell; iCellLast = usableSize - 4; - if( pBt->db->flags & SQLITE_CellSizeCk ){ +#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) + { int i; /* Index into the cell pointer array */ int sz; /* Size of a cell */ if( !pPage->leaf ) iCellLast--; for(i=0; inCell; i++){ - pc = get2byteAligned(&data[cellOffset+i*2]); + pc = get2byte(&data[cellOffset+i*2]); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pciCellLast ){ return SQLITE_CORRUPT_BKPT; } - sz = pPage->xCellSize(pPage, &data[pc]); + sz = cellSizePtr(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ return SQLITE_CORRUPT_BKPT; @@ -56932,21 +52645,15 @@ static int btreeInitPage(MemPage *pPage){ } if( !pPage->leaf ) iCellLast++; } +#endif - /* Compute the total free space on the page - ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the - ** start of the first freeblock on the page, or is zero if there are no - ** freeblocks. */ + /* Compute the total free space on the page */ pc = get2byte(&data[hdr+1]); - nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ + nFree = data[hdr+7] + top; while( pc>0 ){ u16 next, size; if( pciCellLast ){ - /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will - ** always be at least one cell before the first freeblock. - ** - ** Or, the freeblock is off the end of the page - */ + /* Start of free block is off the page */ return SQLITE_CORRUPT_BKPT; } next = get2byte(&data[pc]); @@ -57004,7 +52711,6 @@ static void zeroPage(MemPage *pPage, int flags){ pPage->cellOffset = first; pPage->aDataEnd = &data[pBt->usableSize]; pPage->aCellIdx = &data[first]; - pPage->aDataOfst = &data[pPage->childPtrSize]; pPage->nOverflow = 0; assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); @@ -57019,23 +52725,20 @@ static void zeroPage(MemPage *pPage, int flags){ */ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){ MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( pgno!=pPage->pgno ){ - pPage->aData = sqlite3PagerGetData(pDbPage); - pPage->pDbPage = pDbPage; - pPage->pBt = pBt; - pPage->pgno = pgno; - pPage->hdrOffset = pgno==1 ? 100 : 0; - } - assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; return pPage; } /* ** Get a page from the pager. Initialize the MemPage.pBt and -** MemPage.aData elements if needed. See also: btreeGetUnusedPage(). +** MemPage.aData elements if needed. ** -** If the PAGER_GET_NOCONTENT flag is set, it means that we do not care -** about the content of the page at this time. So do not go to the disk +** If the noContent flag is set, it means that we do not care about +** the content of the page at this time. So do not go to the disk ** to fetch the content. Just fill in the content with zeros for now. ** If in the future we call sqlite3PagerWrite() on this page, that ** means we have started to be concerned about content and the disk @@ -57052,7 +52755,7 @@ static int btreeGetPage( assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY ); assert( sqlite3_mutex_held(pBt->mutex) ); - rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); if( rc ) return rc; *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); return SQLITE_OK; @@ -57083,67 +52786,39 @@ static Pgno btreePagecount(BtShared *pBt){ SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ assert( sqlite3BtreeHoldsMutex(p) ); assert( ((p->pBt->nPage)&0x8000000)==0 ); - return btreePagecount(p->pBt); + return (int)btreePagecount(p->pBt); } /* -** Get a page from the pager and initialize it. +** Get a page from the pager and initialize it. This routine is just a +** convenience wrapper around separate calls to btreeGetPage() and +** btreeInitPage(). ** -** 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 +** If an error occurs, then the value *ppPage is set to 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 bReadonly /* PAGER_GET_READONLY or 0 */ ){ int rc; - DbPage *pDbPage; assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] ); - assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); - assert( pCur==0 || pCur->iPage>0 ); + assert( bReadonly==PAGER_GET_READONLY || bReadonly==0 ); if( pgno>btreePagecount(pBt) ){ rc = SQLITE_CORRUPT_BKPT; - goto getAndInitPage_error; - } - rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); - if( rc ){ - goto getAndInitPage_error; - } - *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - if( (*ppPage)->isInit==0 ){ - btreePageFromDbPage(pDbPage, pgno, pBt); - rc = btreeInitPage(*ppPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - goto getAndInitPage_error; + }else{ + rc = btreeGetPage(pBt, pgno, ppPage, bReadonly); + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ + rc = btreeInitPage(*ppPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } } } - assert( (*ppPage)->pgno==pgno ); - assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); - /* If obtaining a child page for a cursor, we must verify that the page is - ** compatible with the root page. */ - if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ - rc = SQLITE_CORRUPT_BKPT; - releasePage(*ppPage); - goto getAndInitPage_error; - } - return SQLITE_OK; - -getAndInitPage_error: - if( pCur ) pCur->iPage--; testcase( pgno==0 ); assert( pgno!=0 || rc==SQLITE_CORRUPT ); return rc; @@ -57153,49 +52828,18 @@ getAndInitPage_error: ** Release a MemPage. This should be called once for each prior ** call to btreeGetPage. */ -static void releasePageNotNull(MemPage *pPage){ - assert( pPage->aData ); - assert( pPage->pBt ); - assert( pPage->pDbPage!=0 ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnrefNotNull(pPage->pDbPage); -} static void releasePage(MemPage *pPage){ - if( pPage ) releasePageNotNull(pPage); -} - -/* -** Get an unused page. -** -** This works just like btreeGetPage() with the addition: -** -** * If the page is already in use for some other purpose, immediately -** release it and return an SQLITE_CURRUPT error. -** * Make sure the isInit flag is clear -*/ -static int btreeGetUnusedPage( - BtShared *pBt, /* The btree */ - Pgno pgno, /* Number of the page to fetch */ - MemPage **ppPage, /* Return the page in this parameter */ - int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */ -){ - int rc = btreeGetPage(pBt, pgno, ppPage, flags); - if( rc==SQLITE_OK ){ - if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ - releasePage(*ppPage); - *ppPage = 0; - return SQLITE_CORRUPT_BKPT; - } - (*ppPage)->isInit = 0; - }else{ - *ppPage = 0; + if( pPage ){ + assert( pPage->aData ); + assert( pPage->pBt ); + assert( pPage->pDbPage!=0 ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3PagerUnrefNotNull(pPage->pDbPage); } - return rc; } - /* ** During a rollback, when the pager reloads information into the cache ** so that the cache is restored to its original state at the start of @@ -57318,18 +52962,16 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( */ if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ - int nFilename = sqlite3Strlen30(zFilename)+1; int nFullPathname = pVfs->mxPathname+1; - char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); + char *zFullPathname = sqlite3Malloc(nFullPathname); MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - p->sharable = 1; if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } if( isMemdb ){ - memcpy(zFullPathname, zFilename, nFilename); + memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); }else{ rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); @@ -57386,8 +53028,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ - assert( sizeof(i64)==8 ); - assert( sizeof(u64)==8 ); + assert( sizeof(i64)==8 || sizeof(i64)==4 ); + assert( sizeof(u64)==8 || sizeof(u64)==4 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); @@ -57417,9 +53059,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( #ifdef SQLITE_SECURE_DELETE pBt->btsFlags |= BTS_SECURE_DELETE; #endif - /* EVIDENCE-OF: R-51873-39618 The page size for a database file is - ** determined by the 2-byte integer located at an offset of 16 bytes from - ** the beginning of the database file. */ pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16); if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ @@ -57438,9 +53077,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( #endif nReserve = 0; }else{ - /* EVIDENCE-OF: R-37497-42412 The size of the reserved region is - ** determined by the one-byte unsigned integer found at an offset of 20 - ** into the database file header. */ nReserve = zDbHeader[20]; pBt->btsFlags |= BTS_PAGESIZE_FIXED; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -57575,8 +53211,7 @@ static int removeFromSharingList(BtShared *pBt){ /* ** Make sure pBt->pTmpSpace points to an allocation of -** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child -** pointer. +** MX_CELL_SIZE(pBt) bytes. */ static void allocateTempSpace(BtShared *pBt){ if( !pBt->pTmpSpace ){ @@ -57591,16 +53226,8 @@ static void allocateTempSpace(BtShared *pBt){ ** it into a database page. This is not actually a problem, but it ** does cause a valgrind error when the 1 or 2 bytes of unitialized ** data is passed to system call write(). So to avoid this error, - ** zero the first 4 bytes of temp space here. - ** - ** Also: Provide four bytes of initialized space before the - ** beginning of pTmpSpace as an area available to prepend the - ** left-child pointer to the beginning of a cell. - */ - if( pBt->pTmpSpace ){ - memset(pBt->pTmpSpace, 0, 8); - pBt->pTmpSpace += 4; - } + ** zero the first 4 bytes of temp space here. */ + if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4); } } @@ -57608,11 +53235,8 @@ static void allocateTempSpace(BtShared *pBt){ ** Free the pBt->pTmpSpace allocation */ static void freeTempSpace(BtShared *pBt){ - if( pBt->pTmpSpace ){ - pBt->pTmpSpace -= 4; - sqlite3PageFree(pBt->pTmpSpace); - pBt->pTmpSpace = 0; - } + sqlite3PageFree( pBt->pTmpSpace); + pBt->pTmpSpace = 0; } /* @@ -57638,7 +53262,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ - sqlite3BtreeRollback(p, SQLITE_OK, 0); + sqlite3BtreeRollback(p, SQLITE_OK); sqlite3BtreeLeave(p); /* If there are still other outstanding references to the shared-btree @@ -57674,11 +53298,19 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ } /* -** Change the "soft" limit on the number of pages in the cache. -** Unused and unmodified pages will be recycled when the number of -** pages in the cache exceeds this soft limit. But the size of the -** cache is allowed to grow larger than this limit if it contains -** dirty pages or pages still in active use. +** Change the limit on the number of pages allowed in the cache. +** +** The maximum number of cache pages is set to the absolute +** value of mxPage. If mxPage is negative, the pager will +** operate asynchronously - it will not stop to do fsync()s +** to insure data is written to the disk surface before +** continuing. Transactions still work if synchronous is off, +** and the database cannot be corrupted if this program +** crashes. But if the operating system crashes or there is +** an abrupt power failure when synchronous is off, the database +** could be left in an inconsistent and unrecoverable state. +** Synchronous is on by default so database corruption is not +** normally a worry. */ SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; @@ -57689,26 +53321,6 @@ SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ return SQLITE_OK; } -/* -** Change the "spill" limit on the number of pages in the cache. -** If the number of pages exceeds this limit during a write transaction, -** the pager might attempt to "spill" pages to the journal early in -** order to free up memory. -** -** The value returned is the current spill size. If zero is passed -** as an argument, no changes are made to the spill size setting, so -** using mxPage of 0 is a way to query the current spill size. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){ - BtShared *pBt = p->pBt; - int res; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return res; -} - #if SQLITE_MAX_MMAP_SIZE>0 /* ** Change the limit on the amount of the database file that may be @@ -57786,9 +53398,6 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, BtShared *pBt = p->pBt; assert( nReserve>=-1 && nReserve<=255 ); sqlite3BtreeEnter(p); -#if SQLITE_HAS_CODEC - if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve; -#endif if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; @@ -57800,7 +53409,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); - assert( !pBt->pCursor ); + assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = (u32)pageSize; freeTempSpace(pBt); } @@ -57818,6 +53427,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize; } +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) /* ** This function is similar to sqlite3BtreeGetReserve(), except that it ** may only be called if it is guaranteed that the b-tree mutex is already @@ -57830,33 +53440,25 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ ** database handle that owns *p, causing undefined behavior. */ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ - int n; assert( sqlite3_mutex_held(p->pBt->mutex) ); - n = p->pBt->pageSize - p->pBt->usableSize; - return n; + return p->pBt->pageSize - p->pBt->usableSize; } +#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */ +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) /* ** 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 ** sometimes used by extensions. -** -** If SQLITE_HAS_MUTEX is defined then the number returned is the -** greater of the current reserved space and the maximum requested -** reserve space. */ -SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){ +SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree *p){ int n; sqlite3BtreeEnter(p); - n = sqlite3BtreeGetReserveNoMutex(p); -#ifdef SQLITE_HAS_CODEC - if( npBt->optimalReserve ) n = p->pBt->optimalReserve; -#endif + n = p->pBt->pageSize - p->pBt->usableSize; sqlite3BtreeLeave(p); return n; } - /* ** Set the maximum page count for a database if mxPage is positive. ** No changes are made if mxPage is 0 or negative. @@ -57887,6 +53489,7 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ sqlite3BtreeLeave(p); return b; } +#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ /* ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' @@ -57971,9 +53574,6 @@ static int lockBtree(BtShared *pBt){ u32 usableSize; u8 *page1 = pPage1->aData; rc = SQLITE_NOTADB; - /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins - ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d - ** 61 74 20 33 00. */ if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; } @@ -58014,21 +53614,15 @@ static int lockBtree(BtShared *pBt){ } #endif - /* EVIDENCE-OF: R-15465-20813 The maximum and minimum embedded payload - ** fractions and the leaf payload fraction values must be 64, 32, and 32. - ** + /* The maximum embedded fraction must be exactly 25%. And the minimum + ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data. ** The original design allowed these amounts to vary, but as of ** version 3.6.0, we require them to be fixed. */ if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ goto page1_init_failed; } - /* EVIDENCE-OF: R-51873-39618 The page size for a database file is - ** determined by the 2-byte integer located at an offset of 16 bytes from - ** the beginning of the database file. */ pageSize = (page1[16]<<8) | (page1[17]<<16); - /* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two - ** between 512 and 65536 inclusive. */ if( ((pageSize-1)&pageSize)!=0 || pageSize>SQLITE_MAX_PAGE_SIZE || pageSize<=256 @@ -58036,13 +53630,6 @@ static int lockBtree(BtShared *pBt){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); - /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte - ** integer at offset 20 is the number of bytes of space at the end of - ** each page to reserve for extensions. - ** - ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is - ** determined by the one-byte unsigned integer found at an offset of 20 - ** into the database file header. */ usableSize = pageSize - page1[20]; if( (u32)pageSize!=pBt->pageSize ){ /* After reading the first page of the database assuming a page size @@ -58063,9 +53650,6 @@ static int lockBtree(BtShared *pBt){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; } - /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to - ** be less than 480. In other words, if the page size is 512, then the - ** reserved space size cannot exceed 32. */ if( usableSize<480 ){ goto page1_init_failed; } @@ -58120,7 +53704,7 @@ page1_init_failed: ** false then all cursors are counted. ** ** For the purposes of this routine, a cursor is any cursor that -** is capable of reading or writing to the database. Cursors that +** is capable of reading or writing to the databse. Cursors that ** have been tripped into the CURSOR_FAULT state are not counted. */ static int countValidCursors(BtShared *pBt, int wrOnly){ @@ -58146,11 +53730,11 @@ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3_mutex_held(pBt->mutex) ); assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE ); if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ - MemPage *pPage1 = pBt->pPage1; - assert( pPage1->aData ); + assert( pBt->pPage1->aData ); assert( sqlite3PagerRefcount(pBt->pPager)==1 ); + assert( pBt->pPage1->aData ); + releasePage(pBt->pPage1); pBt->pPage1 = 0; - releasePageNotNull(pPage1); } } @@ -58455,22 +54039,20 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ u8 isInitOrig = pPage->isInit; int i; int nCell; - int rc; - rc = btreeInitPage(pPage); - if( rc ) return rc; + btreeInitPage(pPage); nCell = pPage->nCell; for(i=0; ixParseCell(pPage, pCell, &info); - if( info.nLocalaData+pPage->maskPage - && iFrom==get4byte(pCell+info.nSize-4) + btreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow + && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage + && iFrom==get4byte(&pCell[info.iOverflow]) ){ - put4byte(pCell+info.nSize-4, iTo); + put4byte(&pCell[info.iOverflow], iTo); break; } }else{ @@ -58586,7 +54168,7 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); ** calling this function again), return SQLITE_DONE. Or, if an error ** occurs, return some other error code. ** -** More specifically, this function attempts to re-organize the database so +** More specificly, this function attempts to re-organize the database so ** that the last page of the file currently in use is no longer in use. ** ** Parameter nFin is the number of pages that this database would contain @@ -58594,7 +54176,7 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); ** ** If the bCommit parameter is non-zero, this function assumes that the ** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE -** or an error. bCommit is passed true for an auto-vacuum-on-commit +** or an error. bCommit is passed true for an auto-vacuum-on-commmit ** operation, or false for an incremental vacuum. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ @@ -58764,7 +54346,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){ static int autoVacuumCommit(BtShared *pBt){ int rc = SQLITE_OK; Pager *pPager = pBt->pPager; - VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); ) + VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) ); assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); @@ -58948,7 +54530,6 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){ sqlite3BtreeLeave(p); return rc; } - p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ pBt->inTransaction = TRANS_READ; btreeClearHasContent(pBt); } @@ -58974,91 +54555,60 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ /* ** This routine sets the state to CURSOR_FAULT and the error -** code to errCode for every cursor on any BtShared that pBtree -** references. Or if the writeOnly flag is set to 1, then only -** trip write cursors and leave read cursors unchanged. +** code to errCode for every cursor on BtShared that pBtree +** references. ** -** Every cursor is a candidate to be tripped, including cursors -** that belong to other database connections that happen to be -** sharing the cache with pBtree. +** Every cursor is tripped, including cursors that belong +** to other database connections that happen to be sharing +** the cache with pBtree. ** -** This routine gets called when a rollback occurs. If the writeOnly -** flag is true, then only write-cursors need be tripped - read-only -** cursors save their current positions so that they may continue -** following the rollback. Or, if writeOnly is false, all cursors are -** tripped. In general, writeOnly is false if the transaction being -** rolled back modified the database schema. In this case b-tree root -** pages may be moved or deleted from the database altogether, making -** it unsafe for read cursors to continue. -** -** If the writeOnly flag is true and an error is encountered while -** saving the current position of a read-only cursor, all cursors, -** including all read-cursors are tripped. -** -** SQLITE_OK is returned if successful, or if an error occurs while -** saving a cursor position, an SQLite error code. +** This routine gets called when a rollback occurs. +** All cursors using the same cache must be tripped +** to prevent them from trying to use the btree after +** the rollback. The rollback may have deleted tables +** or moved root pages, so it is not sufficient to +** save the state of the cursor. The cursor must be +** invalidated. */ -SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ BtCursor *p; - int rc = SQLITE_OK; - - assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); - if( pBtree ){ - sqlite3BtreeEnter(pBtree); - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - int i; - if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ - if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ - rc = saveCursorPosition(p); - if( rc!=SQLITE_OK ){ - (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); - break; - } - } - }else{ - sqlite3BtreeClearCursor(p); - p->eState = CURSOR_FAULT; - p->skipNext = errCode; - } - for(i=0; i<=p->iPage; i++){ - releasePage(p->apPage[i]); - p->apPage[i] = 0; - } + if( pBtree==0 ) return; + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + int i; + sqlite3BtreeClearCursor(p); + p->eState = CURSOR_FAULT; + p->skipNext = errCode; + for(i=0; i<=p->iPage; i++){ + releasePage(p->apPage[i]); + p->apPage[i] = 0; } - sqlite3BtreeLeave(pBtree); } - return rc; + sqlite3BtreeLeave(pBtree); } /* -** Rollback the transaction in progress. -** -** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). -** Only write cursors are tripped if writeOnly is true but all cursors are -** tripped if writeOnly is false. Any attempt to use -** a tripped cursor will result in an error. +** Rollback the transaction in progress. All cursors will be +** invalided by this operation. Any attempt to use a cursor +** that was open at the beginning of this operation will result +** in an error. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ int rc; BtShared *pBt = p->pBt; MemPage *pPage1; - assert( writeOnly==1 || writeOnly==0 ); - assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK ); sqlite3BtreeEnter(p); if( tripCode==SQLITE_OK ){ rc = tripCode = saveAllCursors(pBt, 0, 0); - if( rc ) writeOnly = 0; }else{ rc = SQLITE_OK; } if( tripCode ){ - int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly); - assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) ); - if( rc2!=SQLITE_OK ) rc = rc2; + sqlite3BtreeTripAllCursors(p, tripCode); } btreeIntegrity(p); @@ -59093,7 +54643,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ } /* -** Start a statement subtransaction. The subtransaction can be rolled +** Start a statement subtransaction. The subtransaction can can be rolled ** back independently of the main transaction. You must start a transaction ** before starting a subtransaction. The subtransaction is ended automatically ** if the main transaction commits or rolls back. @@ -59206,30 +54756,24 @@ static int btreeCursor( BtCursor *pCur /* Space for new cursor */ ){ BtShared *pBt = p->pBt; /* Shared b-tree handle */ - BtCursor *pX; /* Looping over other all cursors */ assert( sqlite3BtreeHoldsMutex(p) ); - assert( wrFlag==0 - || wrFlag==BTREE_WRCSR - || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE) - ); + assert( wrFlag==0 || wrFlag==1 ); /* The following assert statements verify that if this is a sharable ** b-tree database, the connection is holding the required table locks, ** and that no other connection has any open cursor that conflicts with ** this lock. */ - assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) ); + assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) ); assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); /* Assert that the caller has opened the required transaction. */ assert( p->inTrans>TRANS_NONE ); assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); assert( pBt->pPage1 && pBt->pPage1->aData ); - assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); - if( wrFlag ){ - allocateTempSpace(pBt); - if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM; + if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){ + return SQLITE_READONLY; } if( iTable==1 && btreePagecount(pBt)==0 ){ assert( wrFlag==0 ); @@ -59243,17 +54787,12 @@ static int btreeCursor( pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; - pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; - /* If there are two or more cursors on the same btree, then all such - ** cursors *must* have the BTCF_Multiple flag set. */ - for(pX=pBt->pCursor; pX; pX=pX->pNext){ - if( pX->pgnoRoot==(Pgno)iTable ){ - pX->curFlags |= BTCF_Multiple; - pCur->curFlags |= BTCF_Multiple; - } - } + assert( wrFlag==0 || wrFlag==BTCF_WriteFlag ); + pCur->curFlags = wrFlag; pCur->pNext = pBt->pCursor; + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur; + } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; return SQLITE_OK; @@ -59266,13 +54805,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursor( BtCursor *pCur /* Write new cursor here */ ){ int rc; - if( iTable<1 ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - sqlite3BtreeEnter(p); - rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); - sqlite3BtreeLeave(p); - } + sqlite3BtreeEnter(p); + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); + sqlite3BtreeLeave(p); return rc; } @@ -59311,24 +54846,19 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBt; sqlite3BtreeEnter(pBtree); sqlite3BtreeClearCursor(pCur); - assert( pBt->pCursor!=0 ); - if( pBt->pCursor==pCur ){ - pBt->pCursor = pCur->pNext; + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; }else{ - BtCursor *pPrev = pBt->pCursor; - do{ - if( pPrev->pNext==pCur ){ - pPrev->pNext = pCur->pNext; - break; - } - pPrev = pPrev->pNext; - }while( ALWAYS(pPrev) ); + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; } for(i=0; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); } unlockBtreeIfUnused(pBt); - sqlite3_free(pCur->aOverflow); + sqlite3DbFree(pBtree->db, pCur->aOverflow); /* sqlite3_free(pCur); */ sqlite3BtreeLeave(pBtree); } @@ -59342,6 +54872,13 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ ** ** BtCursor.info is a cache of the information in the current cell. ** Using this cache reduces the number of calls to btreeParseCell(). +** +** 2007-06-25: There is a bug in some versions of MSVC that cause the +** compiler to crash when getCellInfo() is implemented as a macro. +** But there is a measureable speed advantage to using the macro on gcc +** (when less compiler optimizations like -Os or -O0 are used and the +** compiler is not doing agressive inlining.) So we use a real function +** for MSVC and a macro for everything else. Ticket #2457. */ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ @@ -59354,15 +54891,28 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ #else #define assertCellInfo(x) #endif -static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ - if( pCur->info.nSize==0 ){ - int iPage = pCur->iPage; - pCur->curFlags |= BTCF_ValidNKey; - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); - }else{ - assertCellInfo(pCur); +#ifdef _MSC_VER + /* Use a real function in MSVC to work around bugs in that compiler. */ + static void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ + int iPage = pCur->iPage; + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); + pCur->curFlags |= BTCF_ValidNKey; + }else{ + assertCellInfo(pCur); + } } -} +#else /* if not _MSC_VER */ + /* Use a macro in all other compilers so that the function is inlined */ +#define getCellInfo(pCur) \ + if( pCur->info.nSize==0 ){ \ + int iPage = pCur->iPage; \ + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ + pCur->curFlags |= BTCF_ValidNKey; \ + }else{ \ + assertCellInfo(pCur); \ + } +#endif /* _MSC_VER */ #ifndef NDEBUG /* The next routine used only within assert() statements */ /* @@ -59389,9 +54939,13 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ */ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - getCellInfo(pCur); - *pSize = pCur->info.nKey; + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState!=CURSOR_VALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } return SQLITE_OK; } @@ -59410,11 +54964,8 @@ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 ); - assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); getCellInfo(pCur); - *pSize = pCur->info.nPayload; + *pSize = pCur->info.nData; return SQLITE_OK; } @@ -59543,7 +55094,7 @@ static int copyPayload( ** ** If the current cursor entry uses one or more overflow pages and the ** eOp argument is not 2, this function may allocate space for and lazily -** populates the overflow page-list cache array (BtCursor.aOverflow). +** popluates the overflow page-list cache array (BtCursor.aOverflow). ** Subsequent calls use this cache to make seeking to the supplied offset ** more efficient. ** @@ -59565,28 +55116,30 @@ static int accessPayload( ){ unsigned char *aPayload; int rc = SQLITE_OK; + u32 nKey; int iIdx = 0; MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ #ifdef SQLITE_DIRECT_OVERFLOW_READ - unsigned char * const pBufStart = pBuf; - int bEnd; /* True if reading to end of data */ + int bEnd; /* True if reading to end of data */ #endif assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->aiIdx[pCur->iPage]nCell ); assert( cursorHoldsMutex(pCur) ); - assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */ + assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */ getCellInfo(pCur); - aPayload = pCur->info.pPayload; + aPayload = pCur->info.pCell + pCur->info.nHeader; + nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); #ifdef SQLITE_DIRECT_OVERFLOW_READ - bEnd = offset+amt==pCur->info.nPayload; + bEnd = (offset+amt==nKey+pCur->info.nData); #endif - assert( offset+amt <= pCur->info.nPayload ); - if( &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){ + if( NEVER(offset+amt > nKey+pCur->info.nData) + || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] + ){ /* Trying to read or write past the end of the data is an error */ return SQLITE_CORRUPT_BKPT; } @@ -59605,7 +55158,6 @@ static int accessPayload( offset -= pCur->info.nLocal; } - if( rc==SQLITE_OK && amt>0 ){ const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ Pgno nextPage; @@ -59623,8 +55175,8 @@ static int accessPayload( if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; if( nOvfl>pCur->nOvflAlloc ){ - Pgno *aNew = (Pgno*)sqlite3Realloc( - pCur->aOverflow, nOvfl*2*sizeof(Pgno) + Pgno *aNew = (Pgno*)sqlite3DbRealloc( + pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ rc = SQLITE_NOMEM; @@ -59643,9 +55195,7 @@ static int accessPayload( ** entry for the first required overflow page is valid, skip ** directly to it. */ - if( (pCur->curFlags & BTCF_ValidOvfl)!=0 - && pCur->aOverflow[offset/ovflSize] - ){ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){ iIdx = (offset/ovflSize); nextPage = pCur->aOverflow[iIdx]; offset = (offset%ovflSize); @@ -59655,9 +55205,7 @@ static int accessPayload( /* If required, populate the overflow page-list cache. */ if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){ - assert( pCur->aOverflow[iIdx]==0 - || pCur->aOverflow[iIdx]==nextPage - || CORRUPT_DB ); + assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); pCur->aOverflow[iIdx] = nextPage; } @@ -59673,7 +55221,6 @@ static int accessPayload( */ assert( eOp!=2 ); assert( pCur->curFlags & BTCF_ValidOvfl ); - assert( pCur->pBtree->db==pBt->db ); if( pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; }else{ @@ -59701,7 +55248,6 @@ static int accessPayload( ** 4) there is no open write-transaction, and ** 5) the database is not a WAL database, ** 6) all data from the page is being read. - ** 7) at least 4 bytes have already been read into the output buffer ** ** then data can be read directly from the database file into the ** output buffer, bypassing the page-cache altogether. This speeds @@ -59713,11 +55259,9 @@ static int accessPayload( && pBt->inTransaction==TRANS_READ /* (4) */ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ && pBt->pPage1->aData[19]==0x01 /* (5) */ - && &pBuf[-4]>=pBufStart /* (7) */ ){ u8 aSave[4]; u8 *aWrite = &pBuf[-4]; - assert( aWrite>=pBufStart ); /* hence (7) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); nextPage = get4byte(aWrite); @@ -59727,7 +55271,7 @@ static int accessPayload( { DbPage *pDbPage; - rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage, + rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage, ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ @@ -59752,7 +55296,7 @@ static int accessPayload( /* ** Read part of the key associated with cursor pCur. Exactly -** "amt" bytes will be transferred into pBuf[]. The transfer +** "amt" bytes will be transfered into pBuf[]. The transfer ** begins at "offset". ** ** The caller must ensure that pCur is pointing to a valid row @@ -59822,19 +55366,14 @@ static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 *pAmt /* Write the number of available bytes here */ ){ - u32 amt; assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); - assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); - assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); - amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); - if( pCur->info.nLocalinfo.nLocal; - *pAmt = amt; - return (void*)pCur->info.pPayload; + *pAmt = pCur->info.nLocal; + return (void*)(pCur->info.pCell + pCur->info.nHeader); } @@ -59870,6 +55409,9 @@ SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ ** vice-versa). */ static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; + int i = pCur->iPage; + MemPage *pNewPage; BtShared *pBt = pCur->pBt; assert( cursorHoldsMutex(pCur) ); @@ -59879,15 +55421,22 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ return SQLITE_CORRUPT_BKPT; } + rc = getAndInitPage(pBt, newPgno, &pNewPage, + (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0); + if( rc ) return rc; + pCur->apPage[i+1] = pNewPage; + pCur->aiIdx[i+1] = 0; + pCur->iPage++; + pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - pCur->iPage++; - pCur->aiIdx[pCur->iPage] = 0; - return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], - pCur, pCur->curPagerFlags); + if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; } -#if SQLITE_DEBUG +#if 0 /* ** Page pParent is an internal (non-leaf) tree page. This function ** asserts that page number iChild is the left-child if the iIdx'th @@ -59896,8 +55445,6 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ ** the page. */ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ - if( CORRUPT_DB ) return; /* The conditions tested below might not be true - ** in a corrupt database */ assert( iIdx<=pParent->nCell ); if( iIdx==pParent->nCell ){ assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); @@ -59922,15 +55469,25 @@ static void moveToParent(BtCursor *pCur){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); assert( pCur->apPage[pCur->iPage] ); + + /* UPDATE: It is actually possible for the condition tested by the assert + ** below to be untrue if the database file is corrupt. This can occur if + ** one cursor has modified page pParent while a reference to it is held + ** by a second cursor. Which can only happen if a single page is linked + ** into more than one b-tree structure in a corrupt database. */ +#if 0 assertParentIndex( pCur->apPage[pCur->iPage-1], pCur->aiIdx[pCur->iPage-1], pCur->apPage[pCur->iPage]->pgno ); +#endif testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); + + releasePage(pCur->apPage[pCur->iPage]); + pCur->iPage--; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - releasePageNotNull(pCur->apPage[pCur->iPage--]); } /* @@ -59971,23 +55528,18 @@ static int moveToRoot(BtCursor *pCur){ } if( pCur->iPage>=0 ){ - while( pCur->iPage ){ - assert( pCur->apPage[pCur->iPage]!=0 ); - releasePageNotNull(pCur->apPage[pCur->iPage--]); - } + while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]); }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ - assert( pCur->iPage==(-1) ); rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], - 0, pCur->curPagerFlags); + (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } pCur->iPage = 0; - pCur->curIntKey = pCur->apPage[0]->intKey; } pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); @@ -60064,16 +55616,17 @@ static int moveToRightmost(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->aiIdx[pCur->iPage] = pPage->nCell; rc = moveToChild(pCur, pgno); - if( rc ) return rc; } - pCur->aiIdx[pCur->iPage] = pPage->nCell-1; - assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & BTCF_ValidNKey)==0 ); - return SQLITE_OK; + if( rc==SQLITE_OK ){ + pCur->aiIdx[pCur->iPage] = pPage->nCell-1; + pCur->info.nSize = 0; + pCur->curFlags &= ~BTCF_ValidNKey; + } + return rc; } /* Move the cursor to the first entry in the table. Return SQLITE_OK @@ -60171,8 +55724,6 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ ** *pRes>0 The cursor is left pointing at an entry that ** is larger than intKey/pIdxKey. ** -** For index tables, the pIdxKey->eqSeen field is set to 1 if there -** exists an entry in the table that exactly matches pIdxKey. */ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( BtCursor *pCur, /* The cursor to be moved */ @@ -60192,7 +55743,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 - && pCur->curIntKey + && pCur->apPage[0]->intKey ){ if( pCur->info.nKey==intKey ){ *pRes = 0; @@ -60206,7 +55757,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( pIdxKey ){ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); - pIdxKey->errCode = 0; + pIdxKey->isCorrupt = 0; assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1 @@ -60227,8 +55778,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); return SQLITE_OK; } - assert( pCur->apPage[0]->intKey==pCur->curIntKey ); - assert( pCur->curIntKey || pIdxKey ); + assert( pCur->apPage[0]->intKey || pIdxKey ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; @@ -60251,8 +55801,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( xRecordCompare==0 ){ for(;;){ i64 nCellKey; - pCell = findCellPastPtr(pPage, idx); - if( pPage->intKeyLeaf ){ + pCell = findCell(pPage, idx) + pPage->childPtrSize; + if( pPage->hasData ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; } @@ -60283,8 +55833,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( } }else{ for(;;){ - int nCell; /* Size of the pCell cell in bytes */ - pCell = findCellPastPtr(pPage, idx); + int nCell; + pCell = findCell(pPage, idx) + pPage->childPtrSize; /* The maximum supported page-size is 65536 bytes. This means that ** the maximum number of record bytes stored on an index B-Tree @@ -60300,37 +55850,24 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated ** and accessPayload() used to retrieve the record into the - ** buffer before VdbeRecordCompare() can be called. - ** - ** If the record is corrupt, the xRecordCompare routine may read - ** up to two varints past the end of the buffer. An extra 18 - ** bytes of padding is allocated at the end of the buffer in - ** case this happens. */ + ** buffer before VdbeRecordCompare() can be called. */ void *pCellKey; u8 * const pCellBody = pCell - pPage->childPtrSize; - pPage->xParseCell(pPage, pCellBody, &pCur->info); + btreeParseCellPtr(pPage, pCellBody, &pCur->info); nCell = (int)pCur->info.nKey; - testcase( nCell<0 ); /* True if key size is 2^32 or more */ - testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */ - testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ - testcase( nCell==2 ); /* Minimum legal index key size */ - if( nCell<2 ){ - rc = SQLITE_CORRUPT_BKPT; - goto moveto_finish; - } - pCellKey = sqlite3Malloc( nCell+18 ); + pCellKey = sqlite3Malloc( nCell ); if( pCellKey==0 ){ rc = SQLITE_NOMEM; goto moveto_finish; @@ -60341,13 +55878,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = xRecordCompare(nCell, pCellKey, pIdxKey); + c = xRecordCompare(nCell, pCellKey, pIdxKey, 0); sqlite3_free(pCellKey); } - assert( - (pIdxKey->errCode!=SQLITE_CORRUPT || c==0) - && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed) - ); + assert( pIdxKey->isCorrupt==0 || c==0 ); if( c<0 ){ lwr = idx+1; }else if( c>0 ){ @@ -60357,7 +55891,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( *pRes = 0; rc = SQLITE_OK; pCur->aiIdx[pCur->iPage] = (u16)idx; - if( pIdxKey->errCode ) rc = SQLITE_CORRUPT; + if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT; goto moveto_finish; } if( lwr>upr ) break; @@ -60412,12 +55946,6 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. ** -** The main entry point is sqlite3BtreeNext(). That routine is optimized -** for the common case of merely incrementing the cell counter BtCursor.aiIdx -** to the next cell on the current page. The (slower) btreeNext() helper -** routine is called when it is necessary to move to a different page or -** to restore the cursor. -** ** The calling function will set *pRes to 0 or 1. The initial *pRes value ** will be 1 if the cursor being stepped corresponds to an SQL index and ** if this routine could have been skipped if that SQL index had been @@ -60427,18 +55955,20 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ ** SQLite btree implementation does not. (Note that the comdb2 btree ** implementation does use this hint, however.) */ -static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; int idx; MemPage *pPage; assert( cursorHoldsMutex(pCur) ); + assert( pRes!=0 ); + assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - assert( *pRes==0 ); if( pCur->eState!=CURSOR_VALID ){ - assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); + invalidateOverflowCache(pCur); rc = restoreCursorPosition(pCur); if( rc!=SQLITE_OK ){ + *pRes = 0; return rc; } if( CURSOR_INVALID==pCur->eState ){ @@ -60450,6 +55980,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ pCur->eState = CURSOR_VALID; if( pCur->skipNext>0 ){ pCur->skipNext = 0; + *pRes = 0; return SQLITE_OK; } pCur->skipNext = 0; @@ -60467,11 +55998,18 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ ** page into more than one b-tree structure. */ testcase( idx>pPage->nCell ); + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); if( idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); - if( rc ) return rc; - return moveToLeftmost(pCur); + if( rc ){ + *pRes = 0; + return rc; + } + rc = moveToLeftmost(pCur); + *pRes = 0; + return rc; } do{ if( pCur->iPage==0 ){ @@ -60482,52 +56020,29 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ moveToParent(pCur); pPage = pCur->apPage[pCur->iPage]; }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); + *pRes = 0; if( pPage->intKey ){ - return sqlite3BtreeNext(pCur, pRes); + rc = sqlite3BtreeNext(pCur, pRes); }else{ - return SQLITE_OK; + rc = SQLITE_OK; } + return rc; } - if( pPage->leaf ){ - return SQLITE_OK; - }else{ - return moveToLeftmost(pCur); - } -} -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ - MemPage *pPage; - assert( cursorHoldsMutex(pCur) ); - assert( pRes!=0 ); - assert( *pRes==0 || *pRes==1 ); - assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - pCur->info.nSize = 0; - pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); *pRes = 0; - if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes); - pPage = pCur->apPage[pCur->iPage]; - if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){ - pCur->aiIdx[pCur->iPage]--; - return btreeNext(pCur, pRes); - } if( pPage->leaf ){ return SQLITE_OK; - }else{ - return moveToLeftmost(pCur); } + rc = moveToLeftmost(pCur); + return rc; } + /* ** Step the cursor to the back to the previous entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. ** -** The main entry point is sqlite3BtreePrevious(). That routine is optimized -** for the common case of merely decrementing the cell counter BtCursor.aiIdx -** to the previous cell on the current page. The (slower) btreePrevious() -** helper routine is called when it is necessary to move to a different page -** or to restore the cursor. -** ** The calling function will set *pRes to 0 or 1. The initial *pRes value ** will be 1 if the cursor being stepped corresponds to an SQL index and ** if this routine could have been skipped if that SQL index had been @@ -60537,20 +56052,22 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ ** SQLite btree implementation does not. (Note that the comdb2 btree ** implementation does use this hint, however.) */ -static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; assert( cursorHoldsMutex(pCur) ); assert( pRes!=0 ); - assert( *pRes==0 ); + assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 ); - assert( pCur->info.nSize==0 ); + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl); if( pCur->eState!=CURSOR_VALID ){ - rc = restoreCursorPosition(pCur); - if( rc!=SQLITE_OK ){ - return rc; + if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){ + rc = btreeRestoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + *pRes = 0; + return rc; + } } if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; @@ -60561,6 +56078,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ pCur->eState = CURSOR_VALID; if( pCur->skipNext<0 ){ pCur->skipNext = 0; + *pRes = 0; return SQLITE_OK; } pCur->skipNext = 0; @@ -60572,7 +56090,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ if( !pPage->leaf ){ int idx = pCur->aiIdx[pCur->iPage]; rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); - if( rc ) return rc; + if( rc ){ + *pRes = 0; + return rc; + } rc = moveToRightmost(pCur); }else{ while( pCur->aiIdx[pCur->iPage]==0 ){ @@ -60583,8 +56104,8 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ } moveToParent(pCur); } - assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 ); + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); pCur->aiIdx[pCur->iPage]--; pPage = pCur->apPage[pCur->iPage]; @@ -60594,24 +56115,8 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ rc = SQLITE_OK; } } - return rc; -} -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ - assert( cursorHoldsMutex(pCur) ); - assert( pRes!=0 ); - assert( *pRes==0 || *pRes==1 ); - assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); *pRes = 0; - pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey); - pCur->info.nSize = 0; - if( pCur->eState!=CURSOR_VALID - || pCur->aiIdx[pCur->iPage]==0 - || pCur->apPage[pCur->iPage]->leaf==0 - ){ - return btreePrevious(pCur, pRes); - } - pCur->aiIdx[pCur->iPage]--; - return SQLITE_OK; + return rc; } /* @@ -60623,7 +56128,8 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ ** sqlite3PagerUnref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates -** an error. *ppPage is set to NULL in the event of an error. +** an error. *ppPage and *pPgno are undefined in the event of an error. +** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. ** ** If the "nearby" parameter is not 0, then an effort is made to ** locate a page close to the page number "nearby". This can be used in an @@ -60655,8 +56161,6 @@ static int allocateBtreePage( assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); pPage1 = pBt->pPage1; mxPage = btreePagecount(pBt); - /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 - ** stores stores the total number of pages on the freelist. */ n = get4byte(&pPage1->aData[36]); testcase( n==mxPage-1 ); if( n>=mxPage ){ @@ -60666,7 +56170,6 @@ static int allocateBtreePage( /* There are pages on the freelist. Reuse one of those pages. */ Pgno iTrunk; u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ - u32 nSearch = 0; /* Count of the number of search attempts */ /* If eMode==BTALLOC_EXACT and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then @@ -60704,21 +56207,15 @@ static int allocateBtreePage( do { pPrevTrunk = pTrunk; if( pPrevTrunk ){ - /* EVIDENCE-OF: R-01506-11053 The first integer on a freelist trunk page - ** is the page number of the next freelist trunk page in the list or - ** zero if this is the last freelist trunk page. */ iTrunk = get4byte(&pPrevTrunk->aData[0]); }else{ - /* EVIDENCE-OF: R-59841-13798 The 4-byte big-endian integer at offset 32 - ** stores the page number of the first page of the freelist, or zero if - ** the freelist is empty. */ iTrunk = get4byte(&pPage1->aData[32]); } testcase( iTrunk==mxPage ); - if( iTrunk>mxPage || nSearch++ > n ){ + if( iTrunk>mxPage ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); + rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); } if( rc ){ pTrunk = 0; @@ -60726,9 +56223,8 @@ static int allocateBtreePage( } assert( pTrunk!=0 ); assert( pTrunk->aData!=0 ); - /* EVIDENCE-OF: R-13523-04394 The second integer on a freelist trunk page - ** is the number of leaf page pointers to follow. */ - k = get4byte(&pTrunk->aData[4]); + + k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */ if( k==0 && !searchList ){ /* The trunk has no leaves and the list is not being searched. ** So extract the trunk page itself and use it as the newly @@ -60783,7 +56279,7 @@ static int allocateBtreePage( goto end_allocate_page; } testcase( iNewTrunk==mxPage ); - rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0); + rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); if( rc!=SQLITE_OK ){ goto end_allocate_page; } @@ -60862,13 +56358,12 @@ static int allocateBtreePage( memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } put4byte(&aData[4], k-1); - noContent = !btreeGetHasContent(pBt, *pPgno)? PAGER_GET_NOCONTENT : 0; - rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, noContent); + noContent = !btreeGetHasContent(pBt, *pPgno) ? PAGER_GET_NOCONTENT : 0; + rc = btreeGetPage(pBt, *pPgno, ppPage, noContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); - *ppPage = 0; } } searchList = 0; @@ -60896,7 +56391,7 @@ static int allocateBtreePage( ** here are confined to those pages that lie between the end of the ** database image and the end of the database file. */ - int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate))? PAGER_GET_NOCONTENT:0; + int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)) ? PAGER_GET_NOCONTENT : 0; rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc ) return rc; @@ -60912,7 +56407,7 @@ static int allocateBtreePage( MemPage *pPg = 0; TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent); + rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); @@ -60926,12 +56421,11 @@ static int allocateBtreePage( *pPgno = pBt->nPage; assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent); + rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); - *ppPage = 0; } TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } @@ -60941,8 +56435,17 @@ static int allocateBtreePage( end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); - assert( rc!=SQLITE_OK || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 ); - assert( rc!=SQLITE_OK || (*ppPage)->isInit==0 ); + if( rc==SQLITE_OK ){ + if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ + releasePage(*ppPage); + *ppPage = 0; + return SQLITE_CORRUPT_BKPT; + } + (*ppPage)->isInit = 0; + }else{ + *ppPage = 0; + } + assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) ); return rc; } @@ -60967,10 +56470,9 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ int nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); - assert( CORRUPT_DB || iPage>1 ); + assert( iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); - if( iPage<2 ) return SQLITE_CORRUPT_BKPT; if( pMemPage ){ pPage = pMemPage; sqlite3PagerRef(pPage->pDbPage); @@ -61040,11 +56542,6 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ ** for now. At some point in the future (once everyone has upgraded ** to 3.6.0 or later) we should consider fixing the conditional above ** to read "usableSize/4-2" instead of "usableSize/4-8". - ** - ** EVIDENCE-OF: R-19920-11576 However, newer versions of SQLite still - ** avoid using the last six entries in the freelist trunk page array in - ** order that database files created by newer versions of SQLite can be - ** read by older versions of SQLite. */ rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc==SQLITE_OK ){ @@ -61093,15 +56590,9 @@ static void freePage(MemPage *pPage, int *pRC){ } /* -** Free any overflow pages associated with the given Cell. Write the -** local Cell size (the number of bytes on the original page, omitting -** overflow) into *pnSize. +** Free any overflow pages associated with the given Cell. */ -static int clearCell( - MemPage *pPage, /* The page that contains the Cell */ - unsigned char *pCell, /* First byte of the Cell */ - u16 *pnSize /* Write the size of the Cell here */ -){ +static int clearCell(MemPage *pPage, unsigned char *pCell){ BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; @@ -61110,21 +56601,18 @@ static int clearCell( u32 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->xParseCell(pPage, pCell, &info); - *pnSize = info.nSize; - if( info.nLocal==info.nPayload ){ + btreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } - if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){ + if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){ return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ } - ovflPgno = get4byte(pCell + info.nSize - 4); + ovflPgno = get4byte(&pCell[info.iOverflow]); assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; - assert( nOvfl>0 || - (CORRUPT_DB && (info.nPayload + ovflPageSize)0 ); while( nOvfl-- ){ Pgno iNext = 0; MemPage *pOvfl = 0; @@ -61197,6 +56685,7 @@ static int fillInCell( BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; + CellInfo info; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); @@ -61206,71 +56695,40 @@ static int fillInCell( || sqlite3PagerIswriteable(pPage->pDbPage) ); /* Fill in the header. */ - nHeader = pPage->childPtrSize; - nPayload = nData + nZero; - if( pPage->intKeyLeaf ){ - nHeader += putVarint32(&pCell[nHeader], nPayload); + nHeader = 0; + if( !pPage->leaf ){ + nHeader += 4; + } + if( pPage->hasData ){ + nHeader += putVarint32(&pCell[nHeader], nData+nZero); }else{ - assert( nData==0 ); - assert( nZero==0 ); + nData = nZero = 0; } nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); + btreeParseCellPtr(pPage, pCell, &info); + assert( info.nHeader==nHeader ); + assert( info.nKey==nKey ); + assert( info.nData==(u32)(nData+nZero) ); - /* Fill in the payload size */ + /* Fill in the payload */ + nPayload = nData + nZero; if( pPage->intKey ){ pSrc = pData; nSrc = nData; nData = 0; }else{ - assert( nKey<=0x7fffffff && pKey!=0 ); - nPayload = (int)nKey; + if( NEVER(nKey>0x7fffffff || pKey==0) ){ + return SQLITE_CORRUPT_BKPT; + } + nPayload += (int)nKey; pSrc = pKey; nSrc = (int)nKey; } - if( nPayload<=pPage->maxLocal ){ - n = nHeader + nPayload; - testcase( n==3 ); - testcase( n==4 ); - if( n<4 ) n = 4; - *pnSize = n; - spaceLeft = nPayload; - pPrior = pCell; - }else{ - int mn = pPage->minLocal; - n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); - testcase( n==pPage->maxLocal ); - testcase( n==pPage->maxLocal+1 ); - if( n > pPage->maxLocal ) n = mn; - spaceLeft = n; - *pnSize = n + nHeader + 4; - pPrior = &pCell[nHeader+n]; - } + *pnSize = info.nSize; + spaceLeft = info.nLocal; pPayload = &pCell[nHeader]; + pPrior = &pCell[info.iOverflow]; - /* At this point variables should be set as follows: - ** - ** nPayload Total payload size in bytes - ** pPayload Begin writing payload here - ** spaceLeft Space available at pPayload. If nPayload>spaceLeft, - ** that means content must spill into overflow pages. - ** *pnSize Size of the local cell (not counting overflow pages) - ** pPrior Where to write the pgno of the first overflow page - ** - ** Use a call to btreeParseCellPtr() to verify that the values above - ** were computed correctly. - */ -#if SQLITE_DEBUG - { - CellInfo info; - pPage->xParseCell(pPage, pCell, &info); - assert( nHeader=(int)(info.pPayload - pCell) ); - assert( info.nKey==nKey ); - assert( *pnSize == info.nSize ); - assert( spaceLeft == info.nLocal ); - } -#endif - - /* Write the payload into the local Cell and any extra into overflow pages */ while( nPayload>0 ){ if( spaceLeft==0 ){ #ifndef SQLITE_OMIT_AUTOVACUUM @@ -61376,7 +56834,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ if( *pRC ) return; assert( idx>=0 && idxnCell ); - assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); + assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; @@ -61395,17 +56853,9 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ return; } pPage->nCell--; - if( pPage->nCell==0 ){ - memset(&data[hdr+1], 0, 4); - data[hdr+7] = 0; - put2byte(&data[hdr+5], pPage->pBt->usableSize); - pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset - - pPage->childPtrSize - 8; - }else{ - memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); - put2byte(&data[hdr+3], pPage->nCell); - pPage->nFree += 2; - } + memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); + put2byte(&data[hdr+3], pPage->nCell); + pPage->nFree += 2; } /* @@ -61419,6 +56869,11 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. +** +** If nSkip is non-zero, then do not copy the first nSkip bytes of the +** cell. The caller will overwrite them after this function returns. If +** nSkip is non-zero, then pCell may not point to an invalid memory location +** (but pCell+nSkip is always valid). */ static void insertCell( MemPage *pPage, /* Page into which we are copying */ @@ -61431,14 +56886,16 @@ static void insertCell( ){ int idx = 0; /* Where to write new cell content in data[] */ int j; /* Loop counter */ + int end; /* First byte past the last cell pointer in data[] */ + int ins; /* Index in data[] where new cell pointer is inserted */ + int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ - u8 *pIns; /* The point in pPage->aCellIdx[] where no cell inserted */ + int nSkip = (iChild ? 4 : 0); if( *pRC ) return; 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->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 ); assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); @@ -61447,10 +56904,10 @@ static void insertCell( ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size ** might be less than 8 (leaf-size + pointer) on the interior node. Hence ** the term after the || in the following assert(). */ - assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) ); + assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ - memcpy(pTemp, pCell, sz); + memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); pCell = pTemp; } if( iChild ){ @@ -61460,14 +56917,6 @@ static void insertCell( assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); 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( rc!=SQLITE_OK ){ @@ -61476,26 +56925,24 @@ static void insertCell( } assert( sqlite3PagerIswriteable(pPage->pDbPage) ); data = pPage->aData; - assert( &data[pPage->cellOffset]==pPage->aCellIdx ); + cellOffset = pPage->cellOffset; + end = cellOffset + 2*pPage->nCell; + ins = cellOffset + 2*i; rc = allocateSpace(pPage, sz, &idx); if( rc ){ *pRC = rc; return; } - /* The allocateSpace() routine guarantees the following properties - ** if it returns successfully */ - assert( idx >= 0 ); - assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); + /* The allocateSpace() routine guarantees the following two properties + ** if it returns success */ + assert( idx >= end+2 ); assert( idx+sz <= (int)pPage->pBt->usableSize ); + pPage->nCell++; pPage->nFree -= (u16)(2 + sz); - memcpy(&data[idx], pCell, sz); + memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); if( iChild ){ put4byte(&data[idx], iChild); } - pIns = pPage->aCellIdx + i*2; - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); - put2byte(pIns, idx); - pPage->nCell++; - /* increment the cell count */ - if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell ); + memmove(&data[ins+2], &data[ins], end-ins); + put2byte(&data[ins], idx); + put2byte(&data[pPage->hdrOffset+3], pPage->nCell); #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ /* The cell may contain a pointer to an overflow page. If so, write @@ -61508,328 +56955,45 @@ static void insertCell( } /* -** A CellArray object contains a cache of pointers and sizes for a -** consecutive sequence of cells that might be held multiple pages. +** Add a list of cells to a page. The page should be initially empty. +** The cells are guaranteed to fit on the page. */ -typedef struct CellArray CellArray; -struct CellArray { - int nCell; /* Number of cells in apCell[] */ - MemPage *pRef; /* Reference page */ - u8 **apCell; /* All cells begin balanced */ - u16 *szCell; /* Local size of all cells in apCell[] */ -}; - -/* -** Make sure the cell sizes at idx, idx+1, ..., idx+N-1 have been -** computed. -*/ -static void populateCellCache(CellArray *p, int idx, int N){ - assert( idx>=0 && idx+N<=p->nCell ); - while( N>0 ){ - assert( p->apCell[idx]!=0 ); - if( p->szCell[idx]==0 ){ - p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]); - }else{ - assert( CORRUPT_DB || - p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) ); - } - idx++; - N--; - } -} - -/* -** Return the size of the Nth element of the cell array -*/ -static SQLITE_NOINLINE u16 computeCellSize(CellArray *p, int N){ - assert( N>=0 && NnCell ); - assert( p->szCell[N]==0 ); - p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]); - return p->szCell[N]; -} -static u16 cachedCellSize(CellArray *p, int N){ - assert( N>=0 && NnCell ); - if( p->szCell[N] ) return p->szCell[N]; - return computeCellSize(p, N); -} - -/* -** Array apCell[] contains pointers to nCell b-tree page cells. The -** szCell[] array contains the size in bytes of each cell. This function -** replaces the current contents of page pPg with the contents of the cell -** array. -** -** Some of the cells in apCell[] may currently be stored in pPg. This -** function works around problems caused by this by making a copy of any -** such cells before overwriting the page data. -** -** The MemPage.nFree field is invalidated by this function. It is the -** responsibility of the caller to set it correctly. -*/ -static int rebuildPage( - MemPage *pPg, /* Edit this page */ - int nCell, /* Final number of cells on page */ - u8 **apCell, /* Array of cells */ - u16 *szCell /* Array of cell sizes */ +static void assemblePage( + MemPage *pPage, /* The page to be assemblied */ + int nCell, /* The number of cells to add to this page */ + u8 **apCell, /* Pointers to cell bodies */ + u16 *aSize /* Sizes of the cells */ ){ - const int hdr = pPg->hdrOffset; /* Offset of header on pPg */ - u8 * const aData = pPg->aData; /* Pointer to data for pPg */ - const int usableSize = pPg->pBt->usableSize; - u8 * const pEnd = &aData[usableSize]; - int i; - u8 *pCellptr = pPg->aCellIdx; - u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); - u8 *pData; + int i; /* Loop counter */ + u8 *pCellptr; /* Address of next cell pointer */ + int cellbody; /* Address of next cell body */ + u8 * const data = pPage->aData; /* Pointer to data for pPage */ + const int hdr = pPage->hdrOffset; /* Offset of header on pPage */ + const int nUsable = pPage->pBt->usableSize; /* Usable size of page */ - i = get2byte(&aData[hdr+5]); - memcpy(&pTmp[i], &aData[i], usableSize - i); + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( nCell>=0 && nCell<=(int)MX_CELL(pPage->pBt) + && (int)MX_CELL(pPage->pBt)<=10921); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - pData = pEnd; - for(i=0; ixCellSize(pPg, pCell) || CORRUPT_DB ); - testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) ); + /* Check that the page has just been zeroed by zeroPage() */ + assert( pPage->nCell==0 ); + assert( get2byteNotZero(&data[hdr+5])==nUsable ); + + pCellptr = &pPage->aCellIdx[nCell*2]; + cellbody = nUsable; + for(i=nCell-1; i>=0; i--){ + u16 sz = aSize[i]; + pCellptr -= 2; + cellbody -= sz; + put2byte(pCellptr, cellbody); + memcpy(&data[cellbody], apCell[i], sz); } - - /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ - pPg->nCell = nCell; - pPg->nOverflow = 0; - - put2byte(&aData[hdr+1], 0); - put2byte(&aData[hdr+3], pPg->nCell); - put2byte(&aData[hdr+5], pData - aData); - aData[hdr+7] = 0x00; - return SQLITE_OK; -} - -/* -** Array apCell[] contains nCell pointers to b-tree cells. Array szCell -** contains the size in bytes of each such cell. This function attempts to -** add the cells stored in the array to page pPg. If it cannot (because -** the page needs to be defragmented before the cells will fit), non-zero -** is returned. Otherwise, if the cells are added successfully, zero is -** returned. -** -** Argument pCellptr points to the first entry in the cell-pointer array -** (part of page pPg) to populate. After cell apCell[0] is written to the -** page body, a 16-bit offset is written to pCellptr. And so on, for each -** cell in the array. It is the responsibility of the caller to ensure -** that it is safe to overwrite this part of the cell-pointer array. -** -** When this function is called, *ppData points to the start of the -** content area on page pPg. If the size of the content area is extended, -** *ppData is updated to point to the new start of the content area -** before returning. -** -** Finally, argument pBegin points to the byte immediately following the -** end of the space required by this page for the cell-pointer area (for -** all cells - not just those inserted by the current call). If the content -** area must be extended to before this point in order to accomodate all -** cells in apCell[], then the cells do not fit and non-zero is returned. -*/ -static int pageInsertArray( - MemPage *pPg, /* Page to add cells to */ - u8 *pBegin, /* End of cell-pointer array */ - u8 **ppData, /* IN/OUT: Page content -area pointer */ - u8 *pCellptr, /* Pointer to cell-pointer area */ - int iFirst, /* Index of first cell to add */ - int nCell, /* Number of cells to add to pPg */ - CellArray *pCArray /* Array of cells */ -){ - int i; - u8 *aData = pPg->aData; - u8 *pData = *ppData; - int iEnd = iFirst + nCell; - assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ - for(i=iFirst; iapCell[i] will never overlap on a well-formed - ** database. But they might for a corrupt database. Hence use memmove() - ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */ - assert( (pSlot+sz)<=pCArray->apCell[i] - || pSlot>=(pCArray->apCell[i]+sz) - || CORRUPT_DB ); - memmove(pSlot, pCArray->apCell[i], sz); - put2byte(pCellptr, (pSlot - aData)); - pCellptr += 2; - } - *ppData = pData; - return 0; -} - -/* -** Array apCell[] contains nCell pointers to b-tree cells. Array szCell -** contains the size in bytes of each such cell. This function adds the -** space associated with each cell in the array that is currently stored -** within the body of pPg to the pPg free-list. The cell-pointers and other -** fields of the page are not updated. -** -** This function returns the total number of cells added to the free-list. -*/ -static int pageFreeArray( - MemPage *pPg, /* Page to edit */ - int iFirst, /* First cell to delete */ - int nCell, /* Cells to delete */ - CellArray *pCArray /* Array of cells */ -){ - u8 * const aData = pPg->aData; - u8 * const pEnd = &aData[pPg->pBt->usableSize]; - u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; - int nRet = 0; - int i; - int iEnd = iFirst + nCell; - u8 *pFree = 0; - int szFree = 0; - - for(i=iFirst; iapCell[i]; - if( SQLITE_WITHIN(pCell, pStart, pEnd) ){ - int sz; - /* 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; - }else{ - pFree = pCell; - szFree += sz; - } - nRet++; - } - } - if( pFree ){ - assert( pFree>aData && (pFree - aData)<65536 ); - freeSpace(pPg, (u16)(pFree - aData), szFree); - } - return nRet; -} - -/* -** apCell[] and szCell[] contains pointers to and sizes of all cells in the -** pages being balanced. The current page, pPg, has pPg->nCell cells starting -** with apCell[iOld]. After balancing, this page should hold nNew cells -** starting at apCell[iNew]. -** -** This routine makes the necessary adjustments to pPg so that it contains -** the correct cells after being balanced. -** -** The pPg->nFree field is invalid when this function returns. It is the -** responsibility of the caller to set it correctly. -*/ -static int editPage( - MemPage *pPg, /* Edit this page */ - int iOld, /* Index of first cell currently on page */ - int iNew, /* Index of new first cell on page */ - int nNew, /* Final number of cells on page */ - CellArray *pCArray /* Array of cells and sizes */ -){ - u8 * const aData = pPg->aData; - const int hdr = pPg->hdrOffset; - u8 *pBegin = &pPg->aCellIdx[nNew * 2]; - int nCell = pPg->nCell; /* Cells stored on pPg */ - u8 *pData; - u8 *pCellptr; - int i; - int iOldEnd = iOld + pPg->nCell + pPg->nOverflow; - int iNewEnd = iNew + nNew; - -#ifdef SQLITE_DEBUG - u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); - memcpy(pTmp, aData, pPg->pBt->usableSize); -#endif - - /* Remove cells from the start and end of the page */ - if( iOldaCellIdx, &pPg->aCellIdx[nShift*2], nCell*2); - nCell -= nShift; - } - if( iNewEnd < iOldEnd ){ - nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); - } - - pData = &aData[get2byteNotZero(&aData[hdr+5])]; - if( pDataaCellIdx; - memmove(&pCellptr[nAdd*2], pCellptr, nCell*2); - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iNew, nAdd, pCArray - ) ) goto editpage_fail; - nCell += nAdd; - } - - /* Add any overflow cells */ - for(i=0; inOverflow; i++){ - int iCell = (iOld + pPg->aiOvfl[i]) - iNew; - if( iCell>=0 && iCellaCellIdx[iCell * 2]; - memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); - nCell++; - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iCell+iNew, 1, pCArray - ) ) goto editpage_fail; - } - } - - /* Append cells to the end of the page */ - pCellptr = &pPg->aCellIdx[nCell*2]; - if( pageInsertArray( - pPg, pBegin, &pData, pCellptr, - iNew+nCell, nNew-nCell, pCArray - ) ) goto editpage_fail; - - pPg->nCell = nNew; - pPg->nOverflow = 0; - - put2byte(&aData[hdr+3], pPg->nCell); - put2byte(&aData[hdr+5], pData - aData); - -#ifdef SQLITE_DEBUG - for(i=0; iapCell[i+iNew]; - int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); - if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ - pCell = &pTmp[pCell - aData]; - } - assert( 0==memcmp(pCell, &aData[iOff], - pCArray->pRef->xCellSize(pCArray->pRef, pCArray->apCell[i+iNew])) ); - } -#endif - - return SQLITE_OK; - editpage_fail: - /* Unable to edit this page. Rebuild it from scratch instead. */ - populateCellCache(pCArray, iNew, nNew); - return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]); + put2byte(&data[hdr+3], nCell); + put2byte(&data[hdr+5], cellbody); + pPage->nFree -= (nCell*2 + nUsable - cellbody); + pPage->nCell = (u16)nCell; } /* @@ -61883,7 +57047,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ - if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; + if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell @@ -61895,15 +57059,13 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ u8 *pOut = &pSpace[4]; u8 *pCell = pPage->apOvfl[0]; - u16 szCell = pPage->xCellSize(pPage, pCell); + u16 szCell = cellSizePtr(pPage, pCell); u8 *pStop; assert( sqlite3PagerIswriteable(pNew->pDbPage) ); assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); - rc = rebuildPage(pNew, 1, &pCell, &szCell); - if( NEVER(rc) ) return rc; - pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell; + assemblePage(pNew, 1, &pCell, &szCell); /* If this is an auto-vacuum database, update the pointer map ** with entries for the new page, and any pointer from the @@ -61975,9 +57137,9 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){ u8 *z; z = findCell(pPage, j); - pPage->xParseCell(pPage, z, &info); - if( info.nLocalpgno && e==PTRMAP_OVERFLOW1 ); } @@ -62095,6 +57257,9 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ ** If aOvflSpace is set to a null pointer, this function returns ** SQLITE_NOMEM. */ +#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) +#pragma optimize("", off) +#endif static int balance_nonroot( MemPage *pParent, /* Parent page of siblings being balanced */ int iParentIdx, /* Index of "the page" in pParent */ @@ -62103,6 +57268,7 @@ static int balance_nonroot( int bBulk /* True if this call is part of a bulk load */ ){ BtShared *pBt; /* The whole database */ + int nCell = 0; /* Number of cells in apCell[] */ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ int nNew = 0; /* Number of pages in apNew[] */ int nOld; /* Number of pages in apOld[] */ @@ -62113,27 +57279,22 @@ static int balance_nonroot( int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ int usableSpace; /* Bytes in pPage beyond the header */ int pageFlags; /* Value of pPage->aData[0] */ + int subtotal; /* Subtotal of bytes in cells on one page */ int iSpace1 = 0; /* First unused byte of aSpace1[] */ int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ int szScratch; /* Size of scratch memory requested */ MemPage *apOld[NB]; /* pPage and up to two siblings */ + MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ u8 *pRight; /* Location in parent of right-sibling pointer */ u8 *apDiv[NB-1]; /* Divider cells in pParent */ - int cntNew[NB+2]; /* Index in b.paCell[] of cell after i-th page */ - int cntOld[NB+2]; /* Old index in b.apCell[] */ - int szNew[NB+2]; /* Combined size of cells placed on i-th page */ + int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ + int szNew[NB+2]; /* Combined size of cells place on i-th page */ + u8 **apCell = 0; /* All cells begin balanced */ + u16 *szCell; /* Local size of all cells in apCell[] */ u8 *aSpace1; /* Space for copies of dividers cells */ Pgno pgno; /* Temp var to store a page number in */ - u8 abDone[NB+2]; /* True after i'th new page is populated */ - Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ - Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ - u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ - CellArray b; /* Parsed information on cells being balanced */ - memset(abDone, 0, sizeof(abDone)); - b.nCell = 0; - b.apCell = 0; pBt = pParent->pBt; assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); @@ -62175,6 +57336,7 @@ static int balance_nonroot( }else if( iParentIdx==i ){ nxDiv = i-2+bBulk; }else{ + assert( bBulk==0 ); nxDiv = iParentIdx-1; } i = 2-bBulk; @@ -62187,7 +57349,7 @@ static int balance_nonroot( } pgno = get4byte(pRight); while( 1 ){ - rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0); + rc = getAndInitPage(pBt, pgno, &apOld[i], 0); if( rc ){ memset(apOld, 0, (i+1)*sizeof(MemPage*)); goto balance_cleanup; @@ -62198,12 +57360,12 @@ static int balance_nonroot( if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); - szNew[i] = pParent->xCellSize(pParent, apDiv[i]); + szNew[i] = cellSizePtr(pParent, apDiv[i]); pParent->nOverflow = 0; }else{ apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); pgno = get4byte(apDiv[i]); - szNew[i] = pParent->xCellSize(pParent, apDiv[i]); + szNew[i] = cellSizePtr(pParent, apDiv[i]); /* Drop the cell from the parent page. apDiv[i] still points to ** the cell within the parent, even though it has been dropped. @@ -62241,209 +57403,138 @@ static int balance_nonroot( /* ** Allocate space for memory structures */ + k = pBt->pageSize + ROUND8(sizeof(MemPage)); szScratch = - nMaxCells*sizeof(u8*) /* b.apCell */ - + nMaxCells*sizeof(u16) /* b.szCell */ - + pBt->pageSize; /* aSpace1 */ - - /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer - ** that is more than 6 times the database page size. */ - assert( szScratch<=6*(int)pBt->pageSize ); - b.apCell = sqlite3ScratchMalloc( szScratch ); - if( b.apCell==0 ){ + nMaxCells*sizeof(u8*) /* apCell */ + + nMaxCells*sizeof(u16) /* szCell */ + + pBt->pageSize /* aSpace1 */ + + k*nOld; /* Page copies (apCopy) */ + apCell = sqlite3ScratchMalloc( szScratch ); + if( apCell==0 ){ rc = SQLITE_NOMEM; goto balance_cleanup; } - b.szCell = (u16*)&b.apCell[nMaxCells]; - aSpace1 = (u8*)&b.szCell[nMaxCells]; + szCell = (u16*)&apCell[nMaxCells]; + aSpace1 = (u8*)&szCell[nMaxCells]; assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); /* ** Load pointers to all cells on sibling pages and the divider cells - ** into the local b.apCell[] array. Make copies of the divider cells - ** into space obtained from aSpace1[]. The divider cells have already - ** been removed from pParent. + ** into the local apCell[] array. Make copies of the divider cells + ** into space obtained from aSpace1[] and remove the divider cells + ** from pParent. ** ** If the siblings are on leaf pages, then the child pointers of the ** divider cells are stripped from the cells before they are copied - ** into aSpace1[]. In this way, all cells in b.apCell[] are without + ** into aSpace1[]. In this way, all cells in apCell[] are without ** child pointers. If siblings are not leaves, then all cell in - ** b.apCell[] include child pointers. Either way, all cells in b.apCell[] + ** apCell[] include child pointers. Either way, all cells in apCell[] ** are alike. ** ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. ** leafData: 1 if pPage holds key+data and pParent holds only keys. */ - b.pRef = apOld[0]; - leafCorrection = b.pRef->leaf*4; - leafData = b.pRef->intKeyLeaf; + leafCorrection = apOld[0]->leaf*4; + leafData = apOld[0]->hasData; for(i=0; inCell; - u8 *aData = pOld->aData; - u16 maskPage = pOld->maskPage; - u8 *piCell = aData + pOld->cellOffset; - u8 *piEnd; + int limit; + + /* Before doing anything else, take a copy of the i'th original sibling + ** The rest of this function will use data from the copies rather + ** that the original pages since the original pages will be in the + ** process of being overwritten. */ + MemPage *pOld = apCopy[i] = (MemPage*)&aSpace1[pBt->pageSize + k*i]; + memcpy(pOld, apOld[i], sizeof(MemPage)); + pOld->aData = (void*)&pOld[1]; + memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize); - /* Verify that all sibling pages are of the same "type" (table-leaf, - ** table-interior, index-leaf, or index-interior). - */ - if( pOld->aData[0]!=apOld[0]->aData[0] ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - - /* Load b.apCell[] with pointers to all cells in pOld. If pOld - ** constains overflow cells, include them in the b.apCell[] array - ** in the correct spot. - ** - ** Note that when there are multiple overflow cells, it is always the - ** case that they are sequential and adjacent. This invariant arises - ** because multiple overflows can only occurs when inserting divider - ** cells into a parent on a prior balance, and divider cells are always - ** adjacent and are inserted in order. There is an assert() tagged - ** with "NOTE 1" in the overflow cell insertion loop to prove this - ** invariant. - ** - ** This must be done in advance. Once the balance starts, the cell - ** offset section of the btree page will be overwritten and we will no - ** long be able to find the cells if a pointer to each cell is not saved - ** first. - */ - memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*limit); + limit = pOld->nCell+pOld->nOverflow; if( pOld->nOverflow>0 ){ - memset(&b.szCell[b.nCell+limit], 0, sizeof(b.szCell[0])*pOld->nOverflow); - limit = pOld->aiOvfl[0]; for(j=0; jnOverflow; k++){ - assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */ - b.apCell[b.nCell] = pOld->apOvfl[k]; - b.nCell++; + }else{ + u8 *aData = pOld->aData; + u16 maskPage = pOld->maskPage; + u16 cellOffset = pOld->cellOffset; + for(j=0; jcellOffset + 2*pOld->nCell; - while( piCellmaxLocal+23 ); assert( iSpace1 <= (int)pBt->pageSize ); memcpy(pTemp, apDiv[i], sz); - b.apCell[b.nCell] = pTemp+leafCorrection; + apCell[nCell] = pTemp+leafCorrection; assert( leafCorrection==0 || leafCorrection==4 ); - b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection; + szCell[nCell] = szCell[nCell] - leafCorrection; if( !pOld->leaf ){ assert( leafCorrection==0 ); assert( pOld->hdrOffset==0 ); /* The right pointer of the child page pOld becomes the left ** pointer of the divider cell */ - memcpy(b.apCell[b.nCell], &pOld->aData[8], 4); + memcpy(apCell[nCell], &pOld->aData[8], 4); }else{ assert( leafCorrection==4 ); - while( b.szCell[b.nCell]<4 ){ - /* Do not allow any cells smaller than 4 bytes. If a smaller cell - ** does exist, pad it with 0x00 bytes. */ - assert( b.szCell[b.nCell]==3 || CORRUPT_DB ); - assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || CORRUPT_DB ); - aSpace1[iSpace1++] = 0x00; - b.szCell[b.nCell]++; + if( szCell[nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. */ + szCell[nCell] = 4; } } - b.nCell++; + nCell++; } } /* - ** Figure out the number of pages needed to hold all b.nCell cells. + ** Figure out the number of pages needed to hold all nCell cells. ** Store this number in "k". Also compute szNew[] which is the total ** size of all cells on the i-th page and cntNew[] which is the index - ** in b.apCell[] of the cell that divides page i from page i+1. - ** cntNew[k] should equal b.nCell. + ** in apCell[] of the cell that divides page i from page i+1. + ** cntNew[k] should equal nCell. ** ** Values computed by this block: ** ** k: The total number of sibling pages ** szNew[i]: Spaced used on the i-th sibling page. - ** cntNew[i]: Index in b.apCell[] and b.szCell[] for the first cell to + ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to ** the right of the i-th sibling page. ** usableSpace: Number of bytes of space available on each sibling. ** */ usableSpace = pBt->usableSize - 12 + leafCorrection; - for(i=0; inFree; - if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } - for(j=0; jnOverflow; j++){ - szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); - } - cntNew[i] = cntOld[i]; - } - k = nOld; - for(i=0; iusableSpace ){ - if( i+1>=k ){ - k = i+2; - if( k>NB+2 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } - szNew[k-1] = 0; - cntNew[k-1] = b.nCell; - } - sz = 2 + cachedCellSize(&b, cntNew[i]-1); - szNew[i] -= sz; - if( !leafData ){ - if( cntNew[i]usableSpace ) break; - szNew[i] += sz; - cntNew[i]++; - if( !leafData ){ - if( cntNew[i]=b.nCell ){ - k = i+1; - }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; + for(subtotal=k=i=0; i usableSpace ){ + szNew[k] = subtotal - szCell[i]; + cntNew[k] = i; + if( leafData ){ i--; } + subtotal = 0; + k++; + if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } } } + szNew[k] = subtotal; + cntNew[k] = nCell; + k++; /* ** The packing computed by the previous block is biased toward the siblings - ** on the left side (siblings with smaller keys). The left siblings are - ** always nearly full, while the right-most sibling might be nearly empty. - ** The next block of code attempts to adjust the packing of siblings to - ** get a better balance. + ** on the left side. The left siblings are always nearly full, while the + ** right-most sibling might be nearly empty. This block of code attempts + ** to adjust the packing of siblings to get a better balance. ** ** This adjustment is more than an optimization. The packing above might ** be so out of balance as to be illegal. For example, the right-most @@ -62457,46 +57548,46 @@ static int balance_nonroot( r = cntNew[i-1] - 1; d = r + 1 - leafData; - (void)cachedCellSize(&b, d); - do{ - assert( d szLeft-(b.szCell[r]+2)) ){ - break; - } - szRight += b.szCell[d] + 2; - szLeft -= b.szCell[r] + 2; - cntNew[i-1] = r; - r--; - d--; - }while( r>=0 ); + assert( d1 ? cntNew[i-2] : 0) ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } } - /* Sanity check: For a non-corrupt database file one of the follwing - ** must be true: - ** (1) We found one or more cells (cntNew[0])>0), or - ** (2) pPage is a virtual root page. A virtual root page is when - ** the real root page is page 1 and we are the only child of - ** that page. + /* Either we found one or more cells (cntnew[0])>0) or pPage is + ** a virtual root page. A virtual root page is when the real root + ** page is page 1 and we are the only child of that page. + ** + ** UPDATE: The assert() below is not necessarily true if the database + ** file is corrupt. The corruption will be detected and reported later + ** in this procedure so there is no need to act upon it now. */ - 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", - 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 +#if 0 + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); +#endif + + TRACE(("BALANCE: old: %d %d %d ", + apOld[0]->pgno, + nOld>=2 ? apOld[1]->pgno : 0, + nOld>=3 ? apOld[2]->pgno : 0 )); /* ** Allocate k new pages. Reuse old pages where possible. */ + if( apOld[0]->pgno<=1 ){ + rc = SQLITE_CORRUPT_BKPT; + goto balance_cleanup; + } pageFlags = apOld[0]->aData[0]; for(i=0; i0 ); rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); if( rc ) goto balance_cleanup; - zeroPage(pNew, pageFlags); apNew[i] = pNew; nNew++; - cntOld[i] = b.nCell; /* Set the pointer-map entry for the new sibling page. */ if( ISAUTOVACUUM ){ @@ -62525,249 +57614,135 @@ static int balance_nonroot( } } - /* - ** Reassign page numbers so that the new pages are in ascending order. - ** This helps to keep entries in the disk file in order so that a scan - ** of the table is closer to a linear scan through the file. That in turn - ** helps the operating system to deliver pages from the disk more rapidly. - ** - ** An O(n^2) insertion sort algorithm is used, but since n is never more - ** than (NB+2) (a small constant), that should not be a problem. - ** - ** When NB==3, this one optimization makes the database about 25% faster - ** for large insertions and deletions. + /* Free any old pages that were not reused as new pages. */ - for(i=0; ipgno; - aPgFlags[i] = apNew[i]->pDbPage->flags; - for(j=0; ji ){ - sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0); - } - sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]); - apNew[i]->pgno = pgno; - } + while( ipgno, szNew[0], cntNew[0], + /* + ** Put the new pages in accending order. This helps to + ** keep entries in the disk file in order so that a scan + ** of the table is a linear scan through the file. That + ** in turn helps the operating system to deliver pages + ** from the disk more rapidly. + ** + ** An O(n^2) insertion sort algorithm is used, but since + ** n is never more than NB (a small constant), that should + ** not be a problem. + ** + ** When NB==3, this one optimization makes the database + ** about 25% faster for large insertions and deletions. + */ + for(i=0; ipgno; + int minI = i; + for(j=i+1; jpgno<(unsigned)minV ){ + minI = j; + minV = apNew[j]->pgno; + } + } + if( minI>i ){ + MemPage *pT; + pT = apNew[i]; + apNew[i] = apNew[minI]; + apNew[minI] = pT; + } + } + TRACE(("new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", + apNew[0]->pgno, szNew[0], nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, - nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0, nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, - nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0, nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, - nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0, - nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0, - nNew>=5 ? cntNew[4] - cntNew[3] - !leafData : 0 - )); + nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0)); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); put4byte(pRight, apNew[nNew-1]->pgno); - /* If the sibling pages are not leaves, ensure that the right-child pointer - ** of the right-most new sibling page is set to the value that was - ** originally in the same field of the right-most old sibling page. */ - if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ - MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1]; - memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4); - } - - /* Make any required updates to pointer map entries associated with - ** cells stored on sibling pages following the balance operation. Pointer - ** map entries associated with divider cells are set by the insertCell() - ** routine. The associated pointer map entries are: - ** - ** a) if the cell contains a reference to an overflow chain, the - ** entry associated with the first page in the overflow chain, and - ** - ** b) if the sibling pages are not leaves, the child page associated - ** with the cell. - ** - ** If the sibling pages are not leaves, then the pointer map entry - ** associated with the right-child of each sibling may also need to be - ** updated. This happens below, after the sibling pages have been - ** populated, not here. + /* + ** Evenly distribute the data in apCell[] across the new pages. + ** Insert divider cells into pParent as necessary. */ - if( ISAUTOVACUUM ){ - MemPage *pNew = apNew[0]; - u8 *aOld = pNew->aData; - int cntOldNext = pNew->nCell + pNew->nOverflow; - int usableSize = pBt->usableSize; - int iNew = 0; - int iOld = 0; - - for(i=0; inCell + pOld->nOverflow + !leafData; - aOld = pOld->aData; - } - if( i==cntNew[iNew] ){ - pNew = apNew[++iNew]; - if( !leafData ) continue; - } - - /* Cell pCell is destined for new sibling page pNew. Originally, it - ** was either part of sibling page iOld (possibly an overflow cell), - ** or else the divider cell to the left of sibling page iOld. So, - ** if sibling page iOld had the same page number as pNew, and if - ** pCell really was a part of sibling page iOld (not a divider or - ** overflow cell), we can skip updating the pointer map entries. */ - if( iOld>=nNew - || pNew->pgno!=aPgno[iOld] - || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize]) - ){ - if( !leafCorrection ){ - ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); - } - if( cachedCellSize(&b,i)>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pCell, &rc); - } - if( rc ) goto balance_cleanup; - } - } - } - - /* Insert new divider cells into pParent. */ - for(i=0; inCell>0 || (nNew==1 && cntNew[0]==0) ); + assert( pNew->nOverflow==0 ); + j = cntNew[i]; - assert( jleaf ){ - memcpy(&pNew->aData[8], pCell, 4); - }else if( leafData ){ - /* If the tree is a leaf-data tree, and the siblings are leaves, - ** then there is no divider cell in b.apCell[]. Instead, the divider - ** cell consists of the integer key for the right-most cell of - ** the sibling-page assembled above only. - */ - CellInfo info; - j--; - pNew->xParseCell(pNew, b.apCell[j], &info); - pCell = pTemp; - sz = 4 + putVarint(&pCell[4], info.nKey); - pTemp = 0; - }else{ - pCell -= 4; - /* Obscure case for non-leaf-data trees: If the cell at pCell was - ** previously stored on a leaf node, and its reported size was 4 - ** bytes, then it may actually be smaller than this - ** (see btreeParseCellPtr(), 4 bytes is the minimum size of - ** any cell). But it is important to pass the correct size to - ** insertCell(), so reparse the cell now. - ** - ** Note that this can never happen in an SQLite data file, as all - ** cells are at least 4 bytes. It only happens in b-trees used - ** to evaluate "IN (SELECT ...)" and similar clauses. - */ - if( b.szCell[j]==4 ){ - assert(leafCorrection==4); - sz = pParent->xCellSize(pParent, pCell); - } - } - iOvflSpace += sz; - assert( sz<=pBt->maxLocal+23 ); - assert( iOvflSpace <= (int)pBt->pageSize ); - insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc); - if( rc!=SQLITE_OK ) goto balance_cleanup; - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - } + /* If the sibling page assembled above was not the right-most sibling, + ** insert a divider cell into the parent page. + */ + assert( i=0 && iPg=0 /* On the upwards pass, or... */ - || cntOld[iPg-1]>=cntNew[iPg-1] /* Condition (1) is true */ - ){ - int iNew; - int iOld; - int nNewCell; - - /* Verify condition (1): If cells are moving left, update iPg - ** only after iPg-1 has already been updated. */ - assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] ); - - /* Verify condition (2): If cells are moving right, update iPg - ** only after iPg+1 has already been updated. */ - assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] ); - - if( iPg==0 ){ - iNew = iOld = 0; - nNewCell = cntNew[0]; + assert( jleaf ){ + memcpy(&pNew->aData[8], pCell, 4); + }else if( leafData ){ + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of + ** the sibling-page assembled above only. + */ + CellInfo info; + j--; + btreeParseCellPtr(pNew, apCell[j], &info); + pCell = pTemp; + sz = 4 + putVarint(&pCell[4], info.nKey); + pTemp = 0; }else{ - iOld = iPgmaxLocal+23 ); + assert( iOvflSpace <= (int)pBt->pageSize ); + insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); + if( rc!=SQLITE_OK ) goto balance_cleanup; + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - rc = editPage(apNew[iPg], iOld, iNew, nNewCell, &b); - if( rc ) goto balance_cleanup; - abDone[iPg]++; - apNew[iPg]->nFree = usableSpace-szNew[iPg]; - assert( apNew[iPg]->nOverflow==0 ); - assert( apNew[iPg]->nCell==nNewCell ); + j++; + nxDiv++; } } - - /* All pages have been processed exactly once */ - assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 ); - + assert( j==nCell ); assert( nOld>0 ); assert( nNew>0 ); + if( (pageFlags & PTF_LEAF)==0 ){ + u8 *zChild = &apCopy[nOld-1]->aData[8]; + memcpy(&apNew[nNew-1]->aData[8], zChild, 4); + } if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){ /* The root page of the b-tree now contains no cells. The only sibling @@ -62780,56 +57755,132 @@ static int balance_nonroot( ** sets all pointer-map entries corresponding to database image pages ** for which the pointer is stored within the content being copied. ** - ** It is critical that the child page be defragmented before being - ** copied into the parent, because if the parent is page 1 then it will - ** by smaller than the child due to the database header, and so all the - ** free space needs to be up front. - */ - assert( nNew==1 || CORRUPT_DB ); - rc = defragmentPage(apNew[0]); - testcase( rc!=SQLITE_OK ); + ** The second assert below verifies that the child page is defragmented + ** (it must be, as it was just reconstructed using assemblePage()). This + ** is important if the parent page happens to be page 1 of the database + ** image. */ + assert( nNew==1 ); assert( apNew[0]->nFree == - (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) - || rc!=SQLITE_OK + (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) ); copyNodeContent(apNew[0], pParent, &rc); freePage(apNew[0], &rc); - }else if( ISAUTOVACUUM && !leafCorrection ){ - /* Fix the pointer map entries associated with the right-child of each - ** sibling page. All other pointer map entries have already been taken - ** care of. */ - for(i=0; iaData[8]); - ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); + }else if( ISAUTOVACUUM ){ + /* Fix the pointer-map entries for all the cells that were shifted around. + ** There are several different types of pointer-map entries that need to + ** be dealt with by this routine. Some of these have been set already, but + ** many have not. The following is a summary: + ** + ** 1) The entries associated with new sibling pages that were not + ** siblings when this function was called. These have already + ** been set. We don't need to worry about old siblings that were + ** moved to the free-list - the freePage() code has taken care + ** of those. + ** + ** 2) The pointer-map entries associated with the first overflow + ** page in any overflow chains used by new divider cells. These + ** have also already been taken care of by the insertCell() code. + ** + ** 3) If the sibling pages are not leaves, then the child pages of + ** cells stored on the sibling pages may need to be updated. + ** + ** 4) If the sibling pages are not internal intkey nodes, then any + ** overflow pages used by these cells may need to be updated + ** (internal intkey nodes never contain pointers to overflow pages). + ** + ** 5) If the sibling pages are not leaves, then the pointer-map + ** entries for the right-child pages of each sibling may need + ** to be updated. + ** + ** Cases 1 and 2 are dealt with above by other code. The next + ** block deals with cases 3 and 4 and the one after that, case 5. Since + ** setting a pointer map entry is a relatively expensive operation, this + ** code only sets pointer map entries for child or overflow pages that have + ** actually moved between pages. */ + MemPage *pNew = apNew[0]; + MemPage *pOld = apCopy[0]; + int nOverflow = pOld->nOverflow; + int iNextOld = pOld->nCell + nOverflow; + int iOverflow = (nOverflow ? pOld->aiOvfl[0] : -1); + j = 0; /* Current 'old' sibling page */ + k = 0; /* Current 'new' sibling page */ + for(i=0; inCell + pOld->nOverflow; + if( pOld->nOverflow ){ + nOverflow = pOld->nOverflow; + iOverflow = i + !leafData + pOld->aiOvfl[0]; + } + isDivider = !leafData; + } + + assert(nOverflow>0 || iOverflowaiOvfl[0]==pOld->aiOvfl[1]-1); + assert(nOverflow<3 || pOld->aiOvfl[1]==pOld->aiOvfl[2]-1); + if( i==iOverflow ){ + isDivider = 1; + if( (--nOverflow)>0 ){ + iOverflow++; + } + } + + if( i==cntNew[k] ){ + /* Cell i is the cell immediately following the last cell on new + ** sibling page k. If the siblings are not leaf pages of an + ** intkey b-tree, then cell i is a divider cell. */ + pNew = apNew[++k]; + if( !leafData ) continue; + } + assert( jpgno!=pNew->pgno ){ + if( !leafCorrection ){ + ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno, &rc); + } + if( szCell[i]>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, apCell[i], &rc); + } + } } - } - assert( pParent->isInit ); - TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", - nOld, nNew, b.nCell)); - - /* Free any old pages that were not reused as new pages. - */ - for(i=nNew; iaData[8]); + ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); + } + } #if 0 - if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){ /* The ptrmapCheckPages() contains assert() statements that verify that ** all pointer map pages are set correctly. This is helpful while ** debugging. This is usually disabled because a corrupt database may ** cause an assert() statement to fail. */ ptrmapCheckPages(apNew, nNew); ptrmapCheckPages(&pParent, 1); - } #endif + } + + assert( pParent->isInit ); + TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", + nOld, nNew, nCell)); /* ** Cleanup before returning. */ balance_cleanup: - sqlite3ScratchFree(b.apCell); + sqlite3ScratchFree(apCell); for(i=0; i= 1700 && defined(_M_ARM) +#pragma optimize("", on) +#endif /* @@ -62957,7 +58011,7 @@ static int balance(BtCursor *pCur){ rc = sqlite3PagerWrite(pParent->pDbPage); if( rc==SQLITE_OK ){ #ifndef SQLITE_OMIT_QUICKBALANCE - if( pPage->intKeyLeaf + if( pPage->hasData && pPage->nOverflow==1 && pPage->aiOvfl[0]==pPage->nCell && pParent->pgno!=1 @@ -62966,7 +58020,7 @@ static int balance(BtCursor *pCur){ /* Call balance_quick() to create a new sibling of pPage on which ** to store the overflow cell. balance_quick() inserts a new cell ** into pParent, which may cause pParent overflow. If this - ** happens, the next iteration of the do-loop will balance pParent + ** happens, the next interation of the do-loop will balance pParent ** use either balance_nonroot() or balance_deeper(). Until this ** happens, the overflow cell is stored in the aBalanceQuickSpace[] ** buffer. @@ -62999,8 +58053,7 @@ static int balance(BtCursor *pCur){ ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); - rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, - pCur->hints&BTREE_BULKLOAD); + rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); if( pFree ){ /* If pFree is not NULL, it points to the pSpace buffer used ** by a previous call to balance_nonroot(). Its contents are @@ -63021,7 +58074,6 @@ static int balance(BtCursor *pCur){ /* The next iteration of the do-loop balances the parent page. */ releasePage(pPage); pCur->iPage--; - assert( pCur->iPage>=0 ); } }while( rc==SQLITE_OK ); @@ -63045,7 +58097,7 @@ static int balance(BtCursor *pCur){ ** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already ** been performed. seekResult is the search result returned (a negative ** number if pCur points at an entry that is smaller than (pKey, nKey), or -** a positive value if pCur points at an entry that is larger than +** a positive value if pCur points at an etry that is larger than ** (pKey, nKey)). ** ** If the seekResult parameter is non-zero, then the caller guarantees that @@ -63078,8 +58130,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } assert( cursorHoldsMutex(pCur) ); - assert( (pCur->curFlags & BTCF_WriteFlag)!=0 - && pBt->inTransaction==TRANS_WRITE + assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE && (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); @@ -63101,28 +58152,23 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** doing any work. To avoid thwarting these optimizations, it is important ** not to clear the cursor here. */ - if( pCur->curFlags & BTCF_Multiple ){ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - } + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; if( pCur->pKeyInfo==0 ){ - assert( pKey==0 ); /* If this is an insert into a table b-tree, invalidate any incrblob ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, nKey, 0); /* If the cursor is currently on the last row and we are appending a - ** new row onto the end, set the "loc" to avoid an unnecessary - ** btreeMoveto() call */ - if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 - && pCur->info.nKey==nKey-1 ){ - loc = -1; - }else if( loc==0 ){ - rc = sqlite3BtreeMovetoUnpacked(pCur, 0, nKey, appendBias, &loc); - if( rc ) return rc; + ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto() + ** call */ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){ + loc = -1; } - }else if( loc==0 ){ + } + + if( !loc ){ rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); if( rc ) return rc; } @@ -63136,11 +58182,12 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); + allocateTempSpace(pBt); newCell = pBt->pTmpSpace; - assert( newCell!=0 ); + if( newCell==0 ) return SQLITE_NOMEM; rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); if( rc ) goto end_insert; - assert( szNew==pPage->xCellSize(pPage, newCell) ); + assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew <= MX_CELL_SIZE(pBt) ); idx = pCur->aiIdx[pCur->iPage]; if( loc==0 ){ @@ -63154,7 +58201,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } - rc = clearCell(pPage, oldCell, &szOld); + szOld = cellSizePtr(pPage, oldCell); + rc = clearCell(pPage, oldCell); dropCell(pPage, idx, szOld, &rc); if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ @@ -63205,15 +58253,10 @@ end_insert: } /* -** Delete the entry that the cursor is pointing to. -** -** If the second parameter is zero, then the cursor is left pointing at an -** arbitrary location after the delete. If it is non-zero, then the cursor -** is left in a state such that the next call to BtreeNext() or BtreePrev() -** moves it to the same row as it would if the call to BtreeDelete() had -** been omitted. +** Delete the entry that the cursor is pointing to. The cursor +** is left pointing at a arbitrary location. */ -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; int rc; /* Return code */ @@ -63221,8 +58264,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ unsigned char *pCell; /* Pointer to cell to delete */ int iCellIdx; /* Index of cell to delete */ int iCellDepth; /* Depth of node containing pCell */ - u16 szCell; /* Size of the cell being deleted */ - int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ assert( cursorHoldsMutex(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -63230,8 +58271,12 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); - assert( pCur->eState==CURSOR_VALID ); + + if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) + || NEVER(pCur->eState!=CURSOR_VALID) + ){ + return SQLITE_ERROR; /* Something has gone awry. */ + } iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; @@ -63252,11 +58297,12 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ } /* Save the positions of any other cursors open on this table before - ** making any modifications. */ - if( pCur->curFlags & BTCF_Multiple ){ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - } + ** making any modifications. Make the page containing the entry to be + ** deleted writable. Then free any overflow pages associated with the + ** entry and finally remove the cell itself from within the page. + */ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; /* If this is a delete operation to remove a row from a table b-tree, ** invalidate any incrblob cursors open on the row being deleted. */ @@ -63264,35 +58310,10 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ invalidateIncrblobCursors(p, pCur->info.nKey, 0); } - /* If the bPreserve flag is set to true, then the cursor position must - ** be preserved following this delete operation. If the current delete - ** will cause a b-tree rebalance, then this is done by saving the cursor - ** key and leaving the cursor in CURSOR_REQUIRESEEK state before - ** returning. - ** - ** Or, if the current delete will not cause a rebalance, then the cursor - ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. In this case set bSkipnext to true. */ - if( bPreserve ){ - if( !pPage->leaf - || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) - ){ - /* A b-tree rebalance will be required after deleting this entry. - ** Save the cursor key. */ - rc = saveCursorKey(pCur); - if( rc ) return rc; - }else{ - bSkipnext = 1; - } - } - - /* Make the page containing the entry to be deleted writable. Then free any - ** overflow pages associated with the entry and finally remove the cell - ** itself from within the page. */ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; - rc = clearCell(pPage, pCell, &szCell); - dropCell(pPage, iCellIdx, szCell, &rc); + rc = clearCell(pPage, pCell); + dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc); if( rc ) return rc; /* If the cell deleted was not located on a leaf page, then the cursor @@ -63307,11 +58328,12 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ unsigned char *pTmp; pCell = findCell(pLeaf, pLeaf->nCell-1); - if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; - nCell = pLeaf->xCellSize(pLeaf, pCell); + nCell = cellSizePtr(pLeaf, pCell); assert( MX_CELL_SIZE(pBt) >= nCell ); + + allocateTempSpace(pBt); pTmp = pBt->pTmpSpace; - assert( pTmp!=0 ); + rc = sqlite3PagerWrite(pLeaf->pDbPage); insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); @@ -63342,23 +58364,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ } if( rc==SQLITE_OK ){ - if( bSkipnext ){ - assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); - assert( pPage==pCur->apPage[pCur->iPage] ); - assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); - pCur->eState = CURSOR_SKIPNEXT; - if( iCellIdx>=pPage->nCell ){ - pCur->skipNext = -1; - pCur->aiIdx[iCellDepth] = pPage->nCell-1; - }else{ - pCur->skipNext = 1; - } - }else{ - rc = moveToRoot(pCur); - if( bPreserve ){ - pCur->eState = CURSOR_REQUIRESEEK; - } - } + moveToRoot(pCur); } return rc; } @@ -63416,8 +58422,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } - assert( pgnoRoot>=3 || CORRUPT_DB ); - testcase( pgnoRoot<3 ); + assert( pgnoRoot>=3 ); /* Allocate a page. The page that currently resides at pgnoRoot will ** be moved to the allocated page (unless the allocated page happens @@ -63540,19 +58545,14 @@ static int clearDatabasePage( unsigned char *pCell; int i; int hdr; - u16 szCell; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); + + rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; - if( pPage->bBusy ){ - rc = SQLITE_CORRUPT_BKPT; - goto cleardatabasepage_out; - } - pPage->bBusy = 1; hdr = pPage->hdrOffset; for(i=0; inCell; i++){ pCell = findCell(pPage, i); @@ -63560,15 +58560,14 @@ static int clearDatabasePage( rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } - rc = clearCell(pPage, pCell, &szCell); + rc = clearCell(pPage, pCell); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; }else if( pnChange ){ - assert( pPage->intKey || CORRUPT_DB ); - testcase( !pPage->intKey ); + assert( pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ @@ -63578,7 +58577,6 @@ static int clearDatabasePage( } cleardatabasepage_out: - pPage->bBusy = 0; releasePage(pPage); return rc; } @@ -63768,13 +58766,6 @@ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ ** The schema layer numbers meta values differently. At the schema ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. -** -** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead -** of reading the value out of the header, it instead loads the "DataVersion" -** from the pager. The BTREE_DATA_VERSION value is not actually stored in the -** database file. It is a number computed by the pager. But its access -** pattern is the same as header meta values, and so it is convenient to -** read it from this routine. */ SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ BtShared *pBt = p->pBt; @@ -63785,11 +58776,7 @@ SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ assert( pBt->pPage1 ); assert( idx>=0 && idx<=15 ); - if( idx==BTREE_DATA_VERSION ){ - *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; - }else{ - *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); - } + *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); /* If auto-vacuum is disabled in this build and this is an auto-vacuum ** database, mark the database as read-only. */ @@ -63880,7 +58867,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ if( pCur->iPage==0 ){ /* All pages of the b-tree have been visited. Return successfully. */ *pnEntry = nEntry; - return moveToRoot(pCur); + return SQLITE_OK; } moveToParent(pCur); }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); @@ -63919,6 +58906,7 @@ SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ */ static void checkAppendMsg( IntegrityCk *pCheck, + char *zMsg1, const char *zFormat, ... ){ @@ -63930,8 +58918,8 @@ static void checkAppendMsg( if( pCheck->errMsg.nChar ){ sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); } - if( pCheck->zPfx ){ - sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2); + if( zMsg1 ){ + sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1); } sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); va_end(ap); @@ -63964,19 +58952,19 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. -** Return 1 if there are 2 or more references to the page and 0 if +** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ -static int checkRef(IntegrityCk *pCheck, Pgno iPage){ +static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage ){ - checkAppendMsg(pCheck, "invalid page number %d", iPage); + checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ - checkAppendMsg(pCheck, "2nd reference to page %d", iPage); + checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } setPageReferenced(pCheck, iPage); @@ -63993,7 +58981,8 @@ static void checkPtrmap( IntegrityCk *pCheck, /* Integrity check context */ Pgno iChild, /* Child page number */ u8 eType, /* Expected pointer map type */ - Pgno iParent /* Expected pointer map parent page number */ + Pgno iParent, /* Expected pointer map parent page number */ + char *zContext /* Context description (used for error msg) */ ){ int rc; u8 ePtrmapType; @@ -64002,12 +58991,12 @@ static void checkPtrmap( rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1; - checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild); + checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); return; } if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ - checkAppendMsg(pCheck, + checkAppendMsg(pCheck, zContext, "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", iChild, eType, iParent, ePtrmapType, iPtrmapParent); } @@ -64022,7 +59011,8 @@ static void checkList( IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ int iPage, /* Page number for first page in the list */ - int N /* Expected number of pages in the list */ + int N, /* Expected number of pages in the list */ + char *zContext /* Context for error messages */ ){ int i; int expected = N; @@ -64031,14 +59021,14 @@ static void checkList( DbPage *pOvflPage; unsigned char *pOvflData; if( iPage<1 ){ - checkAppendMsg(pCheck, + checkAppendMsg(pCheck, zContext, "%d of %d pages missing from overflow list starting at %d", N+1, expected, iFirst); break; } - if( checkRef(pCheck, iPage) ) break; - if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ - checkAppendMsg(pCheck, "failed to get page %d", iPage); + if( checkRef(pCheck, iPage, zContext) ) break; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); break; } pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); @@ -64046,11 +59036,11 @@ static void checkList( int n = get4byte(&pOvflData[4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ - checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0); + checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); } #endif if( n>(int)pCheck->pBt->usableSize/4-2 ){ - checkAppendMsg(pCheck, + checkAppendMsg(pCheck, zContext, "freelist leaf count too big on page %d", iPage); N--; }else{ @@ -64058,10 +59048,10 @@ static void checkList( Pgno iFreePage = get4byte(&pOvflData[8+i*4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ - checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0); + checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); } #endif - checkRef(pCheck, iFreePage); + checkRef(pCheck, iFreePage, zContext); } N -= n; } @@ -64074,71 +59064,16 @@ static void checkList( */ if( pCheck->pBt->autoVacuum && N>0 ){ i = get4byte(pOvflData); - checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage); + checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); } } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); - - if( isFreeList && N<(iPage!=0) ){ - checkAppendMsg(pCheck, "free-page count in header is too small"); - } } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ -/* -** An implementation of a min-heap. -** -** aHeap[0] is the number of elements on the heap. aHeap[1] is the -** root element. The daughter nodes of aHeap[N] are aHeap[N*2] -** and aHeap[N*2+1]. -** -** The heap property is this: Every node is less than or equal to both -** of its daughter nodes. A consequence of the heap property is that the -** root node aHeap[1] is always the minimum value currently in the heap. -** -** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto -** the heap, preserving the heap property. The btreeHeapPull() routine -** removes the root element from the heap (the minimum value in the heap) -** and then moves other nodes around as necessary to preserve the heap -** property. -** -** This heap is used for cell overlap and coverage testing. Each u32 -** entry represents the span of a cell or freeblock on a btree page. -** The upper 16 bits are the index of the first byte of a range and the -** lower 16 bits are the index of the last byte of that range. -*/ -static void btreeHeapInsert(u32 *aHeap, u32 x){ - u32 j, i = ++aHeap[0]; - aHeap[i] = x; - while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ - x = aHeap[j]; - aHeap[j] = aHeap[i]; - aHeap[i] = x; - i = j; - } -} -static int btreeHeapPull(u32 *aHeap, u32 *pOut){ - u32 j, i, x; - if( (x = aHeap[0])==0 ) return 0; - *pOut = aHeap[1]; - aHeap[1] = aHeap[x]; - aHeap[x] = 0xffffffff; - aHeap[0]--; - i = 1; - while( (j = i*2)<=aHeap[0] ){ - if( aHeap[j]>aHeap[j+1] ) j++; - if( aHeap[i]zPfx; - int saved_v1 = pCheck->v1; - int saved_v2 = pCheck->v2; - u8 savedIsInit = 0; + MemPage *pPage; + int i, rc, depth, d2, pgno, cnt; + int hdr, cellStart; + int nCell; + u8 *data; + BtShared *pBt; + int usableSize; + char zContext[100]; + char *hit = 0; + i64 nMinKey = 0; + i64 nMaxKey = 0; + + sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); /* Check that the page exists */ pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; - if( checkRef(pCheck, iPage) ) return 0; - pCheck->zPfx = "Page %d: "; - pCheck->v1 = iPage; + if( checkRef(pCheck, iPage, zParentContext) ) return 0; if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ - checkAppendMsg(pCheck, + checkAppendMsg(pCheck, zContext, "unable to get the page. error code=%d", rc); - goto end_of_check; + return 0; } /* Clear MemPage.isInit to make sure the corruption detection code in ** btreeInitPage() is executed. */ - savedIsInit = pPage->isInit; pPage->isInit = 0; if( (rc = btreeInitPage(pPage))!=0 ){ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ - checkAppendMsg(pCheck, + checkAppendMsg(pCheck, zContext, "btreeInitPage() returns error code %d", rc); - goto end_of_check; - } - data = pPage->aData; - hdr = pPage->hdrOffset; - - /* Set up for cell analysis */ - pCheck->zPfx = "On tree page %d cell %d: "; - contentOffset = get2byteNotZero(&data[hdr+5]); - assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ - - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ - nCell = get2byte(&data[hdr+3]); - assert( pPage->nCell==nCell ); - - /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page - ** immediately follows the b-tree page header. */ - cellStart = hdr + 12 - 4*pPage->leaf; - assert( pPage->aCellIdx==&data[cellStart] ); - pCellIdx = &data[cellStart + 2*(nCell-1)]; - - if( !pPage->leaf ){ - /* Analyze the right-child page of internal pages */ - pgno = get4byte(&data[hdr+8]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - pCheck->zPfx = "On page %d at right child: "; - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); - } -#endif - depth = checkTreePage(pCheck, pgno, &maxKey, maxKey); - keyCanBeEqual = 0; - }else{ - /* For leaf pages, the coverage check will occur in the same loop - ** as the other cell checks, so initialize the heap. */ - heap = pCheck->heap; - heap[0] = 0; + releasePage(pPage); + return 0; } - /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte - ** integer offsets to the cell contents. */ - for(i=nCell-1; i>=0 && pCheck->mxErr; i--){ + /* Check out all the cells. + */ + depth = 0; + for(i=0; inCell && pCheck->mxErr; i++){ + u8 *pCell; + u32 sz; CellInfo info; - /* Check cell size */ - pCheck->v2 = i; - assert( pCellIdx==&data[cellStart + i*2] ); - pc = get2byteAligned(pCellIdx); - pCellIdx -= 2; - if( pcusableSize-4 ){ - checkAppendMsg(pCheck, "Offset %d out of range %d..%d", - pc, contentOffset, usableSize-4); - doCoverageCheck = 0; - continue; - } - pCell = &data[pc]; - pPage->xParseCell(pPage, pCell, &info); - if( pc+info.nSize>usableSize ){ - checkAppendMsg(pCheck, "Extends off end of page"); - doCoverageCheck = 0; - continue; - } - - /* Check for integer primary key out of range */ - if( pPage->intKey ){ - if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){ - checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey); + /* Check payload overflow pages + */ + sqlite3_snprintf(sizeof(zContext), zContext, + "On tree page %d cell %d: ", iPage, i); + pCell = findCell(pPage,i); + btreeParseCellPtr(pPage, pCell, &info); + sz = info.nData; + if( !pPage->intKey ) sz += (int)info.nKey; + /* For intKey pages, check that the keys are in order. + */ + else if( i==0 ) nMinKey = nMaxKey = info.nKey; + else{ + if( info.nKey <= nMaxKey ){ + checkAppendMsg(pCheck, zContext, + "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey); } - maxKey = info.nKey; + nMaxKey = info.nKey; } - - /* Check the content overflow list */ - if( info.nPayload>info.nLocal ){ - int nPage; /* Number of pages on the overflow chain */ - Pgno pgnoOvfl; /* First page of the overflow chain */ - assert( pc + info.nSize - 4 <= usableSize ); - nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); - pgnoOvfl = get4byte(&pCell[info.nSize - 4]); + assert( sz==info.nPayload ); + if( (sz>info.nLocal) + && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) + ){ + int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage); + checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext); } #endif - checkList(pCheck, 0, pgnoOvfl, nPage); + checkList(pCheck, 0, pgnoOvfl, nPage, zContext); } + /* Check sanity of left child page. + */ if( !pPage->leaf ){ - /* Check sanity of left child page for internal pages */ pgno = get4byte(pCell); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); } #endif - d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey); - keyCanBeEqual = 0; - if( d2!=depth ){ - checkAppendMsg(pCheck, "Child page depth differs"); - depth = d2; + d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey); + if( i>0 && d2!=depth ){ + checkAppendMsg(pCheck, zContext, "Child page depth differs"); + } + depth = d2; + } + } + + if( !pPage->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + sqlite3_snprintf(sizeof(zContext), zContext, + "On page %d at right child: ", iPage); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); + } +#endif + checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey); + } + + /* For intKey leaf pages, check that the min/max keys are in order + ** with any left/parent/right pages. + */ + if( pPage->leaf && pPage->intKey ){ + /* if we are a left child page */ + if( pnParentMinKey ){ + /* if we are the left most child page */ + if( !pnParentMaxKey ){ + if( nMaxKey > *pnParentMinKey ){ + checkAppendMsg(pCheck, zContext, + "Rowid %lld out of order (max larger than parent min of %lld)", + nMaxKey, *pnParentMinKey); + } + }else{ + if( nMinKey <= *pnParentMinKey ){ + checkAppendMsg(pCheck, zContext, + "Rowid %lld out of order (min less than parent min of %lld)", + nMinKey, *pnParentMinKey); + } + if( nMaxKey > *pnParentMaxKey ){ + checkAppendMsg(pCheck, zContext, + "Rowid %lld out of order (max larger than parent max of %lld)", + nMaxKey, *pnParentMaxKey); + } + *pnParentMinKey = nMaxKey; + } + /* else if we're a right child page */ + } else if( pnParentMaxKey ){ + if( nMinKey <= *pnParentMaxKey ){ + checkAppendMsg(pCheck, zContext, + "Rowid %lld out of order (min less than parent max of %lld)", + nMinKey, *pnParentMaxKey); } - }else{ - /* Populate the coverage-checking heap for leaf pages */ - btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1)); } } - *piMinKey = maxKey; /* Check for complete coverage of the page */ - pCheck->zPfx = 0; - if( doCoverageCheck && pCheck->mxErr>0 ){ - /* For leaf pages, the min-heap has already been initialized and the - ** cells have already been inserted. But for internal pages, that has - ** not yet been done, so do it now */ - if( !pPage->leaf ){ - heap = pCheck->heap; - heap[0] = 0; - for(i=nCell-1; i>=0; i--){ - u32 size; - pc = get2byteAligned(&data[cellStart+i*2]); - size = pPage->xCellSize(pPage, &data[pc]); - btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); + data = pPage->aData; + hdr = pPage->hdrOffset; + hit = sqlite3PageMalloc( pBt->pageSize ); + if( hit==0 ){ + pCheck->mallocFailed = 1; + }else{ + int contentOffset = get2byteNotZero(&data[hdr+5]); + assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ + memset(hit+contentOffset, 0, usableSize-contentOffset); + memset(hit, 1, contentOffset); + nCell = get2byte(&data[hdr+3]); + cellStart = hdr + 12 - 4*pPage->leaf; + for(i=0; i=usableSize ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage); + }else{ + for(j=pc+size-1; j>=pc; j--) hit[j]++; } } - /* Add the freeblocks to the min-heap - ** - ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header - ** is the offset of the first freeblock, or zero if there are no - ** freeblocks on the page. - */ i = get2byte(&data[hdr+1]); while( i>0 ){ int size, j; - assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */ + assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */ size = get2byte(&data[i+2]); - assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */ - btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); - /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a - ** big-endian integer which is the offset in the b-tree page of the next - ** freeblock in the chain, or zero if the freeblock is the last on the - ** chain. */ + assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */ + for(j=i+size-1; j>=i; j--) hit[j]++; j = get2byte(&data[i]); - /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of - ** increasing offset. */ assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ - assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */ + assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */ i = j; } - /* Analyze the min-heap looking for overlap between cells and/or - ** freeblocks, and counting the number of untracked bytes in nFrag. - ** - ** Each min-heap entry is of the form: (start_address<<16)|end_address. - ** There is an implied first entry the covers the page header, the cell - ** pointer index, and the gap between the cell pointer index and the start - ** of cell content. - ** - ** The loop below pulls entries from the min-heap in order and compares - ** the start_address against the previous end_address. If there is an - ** overlap, that means bytes are used multiple times. If there is a gap, - ** that gap is added to the fragmentation count. - */ - nFrag = 0; - prev = contentOffset - 1; /* Implied first min-heap entry */ - while( btreeHeapPull(heap,&x) ){ - if( (prev&0xffff)>=(x>>16) ){ - checkAppendMsg(pCheck, - "Multiple uses for byte %u of page %d", x>>16, iPage); + for(i=cnt=0; i1 ){ + checkAppendMsg(pCheck, 0, + "Multiple uses for byte %d of page %d", i, iPage); break; - }else{ - nFrag += (x>>16) - (prev&0xffff) - 1; - prev = x; } } - nFrag += usableSize - (prev&0xffff) - 1; - /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments - ** is stored in the fifth field of the b-tree page header. - ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the - ** number of fragmented free bytes within the cell content area. - */ - if( heap[0]==0 && nFrag!=data[hdr+7] ){ - checkAppendMsg(pCheck, + if( cnt!=data[hdr+7] ){ + checkAppendMsg(pCheck, 0, "Fragmentation of %d bytes reported as %d on page %d", - nFrag, data[hdr+7], iPage); + cnt, data[hdr+7], iPage); } } - -end_of_check: - if( !doCoverageCheck ) pPage->isInit = savedIsInit; + sqlite3PageFree(hit); releasePage(pPage); - pCheck->zPfx = saved_zPfx; - pCheck->v1 = saved_v1; - pCheck->v2 = saved_v2; return depth+1; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -64426,74 +59325,60 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( int *pnErr /* Write number of errors seen to this variable */ ){ Pgno i; + int nRef; IntegrityCk sCheck; BtShared *pBt = p->pBt; - int savedDbFlags = pBt->db->flags; char zErr[100]; - VVA_ONLY( int nRef ); sqlite3BtreeEnter(p); assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); - assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); + nRef = sqlite3PagerRefcount(pBt->pPager); sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = btreePagecount(sCheck.pBt); sCheck.mxErr = mxErr; sCheck.nErr = 0; sCheck.mallocFailed = 0; - sCheck.zPfx = 0; - sCheck.v1 = 0; - sCheck.v2 = 0; - sCheck.aPgRef = 0; - sCheck.heap = 0; - sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); + *pnErr = 0; if( sCheck.nPage==0 ){ - goto integrity_ck_cleanup; + sqlite3BtreeLeave(p); + return 0; } sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); if( !sCheck.aPgRef ){ - sCheck.mallocFailed = 1; - goto integrity_ck_cleanup; + *pnErr = 1; + sqlite3BtreeLeave(p); + return 0; } - sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); - if( sCheck.heap==0 ){ - sCheck.mallocFailed = 1; - goto integrity_ck_cleanup; - } - i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); + sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); + sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ - sCheck.zPfx = "Main freelist: "; checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), - get4byte(&pBt->pPage1->aData[36])); - sCheck.zPfx = 0; + get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); /* Check all the tables. */ - testcase( pBt->db->flags & SQLITE_CellSizeCk ); - pBt->db->flags &= ~SQLITE_CellSizeCk; for(i=0; (int)iautoVacuum && aRoot[i]>1 ){ - checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); } #endif - checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); + checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); } - pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ - checkAppendMsg(&sCheck, "Page %d is never used", i); + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain @@ -64501,29 +59386,37 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( */ if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Page %d is never used", i); + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); + checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } #endif } + /* Make sure this analysis did not leave any unref() pages. + ** This is an internal consistency check; an integrity check + ** of the integrity check. + */ + if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){ + checkAppendMsg(&sCheck, 0, + "Outstanding page count goes from %d to %d during this analysis", + nRef, sqlite3PagerRefcount(pBt->pPager) + ); + } + /* Clean up and report errors. */ -integrity_ck_cleanup: - sqlite3PageFree(sCheck.heap); + sqlite3BtreeLeave(p); sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ sqlite3StrAccumReset(&sCheck.errMsg); - sCheck.nErr++; + *pnErr = sCheck.nErr+1; + return 0; } *pnErr = sCheck.nErr; if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); - /* Make sure this analysis did not leave any unref() pages. */ - assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); - sqlite3BtreeLeave(p); return sqlite3StrAccumFinish(&sCheck.errMsg); } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -64703,7 +59596,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void ** required in case any of them are holding references to an xFetch ** version of the b-tree page modified by the accessPayload call below. ** - ** Note that pCsr must be open on a INTKEY table and saveCursorPosition() + ** Note that pCsr must be open on a BTREE_INTKEY table and saveCursorPosition() ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence ** saveAllCursors can only return SQLITE_OK. */ @@ -64734,7 +59627,6 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void */ SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ pCur->curFlags |= BTCF_Incrblob; - pCur->pBtree->hasIncrblobCur = 1; } #endif @@ -64775,11 +59667,12 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ } /* -** Return true if the cursor has a hint specified. This routine is -** only used from within assert() statements +** set the mask of hint flags for cursor pCsr. Currently the only valid +** values are 0 and BTREE_BULKLOAD. */ -SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ - return (pCsr->hints & mask)!=0; +SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ + assert( mask==BTREE_BULKLOAD || mask==0 ); + pCsr->hints = mask; } /* @@ -64789,11 +59682,6 @@ SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){ return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; } -/* -** Return the size of the header added to each page by this module. -*/ -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } - /************** End of btree.c ***********************************************/ /************** Begin file backup.c ******************************************/ /* @@ -64810,8 +59698,6 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); ** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. */ -/* #include "sqliteInt.h" */ -/* #include "btreeInt.h" */ /* ** Structure allocated for each backup operation. @@ -64885,12 +59771,12 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int rc = 0; pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); if( pParse==0 ){ - sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); + sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); rc = SQLITE_NOMEM; }else{ pParse->db = pDb; if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); + sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, pParse->zErrMsg); @@ -64903,7 +59789,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ } if( i<0 ){ - sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); + sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); return 0; } @@ -64920,20 +59806,6 @@ static int setDestPgsz(sqlite3_backup *p){ return rc; } -/* -** Check that there is no open read-transaction on the b-tree passed as the -** second argument. If there is not, return SQLITE_OK. Otherwise, if there -** is an open read-transaction, return SQLITE_ERROR and leave an error -** message in database handle db. -*/ -static int checkReadTransaction(sqlite3 *db, Btree *p){ - if( sqlite3BtreeIsInReadTrans(p) ){ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); - return SQLITE_ERROR; - } - return SQLITE_OK; -} - /* ** Create an sqlite3_backup process to copy the contents of zSrcDb from ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return @@ -64942,7 +59814,7 @@ static int checkReadTransaction(sqlite3 *db, Btree *p){ ** If an error occurs, NULL is returned and an error code and error message ** stored in database handle pDestDb. */ -SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( +SQLITE_API sqlite3_backup *sqlite3_backup_init( sqlite3* pDestDb, /* Database to write to */ const char *zDestDb, /* Name of database within pDestDb */ sqlite3* pSrcDb, /* Database connection to read from */ @@ -64950,13 +59822,6 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( ){ sqlite3_backup *p; /* Value to return */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - /* Lock the source database handle. The destination database ** handle is not locked in this routine, but it is locked in ** sqlite3_backup_step(). The user is required to ensure that no @@ -64969,7 +59834,7 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( sqlite3_mutex_enter(pDestDb->mutex); if( pSrcDb==pDestDb ){ - sqlite3ErrorWithMsg( + sqlite3Error( pDestDb, SQLITE_ERROR, "source and destination must be distinct" ); p = 0; @@ -64980,7 +59845,7 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( ** sqlite3_backup_finish(). */ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM); + sqlite3Error(pDestDb, SQLITE_NOMEM, 0); } } @@ -64993,15 +59858,12 @@ SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init( p->iNext = 1; p->isAttached = 0; - if( 0==p->pSrc || 0==p->pDest - || setDestPgsz(p)==SQLITE_NOMEM - || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK - ){ + if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){ /* One (or both) of the named databases did not exist or an OOM - ** error was hit. Or there is a transaction open on the destination - ** database. The error has already been written into the pDestDb - ** handle. All that is left to do here is free the sqlite3_backup - ** structure. */ + ** error was hit. The error has already been written into the + ** pDestDb handle. All that is left to do here is free the + ** sqlite3_backup structure. + */ sqlite3_free(p); p = 0; } @@ -65045,7 +59907,7 @@ static int backupOnePage( ** guaranteed that the shared-mutex is held by this thread, handle ** p->pSrc may not actually be the owner. */ int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); - int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); + int nDestReserve = sqlite3BtreeGetReserve(p->pDest); #endif int rc = SQLITE_OK; i64 iOff; @@ -65091,7 +59953,7 @@ static int backupOnePage( DbPage *pDestPg = 0; Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; - if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0)) + if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg)) && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) ){ const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; @@ -65150,15 +60012,12 @@ static void attachBackupObject(sqlite3_backup *p){ /* ** Copy nPage pages from the source b-tree to the destination. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ int rc; int destMode; /* Destination journal mode */ int pgszSrc = 0; /* Source page size */ int pgszDest = 0; /* Destination page size */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(p->pSrcDb->mutex); sqlite3BtreeEnter(p->pSrc); if( p->pDestDb ){ @@ -65217,7 +60076,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ - rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); + rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg, + PAGER_GET_READONLY); if( rc==SQLITE_OK ){ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); sqlite3PagerUnref(pSrcPg); @@ -65317,7 +60177,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ DbPage *pPg; - rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); + rc = sqlite3PagerGet(pDestPager, iPg, &pPg); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg); sqlite3PagerUnref(pPg); @@ -65337,7 +60197,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ ){ PgHdr *pSrcPg = 0; const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); - rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0); + rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); if( rc==SQLITE_OK ){ u8 *zData = sqlite3PagerGetData(pSrcPg); rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); @@ -65394,7 +60254,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){ /* ** Release all resources associated with an sqlite3_backup* handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ sqlite3_backup **pp; /* Ptr to head of pagers backup list */ sqlite3 *pSrcDb; /* Source database connection */ int rc; /* Value to return */ @@ -65421,12 +60281,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ } /* If a transaction is still open on the Btree, roll it back. */ - sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); + sqlite3BtreeRollback(p->pDest, SQLITE_OK); /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; if( p->pDestDb ){ - sqlite3Error(p->pDestDb, rc); + sqlite3Error(p->pDestDb, rc, 0); /* Exit the mutexes and free the backup context structure. */ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); @@ -65446,13 +60306,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){ ** Return the number of pages still to be backed up as of the most recent ** call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ return p->nRemaining; } @@ -65460,13 +60314,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){ ** Return the total number of pages in the source database as of the most ** recent call to sqlite3_backup_step(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( p==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ return p->nPagecount; } @@ -65482,13 +60330,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){ ** corresponding to the source database is held when this function is ** called. */ -static SQLITE_NOINLINE void backupUpdate( - sqlite3_backup *p, - Pgno iPage, - const u8 *aData -){ - assert( p!=0 ); - do{ +SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ + sqlite3_backup *p; /* Iterator variable */ + for(p=pBackup; p; p=p->pNext){ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); if( !isFatalError(p->rc) && iPageiNext ){ /* The backup process p has already copied page iPage. But now it @@ -65505,10 +60349,7 @@ static SQLITE_NOINLINE void backupUpdate( p->rc = rc; } } - }while( (p = p->pNext)!=0 ); -} -SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ - if( pBackup ) backupUpdate(pBackup, iPage, aData); + } } /* @@ -65566,10 +60407,6 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ b.pDest = pTo; b.iNext = 1; -#ifdef SQLITE_HAS_CODEC - sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); -#endif - /* 0x7FFFFFFF is the hard limit for the number of pages in a database ** file. By passing this as the number of pages to copy to ** sqlite3_backup_step(), we can guarantee that the copy finishes @@ -65613,8 +60450,6 @@ copy_finished: ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ #ifdef SQLITE_DEBUG /* @@ -65624,40 +60459,29 @@ copy_finished: ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); */ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ - /* If MEM_Dyn is set then Mem.xDel!=0. - ** Mem.xDel is might not be initialized if MEM_Dyn is clear. + /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor + ** function for Mem.z */ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); - - /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we - ** ensure that if Mem.szMalloc>0 then it is safe to do - ** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn. - ** That saves a few cycles in inner loops. */ - assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); - - /* Cannot be both MEM_Int and MEM_Real at the same time */ - assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); - - /* The szMalloc field holds the correct memory allocation size */ - assert( p->szMalloc==0 - || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) ); + assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 ); /* If p holds a string or blob, the Mem.z must point to exactly ** one of the following: ** ** (1) Memory in Mem.zMalloc and managed by the Mem object ** (2) Memory to be freed using Mem.xDel - ** (3) An ephemeral string or blob + ** (3) An ephermal string or blob ** (4) A static string or blob */ - if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){ + if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){ assert( - ((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) + + ((p->z==p->zMalloc)? 1 : 0) + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 ); } + return 1; } #endif @@ -65711,7 +60535,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ ** blob if bPreserve is true. If bPreserve is false, any prior content ** in pMem->z is discarded. */ -SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ +SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( sqlite3VdbeCheckMemInvariants(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); @@ -65720,28 +60544,24 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); testcase( bPreserve && pMem->z==0 ); - assert( pMem->szMalloc==0 - || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); - if( pMem->szMalloczMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)szMalloc>0 && pMem->z==pMem->zMalloc ){ + if( bPreserve && pMem->z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); bPreserve = 0; }else{ - if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); + sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } if( pMem->zMalloc==0 ){ - sqlite3VdbeMemSetNull(pMem); + VdbeMemRelease(pMem); pMem->z = 0; - pMem->szMalloc = 0; + pMem->flags = MEM_Null; return SQLITE_NOMEM; - }else{ - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); } } - if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){ + if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } if( (pMem->flags&MEM_Dyn)!=0 ){ @@ -65751,37 +60571,15 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre pMem->z = pMem->zMalloc; pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static); + pMem->xDel = 0; return SQLITE_OK; } /* -** Change the pMem->zMalloc allocation to be at least szNew bytes. -** If pMem->zMalloc already meets or exceeds the requested size, this -** routine is a no-op. -** -** Any prior string or blob content in the pMem object may be discarded. -** The pMem->xDel destructor is called, if it exists. Though MEM_Str -** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null -** values are preserved. -** -** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM) -** if unable to complete the resizing. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ - assert( szNew>0 ); - assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 ); - if( pMem->szMallocflags & MEM_Dyn)==0 ); - pMem->z = pMem->zMalloc; - pMem->flags &= (MEM_Null|MEM_Int|MEM_Real); - return SQLITE_OK; -} - -/* -** Change pMem so that its MEM_Str or MEM_Blob value is stored in -** MEM.zMalloc, where it can be safely written. +** Make the given Mem object MEM_Dyn. In other words, make it so +** that any TEXT or BLOB content is stored in memory obtained from +** malloc(). In this way, we know that the memory is safe to be +** overwritten or altered. ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ @@ -65791,18 +60589,17 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ assert( (pMem->flags&MEM_RowSet)==0 ); ExpandBlob(pMem); f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){ + if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ return SQLITE_NOMEM; } pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; pMem->flags |= MEM_Term; - } - pMem->flags &= ~MEM_Ephem; #ifdef SQLITE_DEBUG - pMem->pScopyFrom = 0; + pMem->pScopyFrom = 0; #endif + } return SQLITE_OK; } @@ -65836,11 +60633,15 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ } #endif + /* -** It is already known that pMem contains an unterminated string. -** Add the zero terminator. +** Make sure the given Mem is \u0000 terminated. */ -static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ +SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){ + return SQLITE_OK; /* Nothing to do */ + } if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ return SQLITE_NOMEM; } @@ -65850,35 +60651,21 @@ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ return SQLITE_OK; } -/* -** Make sure the given Mem is \u0000 terminated. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) ); - testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 ); - if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){ - return SQLITE_OK; /* Nothing to do */ - }else{ - return vdbeMemAddTerminator(pMem); - } -} - /* ** Add MEM_Str to the set of representations for the given Mem. Numbers ** are converted using sqlite3_snprintf(). Converting a BLOB to a string ** is a no-op. ** -** Existing representations MEM_Int and MEM_Real are invalidated if -** bForce is true but are retained if bForce is false. +** Existing representations MEM_Int and MEM_Real are *not* invalidated. ** ** A MEM_Null value will never be passed to this function. This function is ** used for converting values to text for returning to the user (i.e. via ** sqlite3_value_text()), or for ensuring that values to be used as btree ** keys are strings. In the former case a NULL pointer is returned the -** user and the latter is an internal programming error. +** user and the later is an internal programming error. */ -SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ +SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, int enc){ + int rc = SQLITE_OK; int fg = pMem->flags; const int nByte = 32; @@ -65890,11 +60677,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){ return SQLITE_NOMEM; } - /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 + /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 ** string representation of the value. Then, if the required encoding ** is UTF-16le or UTF-16be do a translation. ** @@ -65904,14 +60691,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); }else{ assert( fg & MEM_Real ); - sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r); } pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; - if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); sqlite3VdbeChangeEncoding(pMem, enc); - return SQLITE_OK; + return rc; } /* @@ -65926,90 +60712,59 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ int rc = SQLITE_OK; if( ALWAYS(pFunc && pFunc->xFinalize) ){ sqlite3_context ctx; - Mem t; assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); memset(&ctx, 0, sizeof(ctx)); - memset(&t, 0, sizeof(t)); - t.flags = MEM_Null; - t.db = pMem->db; - ctx.pOut = &t; + ctx.s.flags = MEM_Null; + ctx.s.db = pMem->db; ctx.pMem = pMem; ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ - assert( (pMem->flags & MEM_Dyn)==0 ); - if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc); - memcpy(pMem, &t, sizeof(t)); + assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); + sqlite3DbFree(pMem->db, pMem->zMalloc); + memcpy(pMem, &ctx.s, sizeof(ctx.s)); rc = ctx.isError; } return rc; } /* -** If the memory cell contains a value that must be freed by -** invoking the external callback in Mem.xDel, then this routine -** will free that value. It also sets Mem.flags to MEM_Null. -** -** This is a helper routine for sqlite3VdbeMemSetNull() and -** for sqlite3VdbeMemRelease(). Use those other routines as the -** entry point for releasing Mem resources. +** If the memory cell contains a string value that must be freed by +** invoking an external callback, free it now. Calling this function +** does not free any Mem.zMalloc buffer. */ -static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){ +SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); - assert( VdbeMemDynamic(p) ); if( p->flags&MEM_Agg ){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); - testcase( p->flags & MEM_Dyn ); - } - if( p->flags&MEM_Dyn ){ + sqlite3VdbeMemRelease(p); + }else if( p->flags&MEM_Dyn ){ assert( (p->flags&MEM_RowSet)==0 ); assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); p->xDel((void *)p->z); + p->xDel = 0; }else if( p->flags&MEM_RowSet ){ sqlite3RowSetClear(p->u.pRowSet); }else if( p->flags&MEM_Frame ){ - VdbeFrame *pFrame = p->u.pFrame; - pFrame->pParent = pFrame->v->pDelFrame; - pFrame->v->pDelFrame = pFrame; + sqlite3VdbeMemSetNull(p); } - p->flags = MEM_Null; } /* -** Release memory held by the Mem p, both external memory cleared -** by p->xDel and memory in p->zMalloc. -** -** This is a helper routine invoked by sqlite3VdbeMemRelease() in -** the unusual case where there really is memory in p that needs -** to be freed. -*/ -static SQLITE_NOINLINE void vdbeMemClear(Mem *p){ - if( VdbeMemDynamic(p) ){ - vdbeMemClearExternAndSetNull(p); - } - if( p->szMalloc ){ - sqlite3DbFree(p->db, p->zMalloc); - p->szMalloc = 0; - } - p->z = 0; -} - -/* -** Release any memory resources held by the Mem. Both the memory that is -** free by Mem.xDel and the Mem.zMalloc allocation are freed. -** -** Use this routine prior to clean up prior to abandoning a Mem, or to -** reset a Mem back to its minimum memory utilization. -** -** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space -** prior to inserting new content into the Mem. +** Release any memory held by the Mem. This may leave the Mem in an +** inconsistent state, for example with (Mem.z==0) and +** (Mem.flags==MEM_Str). */ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); - if( VdbeMemDynamic(p) || p->szMalloc ){ - vdbeMemClear(p); + VdbeMemRelease(p); + if( p->zMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->zMalloc = 0; } + p->z = 0; + assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ } /* @@ -66048,7 +60803,7 @@ static i64 doubleToInt64(double r){ ** If pMem is an integer, then the value is exact. If pMem is ** a floating-point then the value returned is the integer part. ** If pMem is a string or blob, then we make an attempt to convert -** it into an integer and return that. If pMem represents an +** it into a integer and return that. If pMem represents an ** an SQL-NULL value, return 0. ** ** If pMem represents a string value, its encoding might be changed. @@ -66061,10 +60816,11 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){ if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ - return doubleToInt64(pMem->u.r); + return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value = 0; assert( pMem->z || pMem->n==0 ); + testcase( pMem->z==0 ); sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; }else{ @@ -66082,7 +60838,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); if( pMem->flags & MEM_Real ){ - return pMem->u.r; + return pMem->r; }else if( pMem->flags & MEM_Int ){ return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ @@ -66101,13 +60857,12 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ ** MEM_Int if we can. */ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ - i64 ix; assert( pMem->flags & MEM_Real ); assert( (pMem->flags & MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - ix = doubleToInt64(pMem->u.r); + pMem->u.i = doubleToInt64(pMem->r); /* Only mark the value as an integer if ** @@ -66119,9 +60874,11 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ ** the second condition under the assumption that addition overflow causes ** values to wrap around. */ - if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.i = ix; - MemSetTypeFlag(pMem, MEM_Int); + if( pMem->r==(double)pMem->u.i + && pMem->u.i>SMALLEST_INT64 + && pMem->u.iflags |= MEM_Int; } } @@ -66146,7 +60903,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - pMem->u.r = sqlite3VdbeRealValue(pMem); + pMem->r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); return SQLITE_OK; } @@ -66166,7 +60923,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ MemSetTypeFlag(pMem, MEM_Int); }else{ - pMem->u.r = sqlite3VdbeRealValue(pMem); + pMem->r = sqlite3VdbeRealValue(pMem); MemSetTypeFlag(pMem, MEM_Real); sqlite3VdbeIntegerAffinity(pMem); } @@ -66176,81 +60933,19 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ return SQLITE_OK; } -/* -** Cast the datatype of the value in pMem according to the affinity -** "aff". Casting is different from applying affinity in that a cast -** is forced. In other words, the value is converted into the desired -** affinity even if that results in loss of data. This routine is -** used (for example) to implement the SQL "cast()" operator. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ - if( pMem->flags & MEM_Null ) return; - switch( aff ){ - case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ - if( (pMem->flags & MEM_Blob)==0 ){ - sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); - assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - MemSetTypeFlag(pMem, MEM_Blob); - }else{ - pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); - } - break; - } - case SQLITE_AFF_NUMERIC: { - sqlite3VdbeMemNumerify(pMem); - break; - } - case SQLITE_AFF_INTEGER: { - sqlite3VdbeMemIntegerify(pMem); - break; - } - case SQLITE_AFF_REAL: { - sqlite3VdbeMemRealify(pMem); - break; - } - default: { - assert( aff==SQLITE_AFF_TEXT ); - assert( MEM_Str==(MEM_Blob>>3) ); - pMem->flags |= (pMem->flags&MEM_Blob)>>3; - sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); - assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); - pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); - break; - } - } -} - -/* -** Initialize bulk memory to be a consistent Mem object. -** -** The minimum amount of initialization feasible is performed. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){ - assert( (flags & ~MEM_TypeMask)==0 ); - pMem->flags = flags; - pMem->db = db; - pMem->szMalloc = 0; -} - - /* ** Delete any previous value and set the value stored in *pMem to NULL. -** -** This routine calls the Mem.xDel destructor to dispose of values that -** require the destructor. But it preserves the Mem.zMalloc memory allocation. -** To free all resources, use sqlite3VdbeMemRelease(), which both calls this -** routine to invoke the destructor and deallocates Mem.zMalloc. -** -** Use this routine to reset the Mem prior to insert a new value. -** -** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it. */ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ - if( VdbeMemDynamic(pMem) ){ - vdbeMemClearExternAndSetNull(pMem); - }else{ - pMem->flags = MEM_Null; + if( pMem->flags & MEM_Frame ){ + VdbeFrame *pFrame = pMem->u.pFrame; + pFrame->pParent = pFrame->v->pDelFrame; + pFrame->v->pDelFrame = pFrame; } + if( pMem->flags & MEM_RowSet ){ + sqlite3RowSetClear(pMem->u.pRowSet); + } + MemSetTypeFlag(pMem, MEM_Null); } SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){ sqlite3VdbeMemSetNull((Mem*)p); @@ -66267,18 +60962,14 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ if( n<0 ) n = 0; pMem->u.nZero = n; pMem->enc = SQLITE_UTF8; - pMem->z = 0; -} -/* -** The pMem is known to contain content that needs to be destroyed prior -** to a value change. So invoke the destructor, then set the value to -** a 64-bit integer. -*/ -static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){ - sqlite3VdbeMemSetNull(pMem); - pMem->u.i = val; - pMem->flags = MEM_Int; +#ifdef SQLITE_OMIT_INCRBLOB + sqlite3VdbeMemGrow(pMem, n, 0); + if( pMem->z ){ + pMem->n = n; + memset(pMem->z, 0, n); + } +#endif } /* @@ -66286,12 +60977,9 @@ static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){ ** manifest type INTEGER. */ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ - if( VdbeMemDynamic(pMem) ){ - vdbeReleaseAndSetInt64(pMem, val); - }else{ - pMem->u.i = val; - pMem->flags = MEM_Int; - } + sqlite3VdbeMemRelease(pMem); + pMem->u.i = val; + pMem->flags = MEM_Int; } #ifndef SQLITE_OMIT_FLOATING_POINT @@ -66300,9 +60988,11 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ ** manifest type REAL. */ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ - sqlite3VdbeMemSetNull(pMem); - if( !sqlite3IsNaN(val) ){ - pMem->u.r = val; + if( sqlite3IsNaN(val) ){ + sqlite3VdbeMemSetNull(pMem); + }else{ + sqlite3VdbeMemRelease(pMem); + pMem->r = val; pMem->flags = MEM_Real; } } @@ -66320,11 +61010,10 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ pMem->zMalloc = sqlite3DbMallocRaw(db, 64); if( db->mallocFailed ){ pMem->flags = MEM_Null; - pMem->szMalloc = 0; }else{ assert( pMem->zMalloc ); - pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); - pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); + pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, + sqlite3DbMallocSize(db, pMem->zMalloc)); assert( pMem->u.pRowSet!=0 ); pMem->flags = MEM_RowSet; } @@ -66348,7 +61037,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){ #ifdef SQLITE_DEBUG /* -** This routine prepares a memory cell for modification by breaking +** This routine prepares a memory cell for modication by breaking ** its link to a shallow copy and by marking any current shallow ** copies of this cell as invalid. ** @@ -66368,6 +61057,10 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ } #endif /* SQLITE_DEBUG */ +/* +** Size of struct Mem not including the Mem.zMalloc member. +*/ +#define MEMCELLSIZE offsetof(Mem,zMalloc) /* ** Make an shallow copy of pFrom into pTo. Prior contents of @@ -66375,16 +61068,11 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ -static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){ - vdbeMemClearExternAndSetNull(pTo); - assert( !VdbeMemDynamic(pTo) ); - sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); -} SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); - assert( pTo->db==pFrom->db ); - if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } + VdbeMemRelease(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->xDel = 0; if( (pFrom->flags&MEM_Static)==0 ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); assert( srcType==MEM_Ephem || srcType==MEM_Static ); @@ -66399,14 +61087,12 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int sr SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; - /* The pFrom==0 case in the following assert() is when an sqlite3_value - ** from sqlite3_value_dup() is used as the argument - ** to sqlite3_result_value(). */ - assert( pTo->db==pFrom->db || pFrom->db==0 ); assert( (pFrom->flags & MEM_RowSet)==0 ); - if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); + VdbeMemRelease(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; + pTo->xDel = 0; + if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ pTo->flags |= MEM_Ephem; @@ -66431,7 +61117,8 @@ SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ sqlite3VdbeMemRelease(pTo); memcpy(pTo, pFrom, sizeof(Mem)); pFrom->flags = MEM_Null; - pFrom->szMalloc = 0; + pFrom->xDel = 0; + pFrom->zMalloc = 0; } /* @@ -66478,8 +61165,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ - nByte = sqlite3Strlen30(z); - if( nByte>iLimit ) nByte = iLimit+1; + for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){} }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} } @@ -66498,17 +61184,14 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( if( nByte>iLimit ){ return SQLITE_TOOBIG; } - testcase( nAlloc==0 ); - testcase( nAlloc==31 ); - testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){ + if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){ return SQLITE_NOMEM; } memcpy(pMem->z, z, nAlloc); }else if( xDel==SQLITE_DYNAMIC ){ sqlite3VdbeMemRelease(pMem); pMem->zMalloc = pMem->z = (char *)z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); + pMem->xDel = 0; }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; @@ -66540,25 +61223,41 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( ** key is true to get the key or false to get data. The result is written ** into the pMem element. ** -** The pMem object must have been initialized. This routine will use -** pMem->zMalloc to hold the content from the btree, if possible. New -** pMem->zMalloc space will be allocated if necessary. The calling routine -** is responsible for making sure that the pMem object is eventually -** destroyed. +** The pMem structure is assumed to be uninitialized. Any prior content +** is overwritten without being freed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ -static SQLITE_NOINLINE int vdbeMemFromBtreeResize( +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ - int rc; - pMem->flags = MEM_Null; - if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ + char *zData; /* Data from the btree layer */ + u32 available = 0; /* Number of bytes available on the local btree page */ + int rc = SQLITE_OK; /* Return code */ + + assert( sqlite3BtreeCursorIsValid(pCur) ); + + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + ** that both the BtShared and database handle mutexes are held. */ + assert( (pMem->flags & MEM_RowSet)==0 ); + if( key ){ + zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); + }else{ + zData = (char *)sqlite3BtreeDataFetch(pCur, &available); + } + assert( zData!=0 ); + + if( offset+amt<=available ){ + sqlite3VdbeMemRelease(pMem); + pMem->z = &zData[offset]; + pMem->flags = MEM_Blob|MEM_Ephem; + pMem->n = (int)amt; + }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ @@ -66573,82 +61272,10 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize( sqlite3VdbeMemRelease(pMem); } } - return rc; -} -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( - BtCursor *pCur, /* Cursor pointing at record to retrieve. */ - u32 offset, /* Offset from the start of data to return bytes from. */ - u32 amt, /* Number of bytes to return. */ - int key, /* If true, retrieve from the btree key, not data. */ - Mem *pMem /* OUT: Return data in this Mem structure. */ -){ - char *zData; /* Data from the btree layer */ - u32 available = 0; /* Number of bytes available on the local btree page */ - int rc = SQLITE_OK; /* Return code */ - - assert( sqlite3BtreeCursorIsValid(pCur) ); - assert( !VdbeMemDynamic(pMem) ); - - /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() - ** that both the BtShared and database handle mutexes are held. */ - assert( (pMem->flags & MEM_RowSet)==0 ); - if( key ){ - zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); - }else{ - zData = (char *)sqlite3BtreeDataFetch(pCur, &available); - } - assert( zData!=0 ); - - if( offset+amt<=available ){ - pMem->z = &zData[offset]; - pMem->flags = MEM_Blob|MEM_Ephem; - pMem->n = (int)amt; - }else{ - rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem); - } return rc; } -/* -** The pVal argument is known to be a value other than NULL. -** Convert it into a string with encoding enc and return a pointer -** to a zero-terminated version of that string. -*/ -static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ - assert( pVal!=0 ); - assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); - assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( (pVal->flags & MEM_RowSet)==0 ); - assert( (pVal->flags & (MEM_Null))==0 ); - if( pVal->flags & (MEM_Blob|MEM_Str) ){ - pVal->flags |= MEM_Str; - if( pVal->flags & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pVal); - } - if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ - sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); - } - if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ - assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); - if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ - return 0; - } - } - sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ - }else{ - sqlite3VdbeMemStringify(pVal, enc, 0); - assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); - } - assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 - || pVal->db->mallocFailed ); - if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ - return pVal->z; - }else{ - return 0; - } -} - /* This function is only available internally, it is not part of the ** external API. It works in a similar way to sqlite3_value_text(), ** except the data returned is in the encoding specified by the second @@ -66661,16 +61288,38 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ */ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ if( !pVal ) return 0; + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); assert( (pVal->flags & MEM_RowSet)==0 ); - if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ - return pVal->z; - } + if( pVal->flags&MEM_Null ){ return 0; } - return valueToText(pVal, enc); + assert( (MEM_Blob>>3) == MEM_Str ); + pVal->flags |= (pVal->flags & MEM_Blob)>>3; + ExpandBlob(pVal); + if( pVal->flags&MEM_Str ){ + sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); + if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ + assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); + if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ + return 0; + } + } + sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ + }else{ + assert( (pVal->flags&MEM_Blob)==0 ); + sqlite3VdbeMemStringify(pVal, enc); + assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); + } + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 + || pVal->db->mallocFailed ); + if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ + return pVal->z; + }else{ + return 0; + } } /* @@ -66704,7 +61353,7 @@ struct ValueNewStat4Ctx { ** Otherwise, if the second argument is non-zero, then this function is ** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not ** already been allocated, allocate the UnpackedRecord structure that -** that function will return to its caller here. Then return a pointer to +** that function will return to its caller here. Then return a pointer ** an sqlite3_value within the UnpackedRecord.a[] array. */ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ @@ -66748,113 +61397,6 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ return sqlite3ValueNew(db); } -/* -** The expression object indicated by the second argument is guaranteed -** to be a scalar SQL function. If -** -** * all function arguments are SQL literals, -** * one of the SQLITE_FUNC_CONSTANT or _SLOCHNG function flags is set, and -** * the SQLITE_FUNC_NEEDCOLL function flag is not set, -** -** then this routine attempts to invoke the SQL function. Assuming no -** error occurs, output parameter (*ppVal) is set to point to a value -** object containing the result before returning SQLITE_OK. -** -** Affinity aff is applied to the result of the function before returning. -** If the result is a text value, the sqlite3_value object uses encoding -** enc. -** -** If the conditions above are not met, this function returns SQLITE_OK -** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to -** NULL and an SQLite error code returned. -*/ -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -static int valueFromFunction( - sqlite3 *db, /* The database connection */ - Expr *p, /* The expression to evaluate */ - u8 enc, /* Encoding to use */ - u8 aff, /* Affinity to use */ - sqlite3_value **ppVal, /* Write the new value here */ - struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ -){ - sqlite3_context ctx; /* Context object for function invocation */ - sqlite3_value **apVal = 0; /* Function arguments */ - int nVal = 0; /* Size of apVal[] array */ - FuncDef *pFunc = 0; /* Function definition */ - sqlite3_value *pVal = 0; /* New value */ - int rc = SQLITE_OK; /* Return code */ - int nName; /* Size of function name in bytes */ - ExprList *pList = 0; /* Function arguments */ - int i; /* Iterator variable */ - - assert( pCtx!=0 ); - assert( (p->flags & EP_TokenOnly)==0 ); - pList = p->x.pList; - if( pList ) nVal = pList->nExpr; - nName = sqlite3Strlen30(p->u.zToken); - pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0); - assert( pFunc ); - if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) - ){ - return SQLITE_OK; - } - - if( pList ){ - apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); - if( apVal==0 ){ - rc = SQLITE_NOMEM; - goto value_from_function_out; - } - for(i=0; ia[i].pExpr, enc, aff, &apVal[i]); - if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; - } - } - - pVal = valueNew(db, pCtx); - if( pVal==0 ){ - rc = SQLITE_NOMEM; - goto value_from_function_out; - } - - assert( pCtx->pParse->rc==SQLITE_OK ); - memset(&ctx, 0, sizeof(ctx)); - ctx.pOut = pVal; - ctx.pFunc = pFunc; - pFunc->xFunc(&ctx, nVal, apVal); - if( ctx.isError ){ - rc = ctx.isError; - sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); - }else{ - sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); - assert( rc==SQLITE_OK ); - rc = sqlite3VdbeChangeEncoding(pVal, enc); - if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ - rc = SQLITE_TOOBIG; - pCtx->pParse->nErr++; - } - } - pCtx->pParse->rc = rc; - - value_from_function_out: - if( rc!=SQLITE_OK ){ - pVal = 0; - } - if( apVal ){ - for(i=0; iop)==TK_UPLUS ) pExpr = pExpr->pLeft; + op = pExpr->op; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; - /* Compressed expressions only appear when parsing the DEFAULT clause - ** on a table column definition, and hence only when pCtx==0. This - ** check ensures that an EP_TokenOnly expression is never passed down - ** into valueFromFunction(). */ - assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); - - if( op==TK_CAST ){ - u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); - rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); - testcase( rc!=SQLITE_OK ); - if( *ppVal ){ - sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); - sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); - } - return rc; - } - /* Handle negative integers in a single step. This is needed in the ** case when the value is -9223372036854775808. */ @@ -66925,7 +61450,7 @@ static int valueFromExpr( 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 ){ + if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); }else{ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); @@ -66940,14 +61465,14 @@ static int valueFromExpr( && pVal!=0 ){ sqlite3VdbeMemNumerify(pVal); - if( pVal->flags & MEM_Real ){ - pVal->u.r = -pVal->u.r; - }else if( pVal->u.i==SMALLEST_INT64 ){ - pVal->u.r = -(double)SMALLEST_INT64; - MemSetTypeFlag(pVal, MEM_Real); + if( pVal->u.i==SMALLEST_INT64 ){ + pVal->flags &= ~MEM_Int; + pVal->flags |= MEM_Real; + pVal->r = (double)SMALLEST_INT64; }else{ pVal->u.i = -pVal->u.i; } + pVal->r = -pVal->r; sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_NULL ){ @@ -66969,12 +61494,6 @@ static int valueFromExpr( } #endif -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - else if( op==TK_FUNCTION && pCtx!=0 ){ - rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); - } -#endif - *ppVal = pVal; return rc; @@ -67025,16 +61544,17 @@ static void recordFunc( sqlite3_value **argv ){ const int file_format = 1; - u32 iSerial; /* Serial type */ + int iSerial; /* Serial type */ int nSerial; /* Bytes of space for iSerial as varint */ - u32 nVal; /* Bytes of space required for argv[0] */ + int nVal; /* Bytes of space required for argv[0] */ int nRet; sqlite3 *db; u8 *aRet; UNUSED_PARAMETER( argc ); - iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); + iSerial = sqlite3VdbeSerialType(argv[0], file_format); nSerial = sqlite3VarintLen(iSerial); + nVal = sqlite3VdbeSerialTypeLen(iSerial); db = sqlite3_context_db_handle(context); nRet = 1 + nSerial + nVal; @@ -67043,7 +61563,7 @@ static void recordFunc( sqlite3_result_error_nomem(context); }else{ aRet[0] = nSerial+1; - putVarint32(&aRet[1], iSerial); + sqlite3PutVarint(&aRet[1], iSerial); sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); sqlite3DbFree(db, aRet); @@ -67065,68 +61585,6 @@ SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){ } } -/* -** Attempt to extract a value from pExpr and use it to construct *ppVal. -** -** If pAlloc is not NULL, then an UnpackedRecord object is created for -** pAlloc if one does not exist and the new value is added to the -** UnpackedRecord object. -** -** A value is extracted in the following cases: -** -** * (pExpr==0). In this case the value is assumed to be an SQL NULL, -** -** * The expression is a bound variable, and this is a reprepare, or -** -** * The expression is a literal value. -** -** On success, *ppVal is made to point to the extracted value. The caller -** is responsible for ensuring that the value is eventually freed. -*/ -static int stat4ValueFromExpr( - Parse *pParse, /* Parse context */ - Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ - struct ValueNewStat4Ctx *pAlloc,/* How to allocate space. Or NULL */ - sqlite3_value **ppVal /* OUT: New value object (or NULL) */ -){ - int rc = SQLITE_OK; - sqlite3_value *pVal = 0; - sqlite3 *db = pParse->db; - - /* Skip over any TK_COLLATE nodes */ - pExpr = sqlite3ExprSkipCollate(pExpr); - - if( !pExpr ){ - pVal = valueNew(db, pAlloc); - if( pVal ){ - sqlite3VdbeMemSetNull((Mem*)pVal); - } - }else if( pExpr->op==TK_VARIABLE - || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) - ){ - Vdbe *v; - int iBindVar = pExpr->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); - if( (v = pParse->pReprepare)!=0 ){ - pVal = valueNew(db, pAlloc); - if( pVal ){ - rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); - if( rc==SQLITE_OK ){ - sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); - } - pVal->db = pParse->db; - } - } - }else{ - rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc); - } - - assert( pVal==0 || pVal->db==db ); - *ppVal = pVal; - return rc; -} - /* ** This function is used to allocate and populate UnpackedRecord ** structures intended to be compared against sample index keys stored @@ -67166,88 +61624,50 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue( int iVal, /* Array element to populate */ int *pbOk /* OUT: True if value was extracted */ ){ - int rc; + int rc = SQLITE_OK; sqlite3_value *pVal = 0; - struct ValueNewStat4Ctx alloc; + sqlite3 *db = pParse->db; + + struct ValueNewStat4Ctx alloc; alloc.pParse = pParse; alloc.pIdx = pIdx; alloc.ppRec = ppRec; alloc.iVal = iVal; - rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal); - assert( pVal==0 || pVal->db==pParse->db ); + /* Skip over any TK_COLLATE nodes */ + pExpr = sqlite3ExprSkipCollate(pExpr); + + if( !pExpr ){ + pVal = valueNew(db, &alloc); + if( pVal ){ + sqlite3VdbeMemSetNull((Mem*)pVal); + } + }else if( pExpr->op==TK_VARIABLE + || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) + ){ + Vdbe *v; + int iBindVar = pExpr->iColumn; + sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); + if( (v = pParse->pReprepare)!=0 ){ + pVal = valueNew(db, &alloc); + if( pVal ){ + rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); + if( rc==SQLITE_OK ){ + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); + } + pVal->db = pParse->db; + } + } + }else{ + rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc); + } *pbOk = (pVal!=0); + + assert( pVal==0 || pVal->db==db ); return rc; } -/* -** Attempt to extract a value from expression pExpr using the methods -** as described for sqlite3Stat4ProbeSetValue() above. -** -** If successful, set *ppVal to point to a new value object and return -** SQLITE_OK. If no value can be extracted, but no other error occurs -** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error -** does occur, return an SQLite error code. The final value of *ppVal -** is undefined in this case. -*/ -SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr( - Parse *pParse, /* Parse context */ - Expr *pExpr, /* The expression to extract a value from */ - u8 affinity, /* Affinity to use */ - sqlite3_value **ppVal /* OUT: New value object (or NULL) */ -){ - return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal); -} - -/* -** Extract the iCol-th column from the nRec-byte record in pRec. Write -** the column value into *ppVal. If *ppVal is initially NULL then a new -** sqlite3_value object is allocated. -** -** If *ppVal is initially NULL then the caller is responsible for -** ensuring that the value written into *ppVal is eventually freed. -*/ -SQLITE_PRIVATE int sqlite3Stat4Column( - sqlite3 *db, /* Database handle */ - const void *pRec, /* Pointer to buffer containing record */ - int nRec, /* Size of buffer pRec in bytes */ - int iCol, /* Column to extract */ - sqlite3_value **ppVal /* OUT: Extracted value */ -){ - u32 t; /* a column type code */ - int nHdr; /* Size of the header in the record */ - int iHdr; /* Next unread header byte */ - int iField; /* Next unread data byte */ - int szField; /* Size of the current data field */ - int i; /* Column index */ - u8 *a = (u8*)pRec; /* Typecast byte array */ - Mem *pMem = *ppVal; /* Write result into this Mem object */ - - assert( iCol>0 ); - iHdr = getVarint32(a, nHdr); - if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; - iField = nHdr; - for(i=0; i<=iCol; i++){ - iHdr += getVarint32(&a[iHdr], t); - testcase( iHdr==nHdr ); - testcase( iHdr==nHdr+1 ); - if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT; - szField = sqlite3VdbeSerialTypeLen(t); - iField += szField; - } - testcase( iField==nRec ); - testcase( iField==nRec+1 ); - if( iField>nRec ) return SQLITE_CORRUPT_BKPT; - if( pMem==0 ){ - pMem = *ppVal = sqlite3ValueNew(db); - if( pMem==0 ) return SQLITE_NOMEM; - } - sqlite3VdbeSerialGet(&a[iField-szField], t, pMem); - pMem->enc = ENC(db); - return SQLITE_OK; -} - /* ** Unless it is NULL, the argument must be an UnpackedRecord object returned ** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes @@ -67260,7 +61680,7 @@ SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; ipKeyInfo); sqlite3DbFree(db, pRec); @@ -67291,28 +61711,19 @@ SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){ } /* -** The sqlite3ValueBytes() routine returns the number of bytes in the -** sqlite3_value object assuming that it uses the encoding "enc". -** The valueBytes() routine is a helper function. +** Return the number of bytes in the sqlite3_value object assuming +** that it uses the encoding "enc" */ -static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){ - return valueToText(pVal, enc)!=0 ? pVal->n : 0; -} SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ Mem *p = (Mem*)pVal; - assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 ); - if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){ - return p->n; - } - if( (p->flags & MEM_Blob)!=0 ){ + if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ if( p->flags & MEM_Zero ){ return p->n + p->u.nZero; }else{ return p->n; } } - if( p->flags & MEM_Null ) return 0; - return valueBytes(pVal, enc); + return 0; } /************** End of vdbemem.c *********************************************/ @@ -67329,10 +61740,10 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ ** ************************************************************************* ** This file contains code used for creating, destroying, and populating -** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior +** to version 2.8.7, all this code was combined into the vdbe.c source file. +** But that file was getting too big so this subroutines were split out. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ /* ** Create a new virtual database engine. @@ -67354,21 +61765,9 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ assert( pParse->aLabel==0 ); assert( pParse->nLabel==0 ); assert( pParse->nOpAlloc==0 ); - assert( pParse->szOpAlloc==0 ); return p; } -/* -** Change the error string stored in Vdbe.zErrMsg -*/ -SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){ - va_list ap; - sqlite3DbFree(p->db, p->zErrMsg); - va_start(ap, zFormat); - p->zErrMsg = sqlite3VMPrintf(p->db, zFormat, ap); - va_end(ap); -} - /* ** Remember the SQL string for a prepared statement. */ @@ -67386,9 +61785,9 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepa /* ** Return the SQL associated with a prepared statement */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe *)pStmt; - return p ? p->zSql : 0; + return (p && p->isPrepareV2) ? p->zSql : 0; } /* @@ -67413,39 +61812,21 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ } /* -** Resize the Vdbe.aOp array so that it is at least nOp elements larger -** than its current size. nOp is guaranteed to be less than or equal -** to 1024/sizeof(Op). +** Resize the Vdbe.aOp array so that it is at least one op larger than +** it was. ** ** If an out-of-memory error occurs while resizing the array, return -** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain +** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain ** unchanged (this is so that any opcodes already allocated can be ** correctly deallocated along with the rest of the Vdbe). */ -static int growOpArray(Vdbe *v, int nOp){ +static int growOpArray(Vdbe *v){ VdbeOp *pNew; Parse *p = v->pParse; - - /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force - ** more frequent reallocs and hence provide more opportunities for - ** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used - ** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array - ** by the minimum* amount required until the size reaches 512. Normal - ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current - ** size of the op array or add 1KB of space, whichever is smaller. */ -#ifdef SQLITE_TEST_REALLOC_STRESS - int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp); -#else int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); - UNUSED_PARAMETER(nOp); -#endif - - assert( nOp<=(1024/sizeof(Op)) ); - assert( nNew>=(p->nOpAlloc+nOp) ); pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); if( pNew ){ - p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); - p->nOpAlloc = p->szOpAlloc/sizeof(Op); + p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); v->aOp = pNew; } return (pNew ? SQLITE_OK : SQLITE_NOMEM); @@ -67478,12 +61859,6 @@ static void test_addop_breakpoint(void){ ** the sqlite3VdbeChangeP4() function to change the value of the P4 ** operand. */ -static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ - assert( p->pParse->nOpAlloc<=p->nOp ); - if( growOpArray(p, 1) ) return 1; - assert( p->pParse->nOpAlloc>p->nOp ); - return sqlite3VdbeAddOp3(p, op, p1, p2, p3); -} SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ int i; VdbeOp *pOp; @@ -67492,7 +61867,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ assert( p->magic==VDBE_MAGIC_INIT ); assert( op>0 && op<0xff ); if( p->pParse->nOpAlloc<=i ){ - return growOp3(p, op, p1, p2, p3); + if( growOpArray(p) ){ + return 1; + } } p->nOp++; pOp = &p->aOp[i]; @@ -67540,44 +61917,6 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ return sqlite3VdbeAddOp3(p, op, p1, p2, 0); } -/* Generate code for an unconditional jump to instruction iDest -*/ -SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe *p, int iDest){ - return sqlite3VdbeAddOp3(p, OP_Goto, 0, iDest, 0); -} - -/* Generate code to cause the string zStr to be loaded into -** register iDest -*/ -SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){ - return sqlite3VdbeAddOp4(p, OP_String8, 0, iDest, 0, zStr, 0); -} - -/* -** Generate code that initializes multiple registers to string or integer -** constants. The registers begin with iDest and increase consecutively. -** One register is initialized for each characgter in zTypes[]. For each -** "s" character in zTypes[], the register is a string if the argument is -** not NULL, or OP_Null if the value is a null pointer. For each "i" character -** in zTypes[], the register is initialized to an integer. -*/ -SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){ - va_list ap; - int i; - char c; - va_start(ap, zTypes); - for(i=0; (c = zTypes[i])!=0; i++){ - if( c=='s' ){ - const char *z = va_arg(ap, const char*); - int addr = sqlite3VdbeAddOp2(p, z==0 ? OP_Null : OP_String8, 0, iDest++); - if( z ) sqlite3VdbeChangeP4(p, addr, z, 0); - }else{ - assert( c=='i' ); - sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++); - } - } - va_end(ap); -} /* ** Add an opcode that includes the p4 value as a pointer. @@ -67596,24 +61935,6 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4( return addr; } -/* -** Add an opcode that includes the p4 value with a P4_INT64 or -** P4_REAL type. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8( - 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 */ - const u8 *zP4, /* The P4 operand */ - int p4type /* P4 operand type */ -){ - char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); - if( p4copy ) memcpy(p4copy, zP4, 8); - return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); -} - /* ** Add an OP_ParseSchema opcode. This routine is broken out from ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees @@ -67670,7 +61991,7 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){ if( p->aLabel ){ p->aLabel[i] = -1; } - return ADDR(i); + return -1-i; } /* @@ -67680,11 +62001,10 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){ */ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ Parse *p = v->pParse; - int j = ADDR(x); + int j = -1-x; assert( v->magic==VDBE_MAGIC_INIT ); assert( jnLabel ); - assert( j>=0 ); - if( p->aLabel ){ + if( ALWAYS(j>=0) && p->aLabel ){ p->aLabel[j] = v->nOp; } p->iFixedOp = v->nOp - 1; @@ -67779,7 +62099,6 @@ static Op *opIterNext(VdbeOpIter *p){ ** * OP_VUpdate ** * OP_VRename ** * OP_FkCounter with P2==0 (immediate foreign key constraint) -** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...) ** ** Then check that the value of Parse.mayAbort is true if an ** ABORT may be thrown, or false otherwise. Return true if it does @@ -67790,9 +62109,6 @@ static Op *opIterNext(VdbeOpIter *p){ */ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int hasAbort = 0; - int hasFkCounter = 0; - int hasCreateTable = 0; - int hasInitCoroutine = 0; Op *pOp; VdbeOpIter sIter; memset(&sIter, 0, sizeof(sIter)); @@ -67801,19 +62117,15 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename +#ifndef SQLITE_OMIT_FOREIGN_KEY + || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) +#endif || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; } - if( opcode==OP_CreateTable ) hasCreateTable = 1; - if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ - hasFkCounter = 1; - } -#endif } sqlite3DbFree(v->db, sIter.apSub); @@ -67822,27 +62134,22 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ ** through all opcodes and hasAbort may be set incorrectly. Return ** true for this case to prevent the assert() in the callers frame ** from failing. */ - return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter - || (hasCreateTable && hasInitCoroutine) ); + return ( v->db->mallocFailed || hasAbort==mayAbort ); } #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ /* -** This routine is called after all opcodes have been inserted. It loops -** through all the opcodes and fixes up some details. +** Loop through the program looking for P2 values that are negative +** on jump instructions. Each such value is a label. Resolve the +** label by setting the P2 value to its correct non-zero value. ** -** (1) For each jump instruction with a negative P2 value (a label) -** resolve the P2 value to an actual address. +** This routine is called once after all opcodes have been inserted. ** -** (2) Compute the maximum number of arguments used by any SQL function -** and store that value in *pMaxFuncArgs. +** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument +** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by +** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. ** -** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately -** indicate what the prepared statement actually does. -** -** (4) Initialize the p4.xAdvance pointer on opcodes that use it. -** -** (5) Reclaim the memory allocated for storing labels. +** The Op.opflags field is set on all opcodes. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; @@ -67858,6 +62165,11 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ /* NOTE: Be sure to update mkopcodeh.awk when adding or removing ** cases from this switch! */ switch( opcode ){ + case OP_Function: + case OP_AggStep: { + if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; + break; + } case OP_Transaction: { if( pOp->p2!=0 ) p->readOnly = 0; /* fall thru */ @@ -67907,15 +62219,15 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ pOp->opflags = sqlite3OpcodeProperty[opcode]; if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ - assert( ADDR(pOp->p2)nLabel ); - pOp->p2 = aLabel[ADDR(pOp->p2)]; + assert( -1-pOp->p2nLabel ); + pOp->p2 = aLabel[-1-pOp->p2]; } } sqlite3DbFree(p->db, pParse->aLabel); pParse->aLabel = 0; pParse->nLabel = 0; *pMaxFuncArgs = nMaxArgs; - assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) ); + assert( p->bIsReader!=0 || p->btreeMask==0 ); } /* @@ -67942,7 +62254,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg) assert( aOp && !p->db->mallocFailed ); /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ - assert( DbMaskAllZero(p->btreeMask) ); + assert( p->btreeMask==0 ); resolveP2Values(p, pnMaxArg); *pnOp = p->nOp; @@ -67955,88 +62267,93 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg) ** address of the first operation added. */ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){ - int addr, i; - VdbeOp *pOut; - assert( nOp>0 ); + int addr; assert( p->magic==VDBE_MAGIC_INIT ); - if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){ + if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){ return 0; } addr = p->nOp; - pOut = &p->aOp[addr]; - for(i=0; iopcode = aOp->opcode; - pOut->p1 = aOp->p1; - pOut->p2 = aOp->p2; - assert( aOp->p2>=0 ); - pOut->p3 = aOp->p3; - pOut->p4type = P4_NOTUSED; - pOut->p4.p = 0; - pOut->p5 = 0; + if( ALWAYS(nOp>0) ){ + int i; + VdbeOpList const *pIn = aOp; + for(i=0; ip2; + VdbeOp *pOut = &p->aOp[i+addr]; + pOut->opcode = pIn->opcode; + pOut->p1 = pIn->p1; + if( p2<0 ){ + assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP ); + pOut->p2 = addr + ADDR(p2); + }else{ + pOut->p2 = p2; + } + pOut->p3 = pIn->p3; + pOut->p4type = P4_NOTUSED; + pOut->p4.p = 0; + pOut->p5 = 0; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - pOut->zComment = 0; + pOut->zComment = 0; #endif #ifdef SQLITE_VDBE_COVERAGE - pOut->iSrcLine = iLineno+i; + pOut->iSrcLine = iLineno+i; #else - (void)iLineno; + (void)iLineno; #endif #ifdef SQLITE_DEBUG - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); - } + if( p->db->flags & SQLITE_VdbeAddopTrace ){ + sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); + } #endif + } + p->nOp += nOp; } - p->nOp += nOp; return addr; } -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* -** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). +** Change the value of the P1 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. */ -SQLITE_PRIVATE void sqlite3VdbeScanStatus( - Vdbe *p, /* VM to add scanstatus() to */ - int addrExplain, /* Address of OP_Explain (or 0) */ - int addrLoop, /* Address of loop counter */ - int addrVisit, /* Address of rows visited counter */ - LogEst nEst, /* Estimated number of output rows */ - const char *zName /* Name of table or index being scanned */ -){ - int nByte = (p->nScan+1) * sizeof(ScanStatus); - ScanStatus *aNew; - aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); - if( aNew ){ - ScanStatus *pNew = &aNew[p->nScan++]; - pNew->addrExplain = addrExplain; - pNew->addrLoop = addrLoop; - pNew->addrVisit = addrVisit; - pNew->nEst = nEst; - pNew->zName = sqlite3DbStrDup(p->db, zName); - p->aScan = aNew; +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p1 = val; } } -#endif - /* -** Change the value of the opcode, or P1, P2, P3, or P5 operands -** for a specific instruction. +** Change the value of the P2 operand for a specific instruction. +** This routine is useful for setting a jump destination. */ -SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){ - sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode; -} -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ - sqlite3VdbeGetOp(p,addr)->p1 = val; -} SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ - sqlite3VdbeGetOp(p,addr)->p2 = val; + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p2 = val; + } } + +/* +** Change the value of the P3 operand for a specific instruction. +*/ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ - sqlite3VdbeGetOp(p,addr)->p3 = val; + assert( p!=0 ); + if( ((u32)p->nOp)>addr ){ + p->aOp[addr].p3 = val; + } } -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ - sqlite3VdbeGetOp(p,-1)->p5 = p5; + +/* +** Change the value of the P5 operand for the most recently +** added operation. +*/ +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ + assert( p!=0 ); + if( p->aOp ){ + assert( p->nOp>0 ); + p->aOp[p->nOp-1].p5 = val; + } } /* @@ -68044,8 +62361,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ ** the address of the next instruction to be coded. */ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - p->pParse->iFixedOp = p->nOp - 1; sqlite3VdbeChangeP2(p, addr, p->nOp); + p->pParse->iFixedOp = p->nOp - 1; } @@ -68068,10 +62385,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ if( p4 ){ assert( db ); switch( p4type ){ - case P4_FUNCCTX: { - freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc); - /* Fall through into the next case */ - } case P4_REAL: case P4_INT64: case P4_DYNAMIC: @@ -68083,12 +62396,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); break; } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - case P4_EXPR: { - sqlite3ExprDelete(db, (Expr*)p4); - break; - } -#endif case P4_MPRINTF: { if( db->pnBytesFreed==0 ) sqlite3_free(p4); break; @@ -68102,7 +62409,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ sqlite3ValueFree((sqlite3_value*)p4); }else{ Mem *p = (Mem*)p4; - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); + sqlite3DbFree(db, p->zMalloc); sqlite3DbFree(db, p); } break; @@ -68147,18 +62454,18 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ ** Change the opcode at addr into OP_Noop */ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ - if( addrnOp ){ + if( p->aOp ){ VdbeOp *pOp = &p->aOp[addr]; sqlite3 *db = p->db; freeP4(db, pOp->p4type, pOp->p4.p); memset(pOp, 0, sizeof(pOp[0])); pOp->opcode = OP_Noop; + if( addr==p->nOp-1 ) p->nOp--; } } /* -** If the last opcode is "op" and it is not a jump destination, -** then remove it. Return true if and only if an opcode was removed. +** Remove the last opcode inserted */ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ @@ -68220,15 +62527,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int }else if( n==P4_KEYINFO ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_KEYINFO; -#ifdef SQLITE_ENABLE_CURSOR_HINTS - }else if( n==P4_EXPR ){ - /* Responsibility for deleting the Expr tree is handed over to the - ** VDBE by this operation. The caller should have already invoked - ** sqlite3ExprDup() or whatever other routine is needed to make a - ** private copy of the tree. */ - pOp->p4.pExpr = (Expr*)zP4; - pOp->p4type = P4_EXPR; -#endif }else if( n==P4_VTAB ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_VTAB; @@ -68308,7 +62606,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ ** routine, then a pointer to a dummy VdbeOp will be returned. That opcode ** is readable but not writable, though it is cast to a writable value. ** The return of a dummy opcode allows the call to continue functioning -** after an OOM fault without having to check to see if the return from +** after a OOM fault without having to check to see if the return from ** this routine is a valid pointer. But because the dummy.opcode is 0, ** dummy will never be written to. This is verified by code inspection and ** by running with Valgrind. @@ -68419,84 +62717,9 @@ static int displayComment( } #endif /* SQLITE_DEBUG */ -#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) -/* -** Translate the P4.pExpr value for an OP_CursorHint opcode into text -** that can be displayed in the P4 column of EXPLAIN output. -*/ -static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ - const char *zOp = 0; - int n; - switch( pExpr->op ){ - case TK_STRING: - sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); - break; - case TK_INTEGER: - sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); - break; - case TK_NULL: - sqlite3_snprintf(nTemp, zTemp, "NULL"); - break; - case TK_REGISTER: { - sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); - break; - } - case TK_COLUMN: { - if( pExpr->iColumn<0 ){ - sqlite3_snprintf(nTemp, zTemp, "rowid"); - }else{ - sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); - } - break; - } - case TK_LT: zOp = "LT"; break; - case TK_LE: zOp = "LE"; break; - case TK_GT: zOp = "GT"; break; - case TK_GE: zOp = "GE"; break; - case TK_NE: zOp = "NE"; break; - case TK_EQ: zOp = "EQ"; break; - case TK_IS: zOp = "IS"; break; - case TK_ISNOT: zOp = "ISNOT"; break; - case TK_AND: zOp = "AND"; break; - case TK_OR: zOp = "OR"; break; - case TK_PLUS: zOp = "ADD"; break; - case TK_STAR: zOp = "MUL"; break; - case TK_MINUS: zOp = "SUB"; break; - case TK_REM: zOp = "REM"; break; - case TK_BITAND: zOp = "BITAND"; break; - case TK_BITOR: zOp = "BITOR"; break; - case TK_SLASH: zOp = "DIV"; break; - case TK_LSHIFT: zOp = "LSHIFT"; break; - case TK_RSHIFT: zOp = "RSHIFT"; break; - case TK_CONCAT: zOp = "CONCAT"; break; - case TK_UMINUS: zOp = "MINUS"; break; - case TK_UPLUS: zOp = "PLUS"; break; - case TK_BITNOT: zOp = "BITNOT"; break; - case TK_NOT: zOp = "NOT"; break; - case TK_ISNULL: zOp = "ISNULL"; break; - case TK_NOTNULL: zOp = "NOTNULL"; break; - default: - sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); - break; - } - - if( zOp ){ - sqlite3_snprintf(nTemp, zTemp, "%s(", zOp); - n = sqlite3Strlen30(zTemp); - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft); - if( npRight ){ - zTemp[n++] = ','; - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight); - } - sqlite3_snprintf(nTemp-n, zTemp+n, ")"); - } - return sqlite3Strlen30(zTemp); -} -#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ - - -#if VDBE_DISPLAY_P4 +#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ + || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Compute a string that describes the P4 parameter for an opcode. ** Use zTemp for any required temporary buffer space. @@ -68519,9 +62742,8 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ zColl = "B"; n = 1; } - if( i+n>nTemp-7 ){ + if( i+n>nTemp-6 ){ memcpy(&zTemp[i],",...",4); - i += 4; break; } zTemp[i++] = ','; @@ -68536,12 +62758,6 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ assert( ip4.pExpr); - break; - } -#endif case P4_COLLSEQ: { CollSeq *pColl = pOp->p4.pColl; sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); @@ -68552,13 +62768,6 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); break; } -#ifdef SQLITE_DEBUG - case P4_FUNCCTX: { - FuncDef *pDef = pOp->p4.pCtx->pFunc; - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); - break; - } -#endif case P4_INT64: { sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); break; @@ -68578,7 +62787,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ }else if( pMem->flags & MEM_Int ){ sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); }else if( pMem->flags & MEM_Null ){ sqlite3_snprintf(nTemp, zTemp, "NULL"); }else{ @@ -68590,7 +62799,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); + sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); break; } #endif @@ -68617,7 +62826,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ assert( zP4!=0 ); return zP4; } -#endif /* VDBE_DISPLAY_P4 */ +#endif /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. @@ -68630,9 +62839,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ assert( i>=0 && idb->nDb && i<(int)sizeof(yDbMask)*8 ); assert( i<(int)sizeof(p->btreeMask)*8 ); - DbMaskSet(p->btreeMask, i); + p->btreeMask |= ((yDbMask)1)<db->aDb[i].pBt) ){ - DbMaskSet(p->lockMask, i); + p->lockMask |= ((yDbMask)1)<lockMask) ) return; /* The common case */ + if( p->lockMask==0 ) return; /* The common case */ db = p->db; aDb = db->aDb; nDb = db->nDb; - for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ + for(i=0, mask=1; ilockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ sqlite3BtreeEnter(aDb[i].pBt); } } @@ -68679,24 +62889,22 @@ SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){ /* ** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). */ -static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){ +SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){ int i; + yDbMask mask; sqlite3 *db; Db *aDb; int nDb; + if( p->lockMask==0 ) return; /* The common case */ db = p->db; aDb = db->aDb; nDb = db->nDb; - for(i=0; ilockMask,i) && ALWAYS(aDb[i].pBt!=0) ){ + for(i=0, mask=1; ilockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ sqlite3BtreeLeave(aDb[i].pBt); } } } -SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){ - if( DbMaskAllZero(p->lockMask) ) return; /* The common case */ - vdbeLeave(p); -} #endif #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) @@ -68731,16 +62939,16 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ */ static void releaseMemArray(Mem *p, int N){ if( p && N ){ - Mem *pEnd = &p[N]; + Mem *pEnd; sqlite3 *db = p->db; u8 malloc_failed = db->mallocFailed; if( db->pnBytesFreed ){ - do{ - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); - }while( (++p)zMalloc); + } return; } - do{ + for(pEnd=&p[N]; pflags & MEM_RowSet ); if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); - }else if( p->szMalloc ){ + }else if( p->zMalloc ){ sqlite3DbFree(db, p->zMalloc); - p->szMalloc = 0; + p->zMalloc = 0; } p->flags = MEM_Undefined; - }while( (++p)mallocFailed = malloc_failed; } } @@ -68869,7 +63077,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( }else if( db->u1.isInterrupted ){ p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; - sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); }else{ char *zP4; Op *pOp; @@ -68931,12 +63139,12 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem->u.i = pOp->p3; /* P3 */ pMem++; - if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ + if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */ assert( p->db->mallocFailed ); return SQLITE_ERROR; } pMem->flags = MEM_Str|MEM_Term; - zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); + zP4 = displayP4(pOp, pMem->z, 32); if( zP4!=pMem->z ){ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); }else{ @@ -68947,7 +63155,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem++; if( p->explain==1 ){ - if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ + if( sqlite3VdbeMemGrow(pMem, 4, 0) ){ assert( p->db->mallocFailed ); return SQLITE_ERROR; } @@ -68958,7 +63166,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( pMem++; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ + if( sqlite3VdbeMemGrow(pMem, 500, 0) ){ assert( p->db->mallocFailed ); return SQLITE_ERROR; } @@ -69041,31 +63249,30 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ ** ** nByte is the number of bytes of space needed. ** -** pFrom points to *pnFrom bytes of available space. New space is allocated -** from the end of the pFrom buffer and *pnFrom is decremented. +** *ppFrom points to available space and pEnd points to the end of the +** available space. When space is allocated, *ppFrom is advanced past +** the end of the allocated space. ** -** *pnNeeded is a counter of the number of bytes of space that have failed -** to allocate. If there is insufficient space in pFrom to satisfy the -** request, then increment *pnNeeded by the amount of the request. +** *pnByte is a counter of the number of bytes of space that have failed +** to allocate. If there is insufficient space in *ppFrom to satisfy the +** request, then increment *pnByte by the amount of the request. */ static void *allocSpace( void *pBuf, /* Where return pointer will be stored */ int nByte, /* Number of bytes to allocate */ - u8 *pFrom, /* Memory available for allocation */ - int *pnFrom, /* IN/OUT: Space available at pFrom */ - int *pnNeeded /* If allocation cannot be made, increment *pnByte */ + u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */ + u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */ + int *pnByte /* If allocation cannot be made, increment *pnByte */ ){ - assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); - if( pBuf==0 ){ - nByte = ROUND8(nByte); - if( nByte <= *pnFrom ){ - *pnFrom -= nByte; - pBuf = &pFrom[*pnFrom]; - }else{ - *pnNeeded += nByte; - } + assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) ); + if( pBuf ) return pBuf; + nByte = ROUND8(nByte); + if( &(*ppFrom)[nByte] <= pEnd ){ + pBuf = (void*)*ppFrom; + *ppFrom += nByte; + }else{ + *pnByte += nByte; } - assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); return pBuf; } @@ -69112,13 +63319,13 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ /* ** Prepare a virtual machine for execution for the first time after ** creating the virtual machine. This involves things such -** as allocating registers and initializing the program counter. +** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). ** -** This function may be called exactly once on each virtual machine. +** This function may be called exact once on a each virtual machine. ** After this routine is called the VM has been "packaged" and is ready -** to run. After this routine is called, further calls to +** to run. After this routine is called, futher calls to ** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects ** the Vdbe from the Parse object that helped generate it so that the ** the Vdbe becomes an independent entity and the Parse object can be @@ -69138,8 +63345,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( int nArg; /* Number of arguments in subprograms */ int nOnce; /* Number of OP_Once instructions */ int n; /* Loop counter */ - int nFree; /* Available free space */ u8 *zCsr; /* Memory available for allocation */ + u8 *zEnd; /* First byte past allocated memory */ int nByte; /* How much extra memory is needed */ assert( p!=0 ); @@ -69167,27 +63374,20 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( */ nMem += nCursor; - /* zCsr will initially point to nFree bytes of unused space at the - ** end of the opcode array, p->aOp. The computation of nFree is - ** conservative - it might be smaller than the true number of free - ** bytes, but never larger. nFree must be a multiple of 8 - it is - ** rounded down if is not. + /* Allocate space for memory registers, SQL variables, VDBE cursors and + ** an array to marshal SQL function arguments in. */ - n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */ - zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */ - assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); - nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */ - assert( nFree>=0 ); - if( nFree>0 ){ - memset(zCsr, 0, nFree); - assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) ); - } + zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */ + zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */ resolveP2Values(p, &nArg); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); if( pParse->explain && nMem<10 ){ nMem = 10; } + memset(zCsr, 0, zEnd-zCsr); + zCsr += (zCsr - (u8*)0)&7; + assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); p->expired = 0; /* Memory for registers, parameters, cursor, etc, is allocated in two @@ -69202,21 +63402,18 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( */ do { nByte = 0; - p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte); - p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte); - p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte); - p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), zCsr, &nFree, &nByte); + p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); + p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); + p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); + p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), - zCsr, &nFree, &nByte); - p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte); -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); -#endif + &zCsr, zEnd, &nByte); + p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; - nFree = nByte; + zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); p->nCursor = nCursor; @@ -69228,7 +63425,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( p->aVar[n].db = db; } } - if( p->azVar && pParse->nzVar>0 ){ + if( p->azVar ){ p->nzVar = pParse->nzVar; memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); @@ -69253,50 +63450,23 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } - assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE ); - switch( pCx->eCurType ){ - case CURTYPE_SORTER: { - sqlite3VdbeSorterClose(p->db, pCx); - break; - } - case CURTYPE_BTREE: { - if( pCx->pBt ){ - sqlite3BtreeClose(pCx->pBt); - /* The pCx->pCursor will be close automatically, if it exists, by - ** the call above. */ - }else{ - assert( pCx->uc.pCursor!=0 ); - sqlite3BtreeCloseCursor(pCx->uc.pCursor); - } - break; - } + sqlite3VdbeSorterClose(p->db, pCx); + if( pCx->pBt ){ + sqlite3BtreeClose(pCx->pBt); + /* The pCx->pCursor will be close automatically, if it exists, by + ** the call above. */ + }else if( pCx->pCursor ){ + sqlite3BtreeCloseCursor(pCx->pCursor); + } #ifndef SQLITE_OMIT_VIRTUALTABLE - case CURTYPE_VTAB: { - sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur; - const sqlite3_module *pModule = pVCur->pVtab->pModule; - assert( pVCur->pVtab->nRef>0 ); - pVCur->pVtab->nRef--; - pModule->xClose(pVCur); - break; - } + if( pCx->pVtabCursor ){ + sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; + const sqlite3_module *pModule = pVtabCursor->pVtab->pModule; + p->inVtabMethod = 1; + pModule->xClose(pVtabCursor); + p->inVtabMethod = 0; + } #endif - } -} - -/* -** Close all cursors in the current frame. -*/ -static void closeCursorsInFrame(Vdbe *p){ - if( p->apCsr ){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } - } - } } /* @@ -69306,10 +63476,6 @@ static void closeCursorsInFrame(Vdbe *p){ */ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; - closeCursorsInFrame(v); -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - v->anExec = pFrame->anExec; -#endif v->aOnceFlag = pFrame->aOnceFlag; v->nOnceFlag = pFrame->nOnceFlag; v->aOp = pFrame->aOp; @@ -69320,7 +63486,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ v->nCursor = pFrame->nCursor; v->db->lastRowid = pFrame->lastRowid; v->nChange = pFrame->nChange; - v->db->nChange = pFrame->nDbChange; return pFrame->pc; } @@ -69337,11 +63502,20 @@ static void closeAllCursors(Vdbe *p){ VdbeFrame *pFrame; for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); sqlite3VdbeFrameRestore(pFrame); - p->pFrame = 0; - p->nFrame = 0; } - assert( p->nFrame==0 ); - closeCursorsInFrame(p); + p->pFrame = 0; + p->nFrame = 0; + + if( p->apCsr ){ + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } + } if( p->aMem ){ releaseMemArray(&p->aMem[1], p->nMem); } @@ -69352,12 +63526,16 @@ static void closeAllCursors(Vdbe *p){ } /* Delete any auxdata allocations made by the VM */ - if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0); + sqlite3VdbeDeleteAuxData(p, -1, 0); assert( p->pAuxData==0 ); } /* -** Clean up the VM after a single run. +** Clean up the VM after execution. +** +** This routine will automatically close any cursors, lists, and/or +** sorters that were left open. It also deletes the values of +** variables in the aVar[] array. */ static void Cleanup(Vdbe *p){ sqlite3 *db = p->db; @@ -69525,7 +63703,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ /* The complex case - There is a multi-file write-transaction active. ** This requires a master journal file to ensure the transaction is - ** committed atomically. + ** committed atomicly. */ #ifndef SQLITE_OMIT_DISKIO else{ @@ -69644,7 +63822,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3OsDelete(pVfs, zMaster, needSync); + rc = sqlite3OsDelete(pVfs, zMaster, 1); sqlite3DbFree(db, zMaster); zMaster = 0; if( rc ){ @@ -69693,7 +63871,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){ int nRead = 0; p = db->pVdbe; while( p ){ - if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){ + if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ cnt++; if( p->readOnly==0 ) nWrite++; if( p->bIsReader ) nRead++; @@ -69791,7 +63969,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; - sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); + sqlite3SetString(&p->zErrMsg, db, "FOREIGN KEY constraint failed"); return SQLITE_ERROR; } return SQLITE_OK; @@ -69853,6 +64031,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ /* Check for one of the special errors */ mrc = p->rc & 0xff; + assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */ isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; if( isSpecialError ){ @@ -69878,7 +64057,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; - p->nChange = 0; } } } @@ -69919,7 +64097,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ }else if( rc!=SQLITE_OK ){ p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); - p->nChange = 0; }else{ db->nDeferredCons = 0; db->nDeferredImmCons = 0; @@ -69928,7 +64105,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ } }else{ sqlite3RollbackAll(db, SQLITE_OK); - p->nChange = 0; } db->nStatement = 0; }else if( eStatementOp==0 ){ @@ -69940,7 +64116,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; - p->nChange = 0; } } @@ -69961,7 +64136,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; - p->nChange = 0; } } @@ -70037,7 +64211,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ db->mallocFailed = mallocFailed; db->errCode = rc; }else{ - sqlite3Error(db, rc); + sqlite3Error(db, rc, 0); } return rc; } @@ -70100,7 +64274,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); + sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } @@ -70178,7 +64352,7 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ ** from left to right), or ** ** * the corresponding bit in argument mask is clear (where the first -** function parameter corresponds to bit 0 etc.). +** function parameter corrsponds to bit 0 etc.). */ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){ AuxData **pp = &pVdbe->pAuxData; @@ -70223,11 +64397,9 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - for(i=0; inScan; i++){ - sqlite3DbFree(db, p->aScan[i].zName); - } - sqlite3DbFree(db, p->aScan); +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) + sqlite3DbFree(db, p->zExplain); + sqlite3DbFree(db, p->pExplain); #endif } @@ -70255,60 +64427,6 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ sqlite3DbFree(db, p); } -/* -** The cursor "p" has a pending seek operation that has not yet been -** carried out. Seek the cursor now. If an error occurs, return -** the appropriate error code. -*/ -static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){ - int res, rc; -#ifdef SQLITE_TEST - extern int sqlite3_search_count; -#endif - assert( p->deferredMoveto ); - assert( p->isTable ); - assert( p->eCurType==CURTYPE_BTREE ); - rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res); - if( rc ) return rc; - if( res!=0 ) return SQLITE_CORRUPT_BKPT; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - p->deferredMoveto = 0; - p->cacheStatus = CACHE_STALE; - return SQLITE_OK; -} - -/* -** Something has moved cursor "p" out of place. Maybe the row it was -** pointed to was deleted out from under it. Or maybe the btree was -** rebalanced. Whatever the cause, try to restore "p" to the place it -** is supposed to be pointing. If the row was deleted out from under the -** cursor, set the cursor to point to a NULL row. -*/ -static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ - int isDifferentRow, rc; - assert( p->eCurType==CURTYPE_BTREE ); - assert( p->uc.pCursor!=0 ); - assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ); - rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow); - p->cacheStatus = CACHE_STALE; - if( isDifferentRow ) p->nullRow = 1; - return rc; -} - -/* -** Check to ensure that the cursor is valid. Restore the cursor -** if need be. Return any I/O error from the restore operation. -*/ -SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ - assert( p->eCurType==CURTYPE_BTREE ); - if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return handleMovedCursor(p); - } - return SQLITE_OK; -} - /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error @@ -70323,12 +64441,29 @@ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ ** not been deleted out from under the cursor, then this routine is a no-op. */ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ - if( p->eCurType==CURTYPE_BTREE ){ - if( p->deferredMoveto ){ - return handleDeferredMoveto(p); - } - if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return handleMovedCursor(p); + if( p->deferredMoveto ){ + int res, rc; +#ifdef SQLITE_TEST + extern int sqlite3_search_count; +#endif + assert( p->isTable ); + rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); + if( rc ) return rc; + p->lastRowid = p->movetoTarget; + if( res!=0 ) return SQLITE_CORRUPT_BKPT; + p->rowidIsValid = 1; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + p->deferredMoveto = 0; + p->cacheStatus = CACHE_STALE; + }else if( p->pCursor ){ + int hasMoved; + int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); + if( rc ) return rc; + if( hasMoved ){ + p->cacheStatus = CACHE_STALE; + if( hasMoved==2 ) p->nullRow = 1; } } return SQLITE_OK; @@ -70379,13 +64514,11 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ /* ** Return the serial-type for the value stored in pMem. */ -SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ +SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ int flags = pMem->flags; - u32 n; + int n; - assert( pLen!=0 ); if( flags&MEM_Null ){ - *pLen = 0; return 0; } if( flags&MEM_Int ){ @@ -70394,76 +64527,44 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ i64 i = pMem->u.i; u64 u; if( i<0 ){ - u = ~i; + if( i<(-MAX_6BYTE) ) return 6; + /* Previous test prevents: u = -(-9223372036854775808) */ + u = -i; }else{ u = i; } if( u<=127 ){ - if( (i&1)==i && file_format>=4 ){ - *pLen = 0; - return 8+(u32)u; - }else{ - *pLen = 1; - return 1; - } + return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1; } - if( u<=32767 ){ *pLen = 2; return 2; } - if( u<=8388607 ){ *pLen = 3; return 3; } - if( u<=2147483647 ){ *pLen = 4; return 4; } - if( u<=MAX_6BYTE ){ *pLen = 6; return 5; } - *pLen = 8; + if( u<=32767 ) return 2; + if( u<=8388607 ) return 3; + if( u<=2147483647 ) return 4; + if( u<=MAX_6BYTE ) return 5; return 6; } if( flags&MEM_Real ){ - *pLen = 8; return 7; } assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); - assert( pMem->n>=0 ); - n = (u32)pMem->n; + n = pMem->n; if( flags & MEM_Zero ){ n += pMem->u.nZero; } - *pLen = n; + assert( n>=0 ); return ((n*2) + 12 + ((flags&MEM_Str)!=0)); } -/* -** The sizes for serial types less than 128 -*/ -static const u8 sqlite3SmallTypeSizes[] = { - /* 0 1 2 3 4 5 6 7 8 9 */ -/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, -/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, -/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, -/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, -/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, -/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, -/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, -/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, -/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, -/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, -/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, -/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, -/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57 -}; - /* ** Return the length of the data corresponding to the supplied serial-type. */ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ - if( serial_type>=128 ){ + if( serial_type>=12 ){ return (serial_type-12)/2; }else{ - assert( serial_type<12 - || sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 ); - return sqlite3SmallTypeSizes[serial_type]; + static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; + return aSize[serial_type]; } } -SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){ - assert( serial_type<128 ); - return sqlite3SmallTypeSizes[serial_type]; -} /* ** If we are on an architecture with mixed-endian floating @@ -70539,18 +64640,17 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ u64 v; u32 i; if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pMem->u.r) ); - memcpy(&v, &pMem->u.r, sizeof(v)); + assert( sizeof(v)==sizeof(pMem->r) ); + memcpy(&v, &pMem->r, sizeof(v)); swapMixedEndianFloat(v); }else{ v = pMem->u.i; } - len = i = sqlite3SmallTypeSizes[serial_type]; - assert( i>0 ); - do{ - buf[--i] = (u8)(v&0xFF); + len = i = sqlite3VdbeSerialTypeLen(serial_type); + while( i-- ){ + buf[i] = (u8)(v&0xFF); v >>= 8; - }while( i ); + } return len; } @@ -70559,7 +64659,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) == (int)sqlite3VdbeSerialTypeLen(serial_type) ); len = pMem->n; - if( len>0 ) memcpy(buf, pMem->z, len); + memcpy(buf, pMem->z, len); return len; } @@ -70574,105 +64674,51 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ #define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) #define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) #define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) -#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. -** -** This function is implemented as two separate routines for performance. -** The few cases that require local variables are broken out into a separate -** routine so that in most cases the overhead of moving the stack pointer -** is avoided. */ -static u32 SQLITE_NOINLINE serialGet( - const unsigned char *buf, /* Buffer to deserialize from */ - u32 serial_type, /* Serial type to deserialize */ - Mem *pMem /* Memory cell to write value into */ -){ - u64 x = FOUR_BYTE_UINT(buf); - u32 y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) + y; - if( serial_type==6 ){ - /* EVIDENCE-OF: R-29851-52272 Value is a big-endian 64-bit - ** twos-complement integer. */ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - }else{ - /* EVIDENCE-OF: R-57343-49114 Value is a big-endian IEEE 754-2008 64-bit - ** floating point number. */ -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->u.r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real; - } - return 8; -} SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ + u64 x; + u32 y; switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ - case 0: { /* Null */ - /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ + case 0: { /* NULL */ pMem->flags = MEM_Null; break; } - case 1: { - /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement - ** integer. */ + case 1: { /* 1-byte signed integer */ pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 1; } case 2: { /* 2-byte signed integer */ - /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit - ** twos-complement integer. */ pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 2; } case 3: { /* 3-byte signed integer */ - /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit - ** twos-complement integer. */ pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 3; } case 4: { /* 4-byte signed integer */ - /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit - ** twos-complement integer. */ - pMem->u.i = FOUR_BYTE_INT(buf); -#ifdef __HP_cc - /* Work around a sign-extension bug in the HP compiler for HP/UX */ - if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL; -#endif + y = FOUR_BYTE_UINT(buf); + pMem->u.i = (i64)*(int*)&y; pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 4; } case 5: { /* 6-byte signed integer */ - /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit - ** twos-complement integer. */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); @@ -70680,32 +64726,52 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ - /* These use local variables, so do them in a separate routine - ** to avoid having to move the frame pointer in the common case */ - return serialGet(buf,serial_type,pMem); +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + x = FOUR_BYTE_UINT(buf); + y = FOUR_BYTE_UINT(buf+4); + x = (x<<32) | y; + if( serial_type==6 ){ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + }else{ + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + } + return 8; } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ - /* EVIDENCE-OF: R-12976-22893 Value is the integer 0. */ - /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; return 0; } default: { - /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in - ** length. - ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and - ** (N-13)/2 bytes in length. */ static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; + u32 len = (serial_type-12)/2; pMem->z = (char *)buf; - pMem->n = (serial_type-12)/2; + pMem->n = len; + pMem->xDel = 0; pMem->flags = aFlag[serial_type&1]; - return pMem->n; + return len; } } return 0; } + /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if @@ -70775,17 +64841,17 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( idx = getVarint32(aKey, szHdr); d = szHdr; u = 0; - while( idxnField && d<=nKey ){ u32 serial_type; idx += getVarint32(&aKey[idx], serial_type); pMem->enc = pKeyInfo->enc; pMem->db = pKeyInfo->db; /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ - pMem->szMalloc = 0; + pMem->zMalloc = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); pMem++; - if( (++u)>=p->nField ) break; + u++; } assert( u<=pKeyInfo->nField + 1 ); p->nField = u; @@ -70799,14 +64865,10 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used ** in assert() statements to ensure that the optimized code in ** sqlite3VdbeRecordCompare() returns results with these two primitives. -** -** Return true if the result of comparison is equivalent to desiredResult. -** Return false if there is a disagreement. */ static int vdbeRecordCompareDebug( int nKey1, const void *pKey1, /* Left key */ - const UnpackedRecord *pPKey2, /* Right key */ - int desiredResult /* Correct answer */ + const UnpackedRecord *pPKey2 /* Right key */ ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ @@ -70818,11 +64880,10 @@ static int vdbeRecordCompareDebug( Mem mem1; pKeyInfo = pPKey2->pKeyInfo; - if( pKeyInfo->db==0 ) return 1; mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ - VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ /* Compilers may complain that mem1.u.i is potentially uninitialized. ** We could initialize it, as shown here, to silence those complaints. @@ -70834,7 +64895,6 @@ static int vdbeRecordCompareDebug( /* mem1.u.i = 0; // not needed, here to silence compiler warning */ idx1 = getVarint32(aKey1, szHdr1); - if( szHdr1>98307 ) return SQLITE_CORRUPT; d1 = szHdr1; assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); assert( pKeyInfo->aSortOrder!=0 ); @@ -70866,11 +64926,11 @@ static int vdbeRecordCompareDebug( */ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); if( rc!=0 ){ - assert( mem1.szMalloc==0 ); /* See comment below */ + assert( mem1.zMalloc==0 ); /* See comment below */ if( pKeyInfo->aSortOrder[i] ){ rc = -rc; /* Invert the result for DESC sort order. */ } - goto debugCompareEnd; + return rc; } i++; }while( idx1nField ); @@ -70879,59 +64939,15 @@ static int vdbeRecordCompareDebug( ** the following assert(). If the assert() fails, it indicates a ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ - assert( mem1.szMalloc==0 ); + assert( mem1.zMalloc==0 ); /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. Return the default_rc + ** all the fields up to that point were equal. Return the the default_rc ** value. */ - rc = pPKey2->default_rc; - -debugCompareEnd: - if( desiredResult==0 && rc==0 ) return 1; - if( desiredResult<0 && rc<0 ) return 1; - if( desiredResult>0 && rc>0 ) return 1; - if( CORRUPT_DB ) return 1; - if( pKeyInfo->db->mallocFailed ) return 1; - return 0; + return pPKey2->default_rc; } #endif -#if SQLITE_DEBUG -/* -** Count the number of fields (a.k.a. columns) in the record given by -** pKey,nKey. The verify that this count is less than or equal to the -** limit given by pKeyInfo->nField + pKeyInfo->nXField. -** -** If this constraint is not satisfied, it means that the high-speed -** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will -** not work correctly. If this assert() ever fires, it probably means -** that the KeyInfo.nField or KeyInfo.nXField values were computed -** incorrectly. -*/ -static void vdbeAssertFieldCountWithinLimits( - int nKey, const void *pKey, /* The record to verify */ - const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */ -){ - int nField = 0; - u32 szHdr; - u32 idx; - u32 notUsed; - const unsigned char *aKey = (const unsigned char*)pKey; - - if( CORRUPT_DB ) return; - idx = getVarint32(aKey, szHdr); - assert( nKey>=0 ); - assert( szHdr<=(u32)nKey ); - while( idxnField+pKeyInfo->nXField ); -} -#else -# define vdbeAssertFieldCountWithinLimits(A,B,C) -#endif - /* ** Both *pMem1 and *pMem2 contain string values. Compare the two values ** using the collation sequence pColl. As usual, return a negative , zero @@ -70941,8 +64957,7 @@ static void vdbeAssertFieldCountWithinLimits( static int vdbeCompareMemString( const Mem *pMem1, const Mem *pMem2, - const CollSeq *pColl, - u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */ + const CollSeq *pColl ){ if( pMem1->enc==pColl->enc ){ /* The strings are already in the correct encoding. Call the @@ -70954,8 +64969,8 @@ static int vdbeCompareMemString( int n1, n2; Mem c1; Mem c2; - sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); - sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); + memset(&c1, 0, sizeof(c1)); + memset(&c2, 0, sizeof(c2)); sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); @@ -70965,51 +64980,10 @@ static int vdbeCompareMemString( rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); sqlite3VdbeMemRelease(&c1); sqlite3VdbeMemRelease(&c2); - if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM; return rc; } } -/* -** Compare two blobs. Return negative, zero, or positive if the first -** is less than, equal to, or greater than the second, respectively. -** If one blob is a prefix of the other, then the shorter is the lessor. -*/ -static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ - int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n); - if( c ) return c; - return pB1->n - pB2->n; -} - -/* -** Do a comparison between a 64-bit signed integer and a 64-bit floating-point -** number. Return negative, zero, or positive if the first (i64) is less than, -** equal to, or greater than the second (double). -*/ -static int sqlite3IntFloatCompare(i64 i, double r){ - if( sizeof(LONGDOUBLE_TYPE)>8 ){ - LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; - if( xr ) return +1; - return 0; - }else{ - i64 y; - double s; - if( r<-9223372036854775808.0 ) return +1; - if( r>9223372036854775807.0 ) return -1; - y = (i64)r; - if( iy ){ - if( y==SMALLEST_INT64 && r>0.0 ) return -1; - return +1; - } - s = (double)i; - if( sr ) return +1; - return 0; - } -} - /* ** Compare the values contained by the two memory cells, returning ** negative, zero or positive if pMem1 is less than, equal to, or greater @@ -71020,6 +64994,7 @@ static int sqlite3IntFloatCompare(i64 i, double r){ ** Two NULL values are considered equal by this function. */ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int rc; int f1, f2; int combined_flags; @@ -71035,34 +65010,34 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C return (f2&MEM_Null) - (f1&MEM_Null); } - /* At least one of the two values is a number + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. */ if( combined_flags&(MEM_Int|MEM_Real) ){ + double r1, r2; if( (f1 & f2 & MEM_Int)!=0 ){ if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return +1; + if( pMem1->u.i > pMem2->u.i ) return 1; return 0; } - if( (f1 & f2 & MEM_Real)!=0 ){ - if( pMem1->u.r < pMem2->u.r ) return -1; - if( pMem1->u.r > pMem2->u.r ) return +1; - return 0; - } - if( (f1&MEM_Int)!=0 ){ - if( (f2&MEM_Real)!=0 ){ - return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r); - }else{ - return -1; - } - } if( (f1&MEM_Real)!=0 ){ - if( (f2&MEM_Int)!=0 ){ - return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r); - }else{ - return -1; - } + r1 = pMem1->r; + }else if( (f1&MEM_Int)!=0 ){ + r1 = (double)pMem1->u.i; + }else{ + return 1; } - return +1; + if( (f2&MEM_Real)!=0 ){ + r2 = pMem2->r; + }else if( (f2&MEM_Int)!=0 ){ + r2 = (double)pMem2->u.i; + }else{ + return -1; + } + if( r1r2 ) return 1; + return 0; } /* If one value is a string and the other is a blob, the string is less. @@ -71076,7 +65051,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C return -1; } - assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed ); + assert( pMem1->enc==pMem2->enc ); assert( pMem1->enc==SQLITE_UTF8 || pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); @@ -71087,14 +65062,18 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C assert( !pColl || pColl->xCmp ); if( pColl ){ - return vdbeCompareMemString(pMem1, pMem2, pColl, 0); + return vdbeCompareMemString(pMem1, pMem2, pColl); } /* If a NULL pointer was passed as the collate function, fall through ** to the blob case and use memcmp(). */ } /* Both values must be blobs. Compare using memcmp(). */ - return sqlite3BlobCompare(pMem1, pMem2); + rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); + if( rc==0 ){ + rc = pMem1->n - pMem2->n; + } + return rc; } @@ -71144,7 +65123,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero ** or positive integer if key1 is less than, equal to or ** greater than key2. The {nKey1, pKey1} key must be a blob -** created by the OP_MakeRecord opcode of the VDBE. The pPKey2 +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 ** key must be a parsed key such as obtained from ** sqlite3VdbeParseRecord. ** @@ -71155,12 +65134,10 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ ** fields that appear in both keys are equal, then pPKey2->default_rc is ** returned. ** -** If database corruption is discovered, set pPKey2->errCode to -** SQLITE_CORRUPT and return 0. If an OOM error is encountered, -** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the -** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). +** If database corruption is discovered, set pPKey2->isCorrupt to non-zero +** and return 0. */ -SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( +SQLITE_PRIVATE int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ @@ -71189,13 +65166,13 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; if( d1>(unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ } i = 0; } - VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); assert( pPKey2->pKeyInfo->aSortOrder!=0 ); @@ -71208,13 +65185,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( if( pRhs->flags & MEM_Int ){ serial_type = aKey1[idx1]; testcase( serial_type==12 ); - if( serial_type>=10 ){ + if( serial_type>=12 ){ rc = +1; }else if( serial_type==0 ){ rc = -1; }else if( serial_type==7 ){ + double rhs = (double)pRhs->u.i; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); - rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r); + if( mem1.rrhs ){ + rc = +1; + } }else{ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); i64 rhs = pRhs->u.i; @@ -71229,24 +65211,23 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* RHS is real */ else if( pRhs->flags & MEM_Real ){ serial_type = aKey1[idx1]; - if( serial_type>=10 ){ - /* Serial types 12 or greater are strings and blobs (greater than - ** numbers). Types 10 and 11 are currently "reserved for future - ** use", so it doesn't really matter what the results of comparing - ** them to numberic values are. */ + if( serial_type>=12 ){ rc = +1; }else if( serial_type==0 ){ rc = -1; }else{ + double rhs = pRhs->r; + double lhs; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); if( serial_type==7 ){ - if( mem1.u.ru.r ){ - rc = -1; - }else if( mem1.u.r>pRhs->u.r ){ - rc = +1; - } + lhs = mem1.r; }else{ - rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r); + lhs = (double)mem1.u.i; + } + if( lhsrhs ){ + rc = +1; } } } @@ -71264,16 +65245,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( testcase( (d1+mem1.n)==(unsigned)nKey1 ); testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); if( (d1+mem1.n) > (unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ }else if( pKeyInfo->aColl[i] ){ mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; mem1.flags = MEM_Str; mem1.z = (char*)&aKey1[d1]; - rc = vdbeCompareMemString( - &mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode - ); + rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]); }else{ int nCmp = MIN(mem1.n, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); @@ -71293,7 +65272,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( testcase( (d1+nStr)==(unsigned)nKey1 ); testcase( (d1+nStr+1)==(unsigned)nKey1 ); if( (d1+nStr) > (unsigned)nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ }else{ int nCmp = MIN(nStr, pRhs->n); @@ -71313,8 +65292,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( if( pKeyInfo->aSortOrder[i] ){ rc = -rc; } - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); - assert( mem1.szMalloc==0 ); /* See comment below */ + assert( CORRUPT_DB + || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + || pKeyInfo->db->mallocFailed + ); + assert( mem1.zMalloc==0 ); /* See comment below */ return rc; } @@ -71327,25 +65310,16 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( /* No memory allocation is ever used on mem1. Prove this using ** the following assert(). If the assert() fails, it indicates a ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ - assert( mem1.szMalloc==0 ); + assert( mem1.zMalloc==0 ); /* rc==0 here means that one or both of the keys ran out of fields and - ** all the fields up to that point were equal. Return the default_rc + ** all the fields up to that point were equal. Return the the default_rc ** value. */ assert( CORRUPT_DB - || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) - || pKeyInfo->db->mallocFailed + || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2) ); - pPKey2->eqSeen = 1; return pPKey2->default_rc; } -SQLITE_PRIVATE int sqlite3VdbeRecordCompare( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); -} - /* ** This function is an optimized version of sqlite3VdbeRecordCompare() @@ -71358,7 +65332,8 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( */ static int vdbeRecordCompareInt( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ + int bSkip /* Ignored */ ){ const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; int serial_type = ((const u8*)pKey1)[1]; @@ -71367,8 +65342,9 @@ static int vdbeRecordCompareInt( u64 x; i64 v = pPKey2->aMem[0].u.i; i64 lhs; + UNUSED_PARAMETER(bSkip); - vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); + assert( bSkip==0 ); assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB ); switch( serial_type ){ case 1: { /* 1-byte signed integer */ @@ -71418,10 +65394,10 @@ static int vdbeRecordCompareInt( ** (as gcc is clever enough to combine the two like cases). Other ** compilers might be similar. */ case 0: case 7: - return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); default: - return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); } if( v>lhs ){ @@ -71431,15 +65407,18 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ res = pPKey2->default_rc; - pPKey2->eqSeen = 1; } - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) ); + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + || CORRUPT_DB + ); return res; } @@ -71451,15 +65430,17 @@ static int vdbeRecordCompareInt( */ static int vdbeRecordCompareString( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ + int bSkip ){ const u8 *aKey1 = (const u8*)pKey1; int serial_type; int res; + UNUSED_PARAMETER(bSkip); - assert( pPKey2->aMem[0].flags & MEM_Str ); - vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); + assert( bSkip==0 ); getVarint32(&aKey1[1], serial_type); + if( serial_type<12 ){ res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ }else if( !(serial_type & 0x01) ){ @@ -71471,7 +65452,7 @@ static int vdbeRecordCompareString( nStr = (serial_type-12) / 2; if( (szHdr + nStr) > nKey1 ){ - pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ } nCmp = MIN( pPKey2->aMem[0].n, nStr ); @@ -71481,10 +65462,9 @@ static int vdbeRecordCompareString( res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; - pPKey2->eqSeen = 1; } }else if( res>0 ){ res = pPKey2->r2; @@ -71498,9 +65478,10 @@ static int vdbeRecordCompareString( } } - assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) || CORRUPT_DB - || pPKey2->pKeyInfo->db->mallocFailed ); return res; } @@ -71564,6 +65545,8 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ u32 lenRowid; /* Size of the rowid */ Mem m, v; + UNUSED_PARAMETER(db); + /* Get the size of the index entry. Only indices entries of less ** than 2GiB are support - anything large must be database corruption. ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so @@ -71575,7 +65558,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ - sqlite3VdbeMemInit(&m, db, 0); + memset(&m, 0, sizeof(m)); rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m); if( rc ){ return rc; @@ -71603,7 +65586,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ goto idx_rowid_corruption; } - lenRowid = sqlite3SmallTypeSizes[typeRowid]; + lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); testcase( (u32)m.n==szHdr+lenRowid ); if( unlikely((u32)m.npCursor; Mem m; - assert( pC->eCurType==CURTYPE_BTREE ); - pCur = pC->uc.pCursor; assert( sqlite3BtreeCursorIsValid(pCur) ); VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ @@ -71656,12 +65636,12 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( *res = 0; return SQLITE_CORRUPT_BKPT; } - sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m); + memset(&m, 0, sizeof(m)); + rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m); if( rc ){ return rc; } - *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0); sqlite3VdbeMemRelease(&m); return SQLITE_OK; } @@ -71778,8 +65758,6 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ ** This file contains code use to implement APIs that are part of the ** VDBE. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_DEPRECATED /* @@ -71790,7 +65768,7 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ ** collating sequences are registered or if an authorizer function is ** added or changed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p==0 || p->expired; } @@ -71818,31 +65796,6 @@ static int vdbeSafetyNotNull(Vdbe *p){ } } -#ifndef SQLITE_OMIT_TRACE -/* -** Invoke the profile callback. This routine is only called if we already -** know that the profile callback is defined and needs to be invoked. -*/ -static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ - sqlite3_int64 iNow; - assert( p->startTime>0 ); - assert( db->xProfile!=0 ); - assert( db->init.busy==0 ); - assert( p->zSql!=0 ); - sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); - db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); - p->startTime = 0; -} -/* -** The checkProfileCallback(DB,P) macro checks to see if a profile callback -** is needed, and it invokes the callback if it is needed. -*/ -# define checkProfileCallback(DB,P) \ - if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); } -#else -# define checkProfileCallback(DB,P) /*no-op*/ -#endif - /* ** The following routine destroys a virtual machine that is created by ** the sqlite3_compile() routine. The integer returned is an SQLITE_ @@ -71852,7 +65805,7 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL @@ -71863,7 +65816,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); - checkProfileCallback(db, v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); @@ -71879,20 +65831,18 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; - sqlite3 *db = v->db; - sqlite3_mutex_enter(db->mutex); - checkProfileCallback(db, v); + sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); sqlite3VdbeRewind(v); - assert( (rc & (db->errMask))==rc ); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); + assert( (rc & (v->db->errMask))==rc ); + rc = sqlite3ApiExit(v->db, rc); + sqlite3_mutex_leave(v->db->mutex); } return rc; } @@ -71900,7 +65850,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ /* ** Set all the parameters in the compiled SQL statement to NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; @@ -71924,56 +65874,46 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){ ** The following routines extract information from a Mem or sqlite3_value ** structure. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ - assert( p->flags==MEM_Null && p->z==0 ); - return 0; - } + sqlite3VdbeMemExpandBlob(p); p->flags |= MEM_Blob; return p->n ? p->z : 0; }else{ return sqlite3_value_text(pVal); } } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){ +SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ return sqlite3VdbeRealValue((Mem*)pVal); } -SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ +SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } -SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ - return ((Mem*)pVal)->eSubtype; -} -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){ +SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16BE); } -SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){ +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ -/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five -** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating -** point number string BLOB NULL -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ +SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { SQLITE_BLOB, /* 0x00 */ SQLITE_NULL, /* 0x01 */ @@ -72011,46 +65951,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){ return aType[pVal->flags&MEM_AffMask]; } -/* Make a copy of an sqlite3_value object -*/ -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value *pOrig){ - sqlite3_value *pNew; - if( pOrig==0 ) return 0; - pNew = sqlite3_malloc( sizeof(*pNew) ); - if( pNew==0 ) return 0; - memset(pNew, 0, sizeof(*pNew)); - memcpy(pNew, pOrig, MEMCELLSIZE); - pNew->flags &= ~MEM_Dyn; - pNew->db = 0; - if( pNew->flags&(MEM_Str|MEM_Blob) ){ - pNew->flags &= ~(MEM_Static|MEM_Dyn); - pNew->flags |= MEM_Ephem; - if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){ - sqlite3ValueFree(pNew); - pNew = 0; - } - } - return pNew; -} - -/* Destroy an sqlite3_value object previously obtained from -** sqlite3_value_dup(). -*/ -SQLITE_API void SQLITE_STDCALL sqlite3_value_free(sqlite3_value *pOld){ - sqlite3ValueFree(pOld); -} - - /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. ** -** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the +** The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the ** result as a string or blob but if the string or blob is too large, it ** then sets the error code to SQLITE_TOOBIG -** -** The invokeValueDestructor(P,X) routine invokes destructor function X() -** on value P is not going to be used and need to be destroyed. */ static void setResultStrOrError( sqlite3_context *pCtx, /* Function context */ @@ -72059,183 +65966,121 @@ static void setResultStrOrError( u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ - if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){ + if( sqlite3VdbeMemSetStr(&pCtx->s, z, n, enc, xDel)==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(pCtx); } } -static int invokeValueDestructor( - const void *p, /* Value to destroy */ - void (*xDel)(void*), /* The destructor */ - sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ -){ - assert( xDel!=SQLITE_DYNAMIC ); - if( xDel==0 ){ - /* noop */ - }else if( xDel==SQLITE_TRANSIENT ){ - /* noop */ - }else{ - xDel((void*)p); - } - if( pCtx ) sqlite3_result_error_toobig(pCtx); - return SQLITE_TOOBIG; -} -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob( +SQLITE_API void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ assert( n>=0 ); - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); setResultStrOrError(pCtx, z, n, 0, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64( - sqlite3_context *pCtx, - const void *z, - sqlite3_uint64 n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - assert( xDel!=SQLITE_DYNAMIC ); - if( n>0x7fffffff ){ - (void)invokeValueDestructor(z, xDel, pCtx); - }else{ - setResultStrOrError(pCtx, z, (int)n, 0, xDel); - } +SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetDouble(&pCtx->s, rVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetDouble(pCtx->pOut, rVal); -} -SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; - sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = SQLITE_ERROR; pCtx->fErrorOrAux = 1; - sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif -SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal); +SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); +SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetInt64(&pCtx->s, iVal); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetNull(pCtx->pOut); +SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetNull(&pCtx->s); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - pCtx->pOut->eSubtype = eSubtype & 0xff; -} -SQLITE_API void SQLITE_STDCALL sqlite3_result_text( +SQLITE_API void sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text64( - sqlite3_context *pCtx, - const char *z, - sqlite3_uint64 n, - void (*xDel)(void *), - unsigned char enc -){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - assert( xDel!=SQLITE_DYNAMIC ); - if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - if( n>0x7fffffff ){ - (void)invokeValueDestructor(z, xDel, pCtx); - }else{ - setResultStrOrError(pCtx, z, (int)n, enc, xDel); - } -} #ifndef SQLITE_OMIT_UTF16 -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16( +SQLITE_API void sqlite3_result_text16( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be( +SQLITE_API void sqlite3_result_text16be( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le( +SQLITE_API void sqlite3_result_text16le( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) ){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemCopy(pCtx->pOut, pValue); +SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemCopy(&pCtx->s, pValue); } -SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); } -SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ - Mem *pOut = pCtx->pOut; - assert( sqlite3_mutex_held(pOut->db->mutex) ); - if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - return SQLITE_TOOBIG; - } - sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); - return SQLITE_OK; -} -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; -#ifdef SQLITE_DEBUG - if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; -#endif - if( pCtx->pOut->flags & MEM_Null ){ - sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, + if( pCtx->s.flags & MEM_Null ){ + sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, SQLITE_STATIC); } } /* Force an SQLITE_TOOBIG error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = SQLITE_TOOBIG; pCtx->fErrorOrAux = 1; - sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, + sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, SQLITE_UTF8, SQLITE_STATIC); } /* An SQLITE_NOMEM error. */ -SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetNull(pCtx->pOut); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetNull(&pCtx->s); pCtx->isError = SQLITE_NOMEM; pCtx->fErrorOrAux = 1; - pCtx->pOut->db->mallocFailed = 1; + pCtx->s.db->mallocFailed = 1; } /* @@ -72249,10 +66094,7 @@ static int doWalCallbacks(sqlite3 *db){ for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ - int nEntry; - sqlite3BtreeEnter(pBt); - nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); - sqlite3BtreeLeave(pBt); + int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); } @@ -72262,7 +66104,6 @@ static int doWalCallbacks(sqlite3 *db){ return rc; } - /* ** Execute the statement pStmt, either until a row of data is ready, the ** statement is completely executed or an error occurs. @@ -72295,7 +66136,7 @@ static int sqlite3Step(Vdbe *p){ ** or SQLITE_BUSY error. */ #ifdef SQLITE_OMIT_AUTORESET - if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){ sqlite3_reset((sqlite3_stmt*)p); }else{ return SQLITE_MISUSE_BKPT; @@ -72331,10 +66172,8 @@ static int sqlite3Step(Vdbe *p){ ); #ifndef SQLITE_OMIT_TRACE - if( db->xProfile && !db->init.busy && p->zSql ){ + if( db->xProfile && !db->init.busy ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); - }else{ - assert( p->startTime==0 ); } #endif @@ -72343,9 +66182,6 @@ static int sqlite3Step(Vdbe *p){ if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; } -#ifdef SQLITE_DEBUG - p->rcApp = SQLITE_OK; -#endif #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); @@ -72358,8 +66194,13 @@ static int sqlite3Step(Vdbe *p){ } #ifndef SQLITE_OMIT_TRACE - /* If the statement completed successfully, invoke the profile callback */ - if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); + /* Invoke the profile callback if there is one + */ + if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ + sqlite3_int64 iNow; + sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); + db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); + } #endif if( rc==SQLITE_DONE ){ @@ -72383,9 +66224,9 @@ end_of_step: ** were called on statement p. */ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR - || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE + || rc==SQLITE_BUSY || rc==SQLITE_MISUSE ); - assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); + assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ /* If this statement was prepared using sqlite3_prepare_v2(), and an ** error has occurred, then return the error code in p->rc to the @@ -72401,7 +66242,7 @@ end_of_step: ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ -SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ @@ -72415,12 +66256,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ sqlite3_mutex_enter(db->mutex); v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA - && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ - int savedPc = v->pc; - rc2 = rc = sqlite3Reprepare(v); - if( rc!=SQLITE_OK) break; + && cnt++ < SQLITE_MAX_SCHEMA_RETRY + && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); - if( savedPc>=0 ) v->doingRerun = 1; + v->doingRerun = 1; assert( v->expired==0 ); } if( rc2!=SQLITE_OK ){ @@ -72433,6 +66272,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); + assert( zErr!=0 || db->mallocFailed ); sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); @@ -72452,7 +66292,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){ ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ +SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData; } @@ -72467,32 +66307,22 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){ ** sqlite3_create_function16() routines that originally registered the ** application defined function. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){ - assert( p && p->pOut ); - return p->pOut->db; +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->s.db; } /* -** Return the current time for a statement. If the current time -** is requested more than once within the same run of a single prepared -** statement, the exact same time is returned for each invocation regardless -** of the amount of time that elapses between invocations. In other words, -** the time returned is always the time of the first call. +** Return the current time for a statement */ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ + Vdbe *v = p->pVdbe; int rc; -#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 - sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; - assert( p->pVdbe!=0 ); -#else - sqlite3_int64 iTime = 0; - sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; -#endif - if( *piTime==0 ){ - rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); - if( rc ) *piTime = 0; + if( v->iCurrentTime==0 ){ + rc = sqlite3OsCurrentTimeInt64(p->s.db->pVfs, &v->iCurrentTime); + if( rc ) v->iCurrentTime = 0; } - return *piTime; + return v->iCurrentTime; } /* @@ -72518,55 +66348,41 @@ SQLITE_PRIVATE void sqlite3InvalidFunction( } /* -** Create a new aggregate context for p and return a pointer to -** its pMem->z element. +** Allocate or return the aggregate context for a user function. A new +** context is allocated on the first call. Subsequent calls return the +** same context that was returned on prior calls. */ -static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ - Mem *pMem = p->pMem; - assert( (pMem->flags & MEM_Agg)==0 ); - if( nByte<=0 ){ - sqlite3VdbeMemSetNull(pMem); - pMem->z = 0; - }else{ - sqlite3VdbeMemClearAndResize(pMem, nByte); - pMem->flags = MEM_Agg; - pMem->u.pDef = p->pFunc; - if( pMem->z ){ - memset(pMem->z, 0, nByte); +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ + Mem *pMem; + assert( p && p->pFunc && p->pFunc->xStep ); + assert( sqlite3_mutex_held(p->s.db->mutex) ); + pMem = p->pMem; + testcase( nByte<0 ); + if( (pMem->flags & MEM_Agg)==0 ){ + if( nByte<=0 ){ + sqlite3VdbeMemReleaseExternal(pMem); + pMem->flags = MEM_Null; + pMem->z = 0; + }else{ + sqlite3VdbeMemGrow(pMem, nByte, 0); + pMem->flags = MEM_Agg; + pMem->u.pDef = p->pFunc; + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } } } return (void*)pMem->z; } /* -** Allocate or return the aggregate context for a user function. A new -** context is allocated on the first call. Subsequent calls return the -** same context that was returned on prior calls. -*/ -SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - assert( p && p->pFunc && p->pFunc->xStep ); - assert( sqlite3_mutex_held(p->pOut->db->mutex) ); - testcase( nByte<0 ); - if( (p->pMem->flags & MEM_Agg)==0 ){ - return createAggContext(p, nByte); - }else{ - return (void*)p->pMem->z; - } -} - -/* -** Return the auxiliary data pointer, if any, for the iArg'th argument to +** Return the auxilary data pointer, if any, for the iArg'th argument to ** the user-function defined by pCtx. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); -#if SQLITE_ENABLE_STAT3_OR_STAT4 - if( pCtx->pVdbe==0 ) return 0; -#else - assert( pCtx->pVdbe!=0 ); -#endif + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; } @@ -72575,11 +66391,11 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int i } /* -** Set the auxiliary data pointer and delete function, for the iArg'th +** Set the auxilary data pointer and delete function, for the iArg'th ** argument to the user-function defined by pCtx. Any previous value is ** deleted by calling the delete function specified when it was set. */ -SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( +SQLITE_API void sqlite3_set_auxdata( sqlite3_context *pCtx, int iArg, void *pAux, @@ -72588,13 +66404,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata( AuxData *pAuxData; Vdbe *pVdbe = pCtx->pVdbe; - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); if( iArg<0 ) goto failed; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - if( pVdbe==0 ) goto failed; -#else - assert( pVdbe!=0 ); -#endif for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; @@ -72626,7 +66437,7 @@ failed: #ifndef SQLITE_OMIT_DEPRECATED /* -** Return the number of times the Step function of an aggregate has been +** Return the number of times the Step function of a aggregate has been ** called. ** ** This function is deprecated. Do not use it for new code. It is @@ -72634,7 +66445,7 @@ failed: ** implementations should keep their own counts within their aggregate ** context. */ -SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ +SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pMem && p->pFunc && p->pFunc->xStep ); return p->pMem->n; } @@ -72643,7 +66454,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){ /* ** Return the number of columns in the result set for the statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; return pVm ? pVm->nResColumn : 0; } @@ -72652,7 +66463,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){ ** Return the number of values available from the current row of the ** currently executing statement pStmt. */ -SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; @@ -72675,23 +66486,11 @@ static const Mem *columnNullValue(void){ #if defined(SQLITE_DEBUG) && defined(__GNUC__) __attribute__((aligned(8))) #endif - = { - /* .u = */ {0}, - /* .flags = */ (u16)MEM_Null, - /* .enc = */ (u8)0, - /* .eSubtype = */ (u8)0, - /* .n = */ (int)0, - /* .z = */ (char*)0, - /* .zMalloc = */ (char*)0, - /* .szMalloc = */ (int)0, - /* .uTemp = */ (u32)0, - /* .db = */ (sqlite3*)0, - /* .xDel = */ (void(*)(void*))0, + = {0, "", (double)0, {0}, 0, MEM_Null, 0, #ifdef SQLITE_DEBUG - /* .pScopyFrom = */ (Mem*)0, - /* .pFiller = */ (void*)0, + 0, 0, /* pScopyFrom, pFiller */ #endif - }; + 0, 0 }; return &nullMem; } @@ -72712,7 +66511,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ }else{ if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE); + sqlite3Error(pVm->db, SQLITE_RANGE, 0); } pOut = (Mem*)columnNullValue(); } @@ -72755,7 +66554,7 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** The following routines are used to access elements of the current row ** in the result set. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might @@ -72765,37 +66564,37 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, i columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){ +SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){ +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } -SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){ +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ Mem *pOut = columnMem(pStmt, i); if( pOut->flags&MEM_Static ){ pOut->flags &= ~MEM_Static; @@ -72805,13 +66604,13 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStm return (sqlite3_value *)pOut; } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType; @@ -72839,19 +66638,11 @@ static const void *columnName( const void *(*xFunc)(Mem*), int useType ){ - const void *ret; - Vdbe *p; + const void *ret = 0; + Vdbe *p = (Vdbe *)pStmt; int n; - sqlite3 *db; -#ifdef SQLITE_ENABLE_API_ARMOR - if( pStmt==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - ret = 0; - p = (Vdbe *)pStmt; - db = p->db; + sqlite3 *db = p->db; + assert( db!=0 ); n = sqlite3_column_count(pStmt); if( N=0 ){ @@ -72875,12 +66666,12 @@ static const void *columnName( ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } @@ -72900,12 +66691,12 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } @@ -72916,14 +66707,14 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pS /* ** Return the name of the database from which a result column derives. ** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. +** anything else which is not an unabiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } @@ -72932,14 +66723,14 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stm /* ** Return the name of the table from which a result column derives. ** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. +** anything else which is not an unabiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } @@ -72948,14 +66739,14 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt * /* ** Return the name of the table column from which a result column derives. ** NULL is returned if the result column is an expression or constant or -** anything else which is not an unambiguous reference to a database column. +** anything else which is not an unabiguous reference to a database column. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ return columnName( pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } @@ -72985,14 +66776,14 @@ static int vdbeUnbind(Vdbe *p, int i){ } sqlite3_mutex_enter(p->db->mutex); if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ - sqlite3Error(p->db, SQLITE_MISUSE); + sqlite3Error(p->db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } if( i<1 || i>p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE); + sqlite3Error(p->db, SQLITE_RANGE, 0); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } @@ -73000,7 +66791,7 @@ static int vdbeUnbind(Vdbe *p, int i){ pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; - sqlite3Error(p->db, SQLITE_OK); + sqlite3Error(p->db, SQLITE_OK, 0); /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. @@ -73042,7 +66833,7 @@ static int bindText( if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } - sqlite3Error(p->db, rc); + sqlite3Error(p->db, rc, 0); rc = sqlite3ApiExit(p->db, rc); } sqlite3_mutex_leave(p->db->mutex); @@ -73056,7 +66847,7 @@ static int bindText( /* ** Bind a blob value to an SQL statement variable. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( +SQLITE_API int sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, @@ -73065,21 +66856,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob( ){ return bindText(pStmt, i, zData, nData, xDel, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64( - sqlite3_stmt *pStmt, - int i, - const void *zData, - sqlite3_uint64 nData, - void (*xDel)(void*) -){ - assert( xDel!=SQLITE_DYNAMIC ); - if( nData>0x7fffffff ){ - return invokeValueDestructor(zData, xDel, 0); - }else{ - return bindText(pStmt, i, zData, (int)nData, xDel, 0); - } -} -SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ +SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73089,10 +66866,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, do } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ +SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73102,7 +66879,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sql } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ +SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); @@ -73111,7 +66888,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( +SQLITE_API int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, @@ -73120,24 +66897,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text( ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64( - sqlite3_stmt *pStmt, - int i, - const char *zData, - sqlite3_uint64 nData, - void (*xDel)(void*), - unsigned char enc -){ - assert( xDel!=SQLITE_DYNAMIC ); - if( nData>0x7fffffff ){ - return invokeValueDestructor(zData, xDel, 0); - }else{ - if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; - return bindText(pStmt, i, zData, (int)nData, xDel, enc); - } -} #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( +SQLITE_API int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, @@ -73147,7 +66908,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16( return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ +SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { @@ -73155,7 +66916,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, con break; } case SQLITE_FLOAT: { - rc = sqlite3_bind_double(pStmt, i, pValue->u.r); + rc = sqlite3_bind_double(pStmt, i, pValue->r); break; } case SQLITE_BLOB: { @@ -73178,7 +66939,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, con } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); @@ -73188,26 +66949,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, } return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - sqlite3_mutex_enter(p->db->mutex); - if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - rc = SQLITE_TOOBIG; - }else{ - assert( (n & 0x7FFFFFFF)==n ); - rc = sqlite3_bind_zeroblob(pStmt, i, n); - } - rc = sqlite3ApiExit(p->db, rc); - sqlite3_mutex_leave(p->db->mutex); - return rc; -} /* ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; return p ? p->nVar : 0; } @@ -73218,7 +66965,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ ** ** The result is always UTF-8. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ Vdbe *p = (Vdbe*)pStmt; if( p==0 || i<1 || i>p->nzVar ){ return 0; @@ -73246,7 +66993,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa } return 0; } -SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); } @@ -73272,7 +67019,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt ** Deprecated external interface. Internal/core SQLite code ** should call sqlite3TransferBindings. ** -** It is misuse to call this routine with statements from different +** Is is misuse to call this routine with statements from different ** database connections. But as this is a deprecated interface, we ** will not bother to check for that condition. ** @@ -73280,7 +67027,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt ** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise ** SQLITE_OK is returned. */ -SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ +SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ @@ -73302,7 +67049,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, ** the first argument to the sqlite3_prepare() that was used to create ** the statement in the first place. */ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->db : 0; } @@ -73310,16 +67057,16 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){ ** Return true if the prepared statement is guaranteed to not modify the ** database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement is in need of being reset. */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; + return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN; } /* @@ -73328,14 +67075,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){ ** prepared statement for the database connection. Return NULL if there ** are no more. */ -SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ sqlite3_stmt *pNext; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(pDb) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(pDb->mutex); if( pStmt==0 ){ pNext = (sqlite3_stmt*)pDb->pVdbe; @@ -73349,89 +67090,13 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_ /* ** Return the value of a status counter for a prepared statement */ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; - u32 v; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !pStmt ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - v = pVdbe->aCounter[op]; + u32 v = pVdbe->aCounter[op]; if( resetFlag ) pVdbe->aCounter[op] = 0; return (int)v; } -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Return status data for a single loop within query pStmt. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, /* Prepared statement being queried */ - int idx, /* Index of loop to report on */ - int iScanStatusOp, /* Which metric to return */ - void *pOut /* OUT: Write the answer here */ -){ - Vdbe *p = (Vdbe*)pStmt; - ScanStatus *pScan; - if( idx<0 || idx>=p->nScan ) return 1; - pScan = &p->aScan[idx]; - switch( iScanStatusOp ){ - case SQLITE_SCANSTAT_NLOOP: { - *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; - break; - } - case SQLITE_SCANSTAT_NVISIT: { - *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; - break; - } - case SQLITE_SCANSTAT_EST: { - double r = 1.0; - LogEst x = pScan->nEst; - while( x<100 ){ - x += 10; - r *= 0.5; - } - *(double*)pOut = r*sqlite3LogEstToInt(x); - break; - } - case SQLITE_SCANSTAT_NAME: { - *(const char**)pOut = pScan->zName; - break; - } - case SQLITE_SCANSTAT_EXPLAIN: { - if( pScan->addrExplain ){ - *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; - }else{ - *(const char**)pOut = 0; - } - break; - } - case SQLITE_SCANSTAT_SELECTID: { - if( pScan->addrExplain ){ - *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; - }else{ - *(int*)pOut = -1; - } - break; - } - default: { - return 1; - } - } - return 0; -} - -/* -** Zero all counters associated with the sqlite3_stmt_scanstatus() data. -*/ -SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - memset(p->anExec, 0, p->nOp * sizeof(i64)); -} -#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ - /************** End of vdbeapi.c *********************************************/ /************** Begin file vdbetrace.c ***************************************/ /* @@ -73451,8 +67116,6 @@ SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt ** ** The Vdbe parse-tree explainer is also found here. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_TRACE @@ -73500,7 +67163,7 @@ static int findNextHostParameter(const char *zSql, int *pnToken){ ** ALGORITHM: Scan the input string looking for host parameters in any of ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within ** string literals, quoted identifier names, and comments. For text forms, -** the host parameter index is found by scanning the prepared +** the host parameter index is found by scanning the perpared ** statement for the corresponding OP_Variable opcode. Once the host ** parameter index is known, locate the value in p->aVar[]. Then render ** the value as a literal in place of the host parameter name. @@ -73520,8 +67183,9 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( char zBase[100]; /* Initial working space */ db = p->db; - sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), + sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); + out.db = db; if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; @@ -73530,8 +67194,6 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( assert( (zRawSql - zStart) > 0 ); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } - }else if( p->nVar==0 ){ - sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); @@ -73548,12 +67210,10 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( idx = nextIndex; } }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || - zRawSql[0]=='@' || zRawSql[0]=='#' ); + assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); testcase( zRawSql[0]==':' ); testcase( zRawSql[0]=='$' ); testcase( zRawSql[0]=='@' ); - testcase( zRawSql[0]=='#' ); idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); assert( idx>0 ); } @@ -73566,7 +67226,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( }else if( pVar->flags & MEM_Int ){ sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); + sqlite3XPrintf(&out, 0, "%!.15g", pVar->r); }else if( pVar->flags & MEM_Str ){ int nOut; /* Number of bytes of the string text to include in output */ #ifndef SQLITE_OMIT_UTF16 @@ -73623,6 +67283,121 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( #endif /* #ifndef SQLITE_OMIT_TRACE */ +/***************************************************************************** +** The following code implements the data-structure explaining logic +** for the Vdbe. +*/ + +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) + +/* +** Allocate a new Explain object +*/ +SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){ + if( pVdbe ){ + Explain *p; + sqlite3BeginBenignMalloc(); + p = (Explain *)sqlite3MallocZero( sizeof(Explain) ); + if( p ){ + p->pVdbe = pVdbe; + sqlite3_free(pVdbe->pExplain); + pVdbe->pExplain = p; + sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase), + SQLITE_MAX_LENGTH); + p->str.useMalloc = 2; + }else{ + sqlite3EndBenignMalloc(); + } + } +} + +/* +** Return true if the Explain ends with a new-line. +*/ +static int endsWithNL(Explain *p){ + return p && p->str.zText && p->str.nChar + && p->str.zText[p->str.nChar-1]=='\n'; +} + +/* +** Append text to the indentation +*/ +SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 ){ + va_list ap; + if( p->nIndent && endsWithNL(p) ){ + int n = p->nIndent; + if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent); + sqlite3AppendSpace(&p->str, p->aIndent[n-1]); + } + va_start(ap, zFormat); + sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap); + va_end(ap); + } +} + +/* +** Append a '\n' if there is not already one. +*/ +SQLITE_PRIVATE void sqlite3ExplainNL(Vdbe *pVdbe){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){ + sqlite3StrAccumAppend(&p->str, "\n", 1); + } +} + +/* +** Push a new indentation level. Subsequent lines will be indented +** so that they begin at the current cursor position. +*/ +SQLITE_PRIVATE void sqlite3ExplainPush(Vdbe *pVdbe){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 ){ + if( p->str.zText && p->nIndentaIndent) ){ + const char *z = p->str.zText; + int i = p->str.nChar-1; + int x; + while( i>=0 && z[i]!='\n' ){ i--; } + x = (p->str.nChar - 1) - i; + if( p->nIndent && xaIndent[p->nIndent-1] ){ + x = p->aIndent[p->nIndent-1]; + } + p->aIndent[p->nIndent] = x; + } + p->nIndent++; + } +} + +/* +** Pop the indentation stack by one level. +*/ +SQLITE_PRIVATE void sqlite3ExplainPop(Vdbe *p){ + if( p && p->pExplain ) p->pExplain->nIndent--; +} + +/* +** Free the indentation structure +*/ +SQLITE_PRIVATE void sqlite3ExplainFinish(Vdbe *pVdbe){ + if( pVdbe && pVdbe->pExplain ){ + sqlite3_free(pVdbe->zExplain); + sqlite3ExplainNL(pVdbe); + pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str); + sqlite3_free(pVdbe->pExplain); + pVdbe->pExplain = 0; + sqlite3EndBenignMalloc(); + } +} + +/* +** Return the explanation of a virtual machine. +*/ +SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ + return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0; +} +#endif /* defined(SQLITE_DEBUG) */ + /************** End of vdbetrace.c *******************************************/ /************** Begin file vdbe.c ********************************************/ /* @@ -73645,8 +67420,6 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ /* ** Invoke this macro on memory cells just prior to changing the @@ -73743,12 +67516,6 @@ SQLITE_API int sqlite3_found_count = 0; ** branch can go. It is usually 2. "I" is the direction the branch ** goes. 0 means falls through. 1 means branch is taken. 2 means the ** second alternative branch is taken. -** -** iSrcLine is the source code line (from the __LINE__ macro) that -** generated the VDBE instruction. This instrumentation assumes that all -** source code is in a single file (the amalgamation). Special values 1 -** and 2 for the iSrcLine parameter mean that this particular branch is -** always taken or never taken, respectively. */ #if !defined(SQLITE_VDBE_COVERAGE) # define VdbeBranchTaken(I,M) @@ -73773,7 +67540,7 @@ SQLITE_API int sqlite3_found_count = 0; ** already. Return non-zero if a malloc() fails. */ #define Stringify(P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ { goto no_mem; } /* @@ -73792,7 +67559,7 @@ SQLITE_API int sqlite3_found_count = 0; && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* Return true if the cursor was opened using the OP_OpenSorter opcode. */ -#define isSorter(x) ((x)->eCurType==CURTYPE_SORTER) +#define isSorter(x) ((x)->pSorter!=0) /* ** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL @@ -73803,7 +67570,7 @@ static VdbeCursor *allocateCursor( int iCur, /* Index of the new VdbeCursor */ int nField, /* Number of fields in the table or index */ int iDb, /* Database the cursor belongs to, or -1 */ - u8 eCurType /* Type of the new cursor */ + int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */ ){ /* Find the memory cell that will be used to store the blob of memory ** required for this VdbeCursor structure. It is convenient to use a @@ -73829,24 +67596,22 @@ static VdbeCursor *allocateCursor( VdbeCursor *pCx = 0; nByte = ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + - (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); + (isBtreeCursor?sqlite3BtreeCursorSize():0); assert( iCurnCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } - if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){ + if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; memset(pCx, 0, sizeof(VdbeCursor)); - pCx->eCurType = eCurType; pCx->iDb = iDb; pCx->nField = nField; - pCx->aOffset = &pCx->aType[nField]; - if( eCurType==CURTYPE_BTREE ){ - pCx->uc.pCursor = (BtCursor*) + if( isBtreeCursor ){ + pCx->pCursor = (BtCursor*) &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; - sqlite3BtreeCursorZero(pCx->uc.pCursor); + sqlite3BtreeCursorZero(pCx->pCursor); } } return pCx; @@ -73857,29 +67622,21 @@ static VdbeCursor *allocateCursor( ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. -** -** If the bTryForInt flag is true, then extra effort is made to give -** an integer representation. Strings that look like floating point -** values but which have no fractional component (example: '48.00') -** will have a MEM_Int representation when bTryForInt is true. -** -** If bTryForInt is false, then if the input string contains a decimal -** point or exponential notation, the result is only MEM_Real, even -** if there is an exact integer representation of the quantity. */ -static void applyNumericAffinity(Mem *pRec, int bTryForInt){ - double rValue; - i64 iValue; - u8 enc = pRec->enc; - assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str ); - if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; - if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ - pRec->u.i = iValue; - pRec->flags |= MEM_Int; - }else{ - pRec->u.r = rValue; - pRec->flags |= MEM_Real; - if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); +static void applyNumericAffinity(Mem *pRec){ + if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ + double rValue; + i64 iValue; + u8 enc = pRec->enc; + if( (pRec->flags&MEM_Str)==0 ) return; + if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; + if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ + pRec->u.i = iValue; + pRec->flags |= MEM_Int; + }else{ + pRec->r = rValue; + pRec->flags |= MEM_Real; + } } } @@ -73898,7 +67655,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ ** SQLITE_AFF_TEXT: ** Convert pRec to a text representation. ** -** SQLITE_AFF_BLOB: +** SQLITE_AFF_NONE: ** No-op. pRec is unchanged. */ static void applyAffinity( @@ -73906,25 +67663,22 @@ static void applyAffinity( char affinity, /* The affinity to be applied */ u8 enc /* Use this text encoding */ ){ - if( affinity>=SQLITE_AFF_NUMERIC ){ - assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL - || affinity==SQLITE_AFF_NUMERIC ); - if( (pRec->flags & MEM_Int)==0 ){ - if( (pRec->flags & MEM_Real)==0 ){ - if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); - }else{ - sqlite3VdbeIntegerAffinity(pRec); - } - } - }else if( affinity==SQLITE_AFF_TEXT ){ + if( affinity==SQLITE_AFF_TEXT ){ /* Only attempt the conversion to TEXT if there is an integer or real ** representation (blob and NULL do not get converted) but no string ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(pRec, enc, 1); + sqlite3VdbeMemStringify(pRec, enc); } pRec->flags &= ~(MEM_Real|MEM_Int); + }else if( affinity!=SQLITE_AFF_NONE ){ + assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL + || affinity==SQLITE_AFF_NUMERIC ); + applyNumericAffinity(pRec); + if( pRec->flags & MEM_Real ){ + sqlite3VdbeIntegerAffinity(pRec); + } } } @@ -73934,11 +67688,11 @@ static void applyAffinity( ** is appropriate. But only do the conversion if it is possible without ** loss of information and return the revised type of the argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){ +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; - applyNumericAffinity(pMem, 0); + applyNumericAffinity(pMem); eType = sqlite3_value_type(pVal); } return eType; @@ -73956,37 +67710,25 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity( applyAffinity((Mem *)pVal, affinity, enc); } -/* -** pMem currently only holds a string type (or maybe a BLOB that we can -** interpret as a string if we want to). Compute its corresponding -** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields -** accordingly. -*/ -static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ - assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); - assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); - if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ - return 0; - } - if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ - return MEM_Int; - } - return MEM_Real; -} - /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or ** none. ** ** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. -** But it does set pMem->u.r and pMem->u.i appropriately. +** But it does set pMem->r and pMem->u.i appropriately. */ static u16 numericType(Mem *pMem){ if( pMem->flags & (MEM_Int|MEM_Real) ){ return pMem->flags & (MEM_Int|MEM_Real); } if( pMem->flags & (MEM_Str|MEM_Blob) ){ - return computeNumericType(pMem); + if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ + return 0; + } + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + return MEM_Int; + } + return MEM_Real; } return 0; } @@ -74089,7 +67831,7 @@ static void memTracePrint(Mem *p){ printf(" i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ - printf(" r:%g", p->u.r); + printf(" r:%g", p->r); #endif }else if( p->flags & MEM_RowSet ){ printf(" (rowset)"); @@ -74232,29 +67974,6 @@ static int checkSavepointCount(sqlite3 *db){ } #endif -/* -** Return the register of pOp->p2 after first preparing it to be -** overwritten with an integer value. -*/ -static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){ - sqlite3VdbeMemSetNull(pOut); - pOut->flags = MEM_Int; - return pOut; -} -static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ - Mem *pOut; - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); - pOut = &p->aMem[pOp->p2]; - memAboutToChange(p, pOut); - if( VdbeMemDynamic(pOut) ){ - return out2PrereleaseWithClear(pOut); - }else{ - pOut->flags = MEM_Int; - return pOut; - } -} - /* ** Execute as much of a VDBE program as we can. @@ -74263,11 +67982,9 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ SQLITE_PRIVATE int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ + int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ - Op *pOp = aOp; /* Current operation */ -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) - Op *pOrigOp; /* Value of pOp at the top of the loop */ -#endif + Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ @@ -74296,7 +68013,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** sqlite3_column_text16() failed. */ goto no_mem; } - assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY ); + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; p->iCurrentTime = 0; @@ -74307,9 +68024,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec( sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( db->xProgress ){ - u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; assert( 0 < db->nProgressOps ); - nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); + nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; + if( nProgressLimit==0 ){ + nProgressLimit = db->nProgressOps; + }else{ + nProgressLimit %= (unsigned)db->nProgressOps; + } } #endif #ifdef SQLITE_DEBUG @@ -74339,22 +68060,20 @@ SQLITE_PRIVATE int sqlite3VdbeExec( } sqlite3EndBenignMalloc(); #endif - for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ - assert( pOp>=aOp && pOp<&aOp[p->nOp]); + for(pc=p->pc; rc==SQLITE_OK; pc++){ + assert( pc>=0 && pcnOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif nVmStep++; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; -#endif + pOp = &aOp[pc]; /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ - sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); + sqlite3VdbePrintOp(stdout, pc, pOp); } #endif @@ -74371,9 +68090,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec( } #endif + /* On any opcode with the "out2-prerelease" tag, free any + ** external allocations out of mem[p2] and set mem[p2] to be + ** an undefined integer. Opcodes will either fill in the integer + ** value or convert mem[p2] to a different type. + */ + assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); + if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + pOut = &aMem[pOp->p2]; + memAboutToChange(p, pOut); + VdbeMemRelease(pOut); + pOut->flags = MEM_Int; + } + /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG - assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); @@ -74406,9 +68139,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec( memAboutToChange(p, &aMem[pOp->p3]); } #endif -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) - pOrigOp = pOp; -#endif switch( pOp->opcode ){ @@ -74432,7 +68162,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** ** Other keywords in the comment that follows each case are used to ** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. -** Keywords include: in1, in2, in3, out2, out3. See +** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See ** the mkopcodeh.awk script for additional information. ** ** Documentation about VDBE opcodes is generated by scanning this file @@ -74460,8 +68190,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( ** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ -jump_to_p2_and_check_for_interrupt: - pOp = &aOp[pOp->p2 - 1]; + pc = pOp->p2 - 1; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon @@ -74506,13 +68235,9 @@ case OP_Gosub: { /* jump */ assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; - pIn1->u.i = (int)(pOp-aOp); + pIn1->u.i = pc; REGISTER_TRACE(pOp->p1, pIn1); - - /* Most jump operations do a goto to this spot in order to update - ** the pOp pointer. */ -jump_to_p2: - pOp = &aOp[pOp->p2 - 1]; + pc = pOp->p2 - 1; break; } @@ -74524,21 +68249,19 @@ jump_to_p2: case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags==MEM_Int ); - pOp = &aOp[pIn1->u.i]; + pc = (int)pIn1->u.i; pIn1->flags = MEM_Undefined; break; } /* Opcode: InitCoroutine P1 P2 P3 * * ** -** Set up register P1 so that it will Yield to the coroutine +** Set up register P1 so that it will OP_Yield to the co-routine ** located at address P3. ** -** If P2!=0 then the coroutine implementation immediately follows -** this opcode. So jump over the coroutine implementation to +** If P2!=0 then the co-routine implementation immediately follows +** this opcode. So jump over the co-routine implementation to ** address P2. -** -** See also: EndCoroutine */ case OP_InitCoroutine: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); @@ -74548,17 +68271,15 @@ case OP_InitCoroutine: { /* jump */ assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; - if( pOp->p2 ) goto jump_to_p2; + if( pOp->p2 ) pc = pOp->p2 - 1; break; } /* Opcode: EndCoroutine P1 * * * * ** -** The instruction at the address in register P1 is a Yield. -** Jump to the P2 parameter of that Yield. +** The instruction at the address in register P1 is an OP_Yield. +** Jump to the P2 parameter of that OP_Yield. ** After the jump, register P1 becomes undefined. -** -** See also: InitCoroutine */ case OP_EndCoroutine: { /* in1 */ VdbeOp *pCaller; @@ -74568,23 +68289,18 @@ case OP_EndCoroutine: { /* in1 */ pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2nOp ); - pOp = &aOp[pCaller->p2 - 1]; + pc = pCaller->p2 - 1; pIn1->flags = MEM_Undefined; break; } /* Opcode: Yield P1 P2 * * * ** -** Swap the program counter with the value in register P1. This -** has the effect of yielding to a coroutine. +** Swap the program counter with the value in register P1. ** -** If the coroutine that is launched by this instruction ends with -** Yield or Return then continue to the next instruction. But if -** the coroutine launched by this instruction ends with -** EndCoroutine, then jump to P2 rather than continuing with the -** next instruction. -** -** See also: InitCoroutine +** If the co-routine ends with OP_Yield or OP_Return then continue +** to the next instruction. But if the co-routine ends with +** OP_EndCoroutine, jump immediately to P2. */ case OP_Yield: { /* in1, jump */ int pcDest; @@ -74592,9 +68308,9 @@ case OP_Yield: { /* in1, jump */ assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; - pIn1->u.i = (int)(pOp - aOp); + pIn1->u.i = pc; REGISTER_TRACE(pOp->p1, pIn1); - pOp = &aOp[pcDest]; + pc = pcDest; break; } @@ -74645,34 +68361,30 @@ case OP_HaltIfNull: { /* in3 */ case OP_Halt: { const char *zType; const char *zLogFmt; - VdbeFrame *pFrame; - int pcx; - pcx = (int)(pOp - aOp); if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ - pFrame = p->pFrame; + VdbeFrame *pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); - pcx = sqlite3VdbeFrameRestore(pFrame); + pc = sqlite3VdbeFrameRestore(pFrame); lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ - /* Instruction pcx is the OP_Program that invoked the sub-program + /* Instruction pc is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified ** as the p2 of the calling OP_Program. */ - pcx = p->aOp[pcx].p2-1; + pc = p->aOp[pc].p2-1; } aOp = p->aOp; aMem = p->aMem; - pOp = &aOp[pcx]; break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; - p->pc = pcx; + p->pc = pc; if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", @@ -74689,13 +68401,14 @@ case OP_Halt: { assert( zType!=0 || pOp->p4.z!=0 ); zLogFmt = "abort at %d in [%s]: %s"; if( zType && pOp->p4.z ){ - sqlite3VdbeError(p, "%s constraint failed: %s", zType, pOp->p4.z); + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s", + zType, pOp->p4.z); }else if( pOp->p4.z ){ - sqlite3VdbeError(p, "%s", pOp->p4.z); + sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); }else{ - sqlite3VdbeError(p, "%s constraint failed", zType); + sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType); } - sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg); + sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -74714,8 +68427,7 @@ case OP_Halt: { ** ** The 32-bit integer value P1 is written into register P2. */ -case OP_Integer: { /* out2 */ - pOut = out2Prerelease(p, pOp); +case OP_Integer: { /* out2-prerelease */ pOut->u.i = pOp->p1; break; } @@ -74726,8 +68438,7 @@ case OP_Integer: { /* out2 */ ** P4 is a pointer to a 64-bit integer value. ** Write that value into register P2. */ -case OP_Int64: { /* out2 */ - pOut = out2Prerelease(p, pOp); +case OP_Int64: { /* out2-prerelease */ assert( pOp->p4.pI64!=0 ); pOut->u.i = *pOp->p4.pI64; break; @@ -74740,11 +68451,10 @@ case OP_Int64: { /* out2 */ ** P4 is a pointer to a 64-bit floating point value. ** Write that value into register P2. */ -case OP_Real: { /* same as TK_FLOAT, out2 */ - pOut = out2Prerelease(p, pOp); +case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; assert( !sqlite3IsNaN(*pOp->p4.pReal) ); - pOut->u.r = *pOp->p4.pReal; + pOut->r = *pOp->p4.pReal; break; } #endif @@ -74753,13 +68463,12 @@ case OP_Real: { /* same as TK_FLOAT, out2 */ ** Synopsis: r[P2]='P4' ** ** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into a String opcode before it is executed for the first time. During +** into an OP_String before it is executed for the first time. During ** this transformation, the length of string P4 is computed and stored ** as the P1 parameter. */ -case OP_String8: { /* same as TK_STRING, out2 */ +case OP_String8: { /* same as TK_STRING, out2-prerelease */ assert( pOp->p4.z!=0 ); - pOut = out2Prerelease(p, pOp); pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); @@ -74768,9 +68477,9 @@ case OP_String8: { /* same as TK_STRING, out2 */ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; - assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); + assert( pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); - pOut->szMalloc = 0; + pOut->zMalloc = 0; pOut->flags |= MEM_Static; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); @@ -74786,33 +68495,18 @@ case OP_String8: { /* same as TK_STRING, out2 */ /* Fall through to the next case, OP_String */ } -/* Opcode: String P1 P2 P3 P4 P5 +/* Opcode: String P1 P2 * P4 * ** Synopsis: r[P2]='P4' (len=P1) ** ** The string value P4 of length P1 (bytes) is stored in register P2. -** -** If P5!=0 and the content of register P3 is greater than zero, then -** the datatype of the register P2 is converted to BLOB. The content is -** the same sequence of bytes, it is merely interpreted as a BLOB instead -** of a string, as if it had been CAST. */ -case OP_String: { /* out2 */ +case OP_String: { /* out2-prerelease */ assert( pOp->p4.z!=0 ); - pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = pOp->p4.z; pOut->n = pOp->p1; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pOp->p5 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=(p->nMem-p->nCursor) ); - pIn3 = &aMem[pOp->p3]; - assert( pIn3->flags & MEM_Int ); - if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; - } -#endif break; } @@ -74828,17 +68522,16 @@ case OP_String: { /* out2 */ ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ -case OP_Null: { /* out2 */ +case OP_Null: { /* out2-prerelease */ int cnt; u16 nullFlag; - pOut = out2Prerelease(p, pOp); cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem-p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); - sqlite3VdbeMemSetNull(pOut); + VdbeMemRelease(pOut); pOut->flags = nullFlag; cnt--; } @@ -74866,9 +68559,8 @@ case OP_SoftNull: { ** P4 points to a blob of data P1 bytes long. Store this ** blob in register P2. */ -case OP_Blob: { /* out2 */ +case OP_Blob: { /* out2-prerelease */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); - pOut = out2Prerelease(p, pOp); sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); @@ -74883,7 +68575,7 @@ case OP_Blob: { /* out2 */ ** 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 */ +case OP_Variable: { /* out2-prerelease */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); @@ -74892,7 +68584,6 @@ case OP_Variable: { /* out2 */ if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } - pOut = out2Prerelease(p, pOp); sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; @@ -74908,6 +68599,7 @@ case OP_Variable: { /* out2 */ ** for P3 to be less than 1. */ case OP_Move: { + char *zMalloc; /* Holding variable for allocated memory */ int n; /* Number of registers left to copy */ int p1; /* Register to copy from */ int p2; /* Register to copy to */ @@ -74925,13 +68617,17 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - sqlite3VdbeMemMove(pOut, pIn1); + VdbeMemRelease(pOut); + zMalloc = pOut->zMalloc; + memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG - if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1; + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ + pOut->pScopyFrom += p1 - pOp->p2; } #endif - Deephemeralize(pOut); + pIn1->flags = MEM_Undefined; + pIn1->xDel = 0; + pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; @@ -74992,22 +68688,6 @@ case OP_SCopy: { /* out2 */ break; } -/* Opcode: IntCopy P1 P2 * * * -** Synopsis: r[P2]=r[P1] -** -** Transfer the integer value held in register P1 into register P2. -** -** This is an optimized version of SCopy that works only for integer -** values. -*/ -case OP_IntCopy: { /* out2 */ - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Int)!=0 ); - pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetInt64(pOut, pIn1->u.i); - break; -} - /* Opcode: ResultRow P1 P2 * * * ** Synopsis: output=r[P1@P2] ** @@ -75086,7 +68766,7 @@ case OP_ResultRow: { /* Return SQLITE_ROW */ - p->pc = (int)(pOp - aOp) + 1; + p->pc = pc + 1; rc = SQLITE_ROW; goto vdbe_return; } @@ -75252,7 +68932,7 @@ fp_math: if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } - pOut->u.r = rB; + pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); @@ -75279,7 +68959,7 @@ arithmetic_result_is_null: ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available -** publicly. Only built-in functions have access to this feature. +** publicly, only to user functions defined in func.c. */ case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); @@ -75289,10 +68969,10 @@ case OP_CollSeq: { break; } -/* Opcode: Function0 P1 P2 P3 P4 P5 +/* Opcode: Function P1 P2 P3 P4 P5 ** Synopsis: r[P3]=func(r[P2@P5]) ** -** Invoke a user function (P4 is a pointer to a FuncDef object that +** Invoke a user function (P4 is a pointer to a Function structure that ** defines the function) with P5 arguments taken from register P2 and ** successors. The result of the function is stored in register P3. ** Register P3 must not be one of the function inputs. @@ -75304,100 +68984,95 @@ case OP_CollSeq: { ** sqlite3_set_auxdata() API may be safely retained until the next ** invocation of this opcode. ** -** See also: Function, AggStep, AggFinal +** See also: AggStep and AggFinal */ -/* Opcode: Function P1 P2 P3 P4 P5 -** Synopsis: r[P3]=func(r[P2@P5]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with P5 arguments taken -** from register P2 and successors. The result of the function is stored -** in register P3. Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** SQL functions are initially coded as OP_Function0 with P4 pointing -** to a FuncDef object. But on first evaluation, the P4 operand is -** automatically converted into an sqlite3_context object and the operation -** changed to this OP_Function opcode. In this way, the initialization of -** the sqlite3_context object occurs only once, rather than once for each -** evaluation of the function. -** -** See also: Function0, AggStep, AggFinal -*/ -case OP_Function0: { - int n; - sqlite3_context *pCtx; - - assert( pOp->p4type==P4_FUNCDEF ); - n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); - if( pCtx==0 ) goto no_mem; - pCtx->pOut = 0; - pCtx->pFunc = pOp->p4.pFunc; - pCtx->iOp = (int)(pOp - aOp); - pCtx->pVdbe = p; - pCtx->argc = n; - pOp->p4type = P4_FUNCCTX; - pOp->p4.pCtx = pCtx; - pOp->opcode = OP_Function; - /* Fall through into OP_Function */ -} case OP_Function: { int i; - sqlite3_context *pCtx; + Mem *pArg; + sqlite3_context ctx; + sqlite3_value **apVal; + int n; - assert( pOp->p4type==P4_FUNCCTX ); - pCtx = pOp->p4.pCtx; - - /* If this function is inside of a trigger, the register array in aMem[] - ** might change from one evaluation to the next. The next block of code - ** checks to see if the register array has changed, and if so it - ** reinitializes the relavant parts of the sqlite3_context object */ + n = pOp->p5; + apVal = p->apArg; + assert( apVal || n==0 ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p3]; - if( pCtx->pOut != pOut ){ - pCtx->pOut = pOut; - for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; + memAboutToChange(p, pOut); + + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); + assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); + pArg = &aMem[pOp->p2]; + for(i=0; ip2+i, pArg); } - memAboutToChange(p, pCtx->pOut); -#ifdef SQLITE_DEBUG - for(i=0; iargc; i++){ - assert( memIsValid(pCtx->argv[i]) ); - REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); + assert( pOp->p4type==P4_FUNCDEF ); + ctx.pFunc = pOp->p4.pFunc; + ctx.iOp = pc; + ctx.pVdbe = p; + + /* The output cell may already have a buffer allocated. Move + ** the pointer to ctx.s so in case the user-function can use + ** the already allocated buffer instead of allocating a new one. + */ + memcpy(&ctx.s, pOut, sizeof(Mem)); + pOut->flags = MEM_Null; + pOut->xDel = 0; + pOut->zMalloc = 0; + MemSetTypeFlag(&ctx.s, MEM_Null); + + ctx.fErrorOrAux = 0; + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + assert( pOp>aOp ); + assert( pOp[-1].p4type==P4_COLLSEQ ); + assert( pOp[-1].opcode==OP_CollSeq ); + ctx.pColl = pOp[-1].p4.pColl; } -#endif - MemSetTypeFlag(pCtx->pOut, MEM_Null); - pCtx->fErrorOrAux = 0; db->lastRowid = lastRowid; - (*pCtx->pFunc->xFunc)(pCtx, pCtx->argc, pCtx->argv); /* IMP: R-24505-23230 */ - lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */ + (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + lastRowid = db->lastRowid; + + if( db->mallocFailed ){ + /* Even though a malloc() has failed, the implementation of the + ** user function may have called an sqlite3_result_XXX() function + ** to return a value. The following call releases any resources + ** associated with such a value. + */ + sqlite3VdbeMemRelease(&ctx.s); + goto no_mem; + } /* If the function returned an error, throw an exception */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); - rc = pCtx->isError; + if( ctx.fErrorOrAux ){ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; } - sqlite3VdbeDeleteAuxData(p, pCtx->iOp, pOp->p1); + sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); } /* Copy the result of the function into register P3 */ - if( pOut->flags & (MEM_Str|MEM_Blob) ){ - sqlite3VdbeChangeEncoding(pCtx->pOut, encoding); - if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big; + sqlite3VdbeChangeEncoding(&ctx.s, encoding); + assert( pOut->flags==MEM_Null ); + memcpy(pOut, &ctx.s, sizeof(Mem)); + if( sqlite3VdbeMemTooBig(pOut) ){ + goto too_big; } - REGISTER_TRACE(pOp->p3, pCtx->pOut); - UPDATE_MAX_BLOBSIZE(pCtx->pOut); +#if 0 + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ + if( p->expired ) rc = SQLITE_ABORT; +#endif + + REGISTER_TRACE(pOp->p3, pOut); + UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -75516,7 +69191,8 @@ case OP_MustBeInt: { /* jump, in1 */ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ - goto jump_to_p2; + pc = pOp->p2 - 1; + break; } } } @@ -75544,37 +69220,106 @@ case OP_RealAffinity: { /* in1 */ #endif #ifndef SQLITE_OMIT_CAST -/* Opcode: Cast P1 P2 * * * -** Synopsis: affinity(r[P1]) +/* Opcode: ToText P1 * * * * ** -** Force the value in register P1 to be the type defined by P2. -** -**
      -**
    • TEXT -**
    • BLOB -**
    • NUMERIC -**
    • INTEGER -**
    • REAL -**
    +** Force the value in register P1 to be text. +** If the value is numeric, convert it to a string using the +** equivalent of sprintf(). Blob values are unchanged and +** are afterwards simply interpreted as text. ** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_Cast: { /* in1 */ - assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL ); - testcase( pOp->p2==SQLITE_AFF_TEXT ); - testcase( pOp->p2==SQLITE_AFF_BLOB ); - testcase( pOp->p2==SQLITE_AFF_NUMERIC ); - testcase( pOp->p2==SQLITE_AFF_INTEGER ); - testcase( pOp->p2==SQLITE_AFF_REAL ); +case OP_ToText: { /* same as TK_TO_TEXT, in1 */ pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); + if( pIn1->flags & MEM_Null ) break; + assert( MEM_Str==(MEM_Blob>>3) ); + pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; + applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); rc = ExpandBlob(pIn1); - sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); + assert( pIn1->flags & MEM_Str || db->mallocFailed ); + pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); UPDATE_MAX_BLOBSIZE(pIn1); break; } + +/* Opcode: ToBlob P1 * * * * +** +** Force the value in register P1 to be a BLOB. +** If the value is numeric, convert it to a string first. +** Strings are simply reinterpreted as blobs with no change +** to the underlying data. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */ + pIn1 = &aMem[pOp->p1]; + if( pIn1->flags & MEM_Null ) break; + if( (pIn1->flags & MEM_Blob)==0 ){ + applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); + assert( pIn1->flags & MEM_Str || db->mallocFailed ); + MemSetTypeFlag(pIn1, MEM_Blob); + }else{ + pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob); + } + UPDATE_MAX_BLOBSIZE(pIn1); + break; +} + +/* Opcode: ToNumeric P1 * * * * +** +** Force the value in register P1 to be numeric (either an +** integer or a floating-point number.) +** If the value is text or blob, try to convert it to an using the +** equivalent of atoi() or atof() and store 0 if no such conversion +** is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ + pIn1 = &aMem[pOp->p1]; + sqlite3VdbeMemNumerify(pIn1); + break; +} #endif /* SQLITE_OMIT_CAST */ +/* Opcode: ToInt P1 * * * * +** +** Force the value in register P1 to be an integer. If +** The value is currently a real number, drop its fractional part. +** If the value is text or blob, try to convert it to an integer using the +** equivalent of atoi() and store 0 if no such conversion is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToInt: { /* same as TK_TO_INT, in1 */ + pIn1 = &aMem[pOp->p1]; + if( (pIn1->flags & MEM_Null)==0 ){ + sqlite3VdbeMemIntegerify(pIn1); + } + break; +} + +#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) +/* Opcode: ToReal P1 * * * * +** +** Force the value in register P1 to be a floating point number. +** If The value is currently an integer, convert it. +** If the value is text or blob, try to convert it to an integer using the +** equivalent of atoi() and store 0.0 if no such conversion is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToReal: { /* same as TK_TO_REAL, in1 */ + pIn1 = &aMem[pOp->p1]; + memAboutToChange(p, pIn1); + if( (pIn1->flags & MEM_Null)==0 ){ + sqlite3VdbeMemRealify(pIn1); + } + break; +} +#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ + /* Opcode: Lt P1 P2 P3 P4 P5 ** Synopsis: if r[P1]p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); }else{ VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ - goto jump_to_p2; + pc = pOp->p2-1; } } break; @@ -75711,38 +69455,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; - if( affinity>=SQLITE_AFF_NUMERIC ){ - if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn1,0); - } - if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3,0); - } - }else if( affinity==SQLITE_AFF_TEXT ){ - if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ - testcase( pIn1->flags & MEM_Int ); - testcase( pIn1->flags & MEM_Real ); - sqlite3VdbeMemStringify(pIn1, encoding, 1); - testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); - flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); - } - if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){ - testcase( pIn3->flags & MEM_Int ); - testcase( pIn3->flags & MEM_Real ); - sqlite3VdbeMemStringify(pIn3, encoding, 1); - testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); - flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); - } + if( affinity ){ + applyAffinity(pIn1, affinity, encoding); + applyAffinity(pIn3, affinity, encoding); + if( db->mallocFailed ) goto no_mem; } + assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - if( flags1 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn1); - flags1 &= ~MEM_Zero; - } - if( flags3 & MEM_Zero ){ - sqlite3VdbeMemExpandBlob(pIn3); - flags3 &= ~MEM_Zero; - } + ExpandBlob(pIn1); + ExpandBlob(pIn3); res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } switch( pOp->opcode ){ @@ -75754,12 +69475,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ default: res = res>=0; break; } - /* Undo any changes made by applyAffinity() to the input registers. */ - assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); - pIn1->flags = flags1; - assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); - pIn3->flags = flags3; - if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); @@ -75769,9 +69484,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res ){ - goto jump_to_p2; + pc = pOp->p2-1; } } + /* Undo any changes made by applyAffinity() to the input registers. */ + pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); + pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); break; } @@ -75866,11 +69584,11 @@ case OP_Compare: { */ case OP_Jump: { /* jump */ if( iCompare<0 ){ - VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; + pc = pOp->p1 - 1; VdbeBranchTaken(0,3); }else if( iCompare==0 ){ - VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; + pc = pOp->p2 - 1; VdbeBranchTaken(1,3); }else{ - VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; + pc = pOp->p3 - 1; VdbeBranchTaken(2,3); } break; } @@ -75939,10 +69657,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ case OP_Not: { /* same as TK_NOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); - if( (pIn1->flags & MEM_Null)==0 ){ - pOut->flags = MEM_Int; - pOut->u.i = !sqlite3VdbeIntValue(pIn1); + if( pIn1->flags & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + }else{ + sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1)); } break; } @@ -75957,30 +69675,26 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); - if( (pIn1->flags & MEM_Null)==0 ){ - pOut->flags = MEM_Int; - pOut->u.i = ~sqlite3VdbeIntValue(pIn1); + if( pIn1->flags & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + }else{ + sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1)); } break; } /* Opcode: Once P1 P2 * * * ** -** Check the "once" flag number P1. If it is set, jump to instruction P2. -** Otherwise, set the flag and fall through to the next instruction. -** In other words, this opcode causes all following opcodes up through P2 -** (but not including P2) to run just once and to be skipped on subsequent -** times through the loop. -** -** All "once" flags are initially cleared whenever a prepared statement -** first begins to run. +** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, +** set the flag and fall through to the next instruction. In other words, +** this opcode causes all following opcodes up through P2 (but not including +** P2) to run just once and to be skipped on subsequent times through the loop. */ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ - goto jump_to_p2; + pc = pOp->p2-1; }else{ p->aOnceFlag[pOp->p1] = 1; } @@ -75991,13 +69705,13 @@ case OP_Once: { /* jump */ ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if and only if P3 is non-zero. +** in P1 is NULL then take the jump if P3 is non-zero. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered false if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if and only if P3 is non-zero. +** in P1 is NULL then take the jump if P3 is zero. */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ @@ -76015,7 +69729,7 @@ case OP_IfNot: { /* jump, in1 */ } VdbeBranchTaken(c!=0, 2); if( c ){ - goto jump_to_p2; + pc = pOp->p2-1; } break; } @@ -76029,7 +69743,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ - goto jump_to_p2; + pc = pOp->p2 - 1; } break; } @@ -76043,7 +69757,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ - goto jump_to_p2; + pc = pOp->p2 - 1; } break; } @@ -76078,6 +69792,7 @@ case OP_Column: { int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ BtCursor *pCrsr; /* The BTree cursor */ + u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ @@ -76087,10 +69802,9 @@ case OP_Column: { const u8 *zHdr; /* Next unparsed byte of the header */ const u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ - u64 offset64; /* 64-bit offset */ + u32 szField; /* Number of bytes in the content of a field */ u32 avail; /* Number of bytes of available data */ u32 t; /* A type code from the record header */ - u16 fx; /* pDest->flags value */ Mem *pReg; /* PseudoTable input register */ p2 = pOp->p2; @@ -76101,30 +69815,32 @@ case OP_Column: { pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( p2nField ); - aOffset = pC->aOffset; - assert( pC->eCurType!=CURTYPE_VTAB ); - assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); - assert( pC->eCurType!=CURTYPE_SORTER ); - pCrsr = pC->uc.pCursor; + aType = pC->aType; + aOffset = aType + pC->nField; +#ifndef SQLITE_OMIT_VIRTUALTABLE + assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */ +#endif + pCrsr = pC->pCursor; + assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ + assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ /* If the cursor cache is stale, bring it up-to-date */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; - if( pC->cacheStatus!=p->cacheCtr ){ + if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ if( pC->nullRow ){ - if( pC->eCurType==CURTYPE_PSEUDO ){ - assert( pC->uc.pseudoTableReg>0 ); - pReg = &aMem[pC->uc.pseudoTableReg]; + if( pCrsr==0 ){ + assert( pC->pseudoTableReg>0 ); + pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ - sqlite3VdbeMemSetNull(pDest); + MemSetTypeFlag(pDest, MEM_Null); goto op_column_out; } }else{ - assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); if( pC->isTable==0 ){ assert( sqlite3BtreeCursorIsValid(pCrsr) ); @@ -76145,18 +69861,17 @@ case OP_Column: { assert( avail<=65536 ); /* Maximum page size is 64KiB */ if( pC->payloadSize <= (u32)avail ){ pC->szRow = pC->payloadSize; - }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; }else{ pC->szRow = avail; } + if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } } pC->cacheStatus = p->cacheCtr; pC->iHdrOffset = getVarint32(pC->aRow, offset); pC->nHdrParsed = 0; aOffset[0] = offset; - - if( availaRow does not have to hold the entire row, but it does at least ** need to cover the header of the record. If pC->aRow does not contain @@ -76164,86 +69879,90 @@ case OP_Column: { ** dynamically allocated. */ pC->aRow = 0; pC->szRow = 0; - - /* Make sure a corrupt database has not given us an oversize header. - ** Do this now to avoid an oversize memory allocation. - ** - ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte - ** types use so much data space that there can only be 4096 and 32 of - ** them, respectively. So the maximum header length results from a - ** 3-byte type for each of the maximum of 32768 columns plus three - ** extra bytes for the header length itself. 32768*3 + 3 = 98307. - */ - if( offset > 98307 || offset > pC->payloadSize ){ - rc = SQLITE_CORRUPT_BKPT; - goto op_column_error; - } } - /* The following goto is an optimization. It can be omitted and - ** everything will still work. But OP_Column is measurably faster - ** by skipping the subsequent conditional, which is always true. + /* Make sure a corrupt database has not given us an oversize header. + ** Do this now to avoid an oversize memory allocation. + ** + ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte + ** types use so much data space that there can only be 4096 and 32 of + ** them, respectively. So the maximum header length results from a + ** 3-byte type for each of the maximum of 32768 columns plus three + ** extra bytes for the header length itself. 32768*3 + 3 = 98307. */ - assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ - goto op_column_read_header; + if( offset > 98307 || offset > pC->payloadSize ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_error; + } } /* Make sure at least the first p2+1 entries of the header have been - ** parsed and valid information is in aOffset[] and pC->aType[]. + ** parsed and valid information is in aOffset[] and aType[]. */ if( pC->nHdrParsed<=p2 ){ /* If there is more header available for parsing in the record, try ** to extract additional fields up through the p2+1-th field */ - op_column_read_header: if( pC->iHdrOffsetaRow==0 ){ memset(&sMem, 0, sizeof(sMem)); - rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem); - if( rc!=SQLITE_OK ) goto op_column_error; + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], + !pC->isTable, &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_error; + } zData = (u8*)sMem.z; }else{ zData = pC->aRow; } - /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ + /* Fill in aType[i] and aOffset[i] values through the p2-th field. */ i = pC->nHdrParsed; - offset64 = aOffset[i]; + offset = aOffset[i]; zHdr = zData + pC->iHdrOffset; zEndHdr = zData + aOffset[0]; assert( i<=p2 && zHdraType[i++] = t; - aOffset[i] = (u32)(offset64 & 0xffffffff); + aType[i] = t; + szField = sqlite3VdbeSerialTypeLen(t); + offset += szField; + if( offsetnHdrParsed = i; pC->iHdrOffset = (u32)(zHdr - zData); - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); + if( pC->aRow==0 ){ + sqlite3VdbeMemRelease(&sMem); + sMem.flags = MEM_Null; + } - /* The record is corrupt if any of the following are true: - ** (1) the bytes of the header extend past the declared header size - ** (2) the entire header was used but not all data was used - ** (3) the end of the data extends beyond the end of the record. + /* If we have read more header data than was contained in the header, + ** or if the end of the last field appears to be past the end of the + ** record, or if the end of the last field appears to be before the end + ** of the record (when all fields present), then we must be dealing + ** with a corrupt database. */ - if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) - || (offset64 > pC->payloadSize) + if( (zHdr > zEndHdr) + || (offset > pC->payloadSize) + || (zHdr==zEndHdr && offset!=pC->payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_error; } - }else{ - t = 0; } - /* If after trying to extract new entries from the header, nHdrParsed is + /* If after trying to extra new entries from the header, nHdrParsed is ** still not up to p2, that means that the record has fewer than p2 ** columns. So the result will be either the default value or a NULL. */ @@ -76251,70 +69970,68 @@ case OP_Column: { if( pOp->p4type==P4_MEM ){ sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); }else{ - sqlite3VdbeMemSetNull(pDest); + MemSetTypeFlag(pDest, MEM_Null); } goto op_column_out; } - }else{ - t = pC->aType[p2]; } /* Extract the content for the p2+1-th column. Control can only - ** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are + ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are ** all valid. */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); - if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest); - assert( t==pC->aType[p2] ); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ - sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest); + VdbeMemRelease(pDest); + sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ + t = aType[p2]; if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) || (len = sqlite3VdbeSerialTypeLen(t))==0 ){ - /* Content is irrelevant for - ** 1. the typeof() function, - ** 2. the length(X) function if X is a blob, and - ** 3. if the content length is zero. - ** So we might as well use bogus content rather than reading - ** content from disk. NULL will work for the value for strings - ** and blobs and whatever is in the payloadSize64 variable - ** will work for everything else. */ - sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest); + /* Content is irrelevant for the typeof() function and for + ** the length(X) function if X is a blob. So we might as well use + ** bogus content rather than reading content from disk. NULL works + ** for text and blob and whatever is in the payloadSize64 variable + ** will work for everything else. Content is also irrelevant if + ** the content length is 0. */ + zData = t<=13 ? (u8*)&payloadSize64 : 0; + sMem.zMalloc = 0; }else{ + memset(&sMem, 0, sizeof(sMem)); + sqlite3VdbeMemMove(&sMem, pDest); rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, - pDest); + &sMem); if( rc!=SQLITE_OK ){ goto op_column_error; } - sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); - pDest->flags &= ~MEM_Ephem; + zData = (u8*)sMem.z; + } + sqlite3VdbeSerialGet(zData, t, pDest); + /* If we dynamically allocated space to hold the data (in the + ** sqlite3VdbeMemFromBtree() call above) then transfer control of that + ** dynamically allocated space over to the pDest structure. + ** This prevents a memory copy. */ + if( sMem.zMalloc ){ + assert( sMem.z==sMem.zMalloc ); + assert( VdbeMemDynamic(pDest)==0 ); + assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z ); + pDest->flags &= ~(MEM_Ephem|MEM_Static); + pDest->flags |= MEM_Term; + pDest->z = sMem.z; + pDest->zMalloc = sMem.zMalloc; } } pDest->enc = encoding; op_column_out: - /* If the column value is an ephemeral string, go ahead and persist - ** that string in case the cursor moves before the column value is - ** used. The following code does the equivalent of Deephemeralize() - ** but does it faster. */ - if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){ - fx = pDest->flags & (MEM_Str|MEM_Blob); - assert( fx!=0 ); - zData = (const u8*)pDest->z; - len = pDest->n; - if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem; - memcpy(pDest->z, zData, len); - pDest->z[len] = 0; - pDest->z[len+1] = 0; - pDest->flags = fx|MEM_Term; - } + Deephemeralize(pDest); op_column_error: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); @@ -76361,7 +70078,7 @@ case OP_Affinity: { ** The mapping from character to affinity is given by the SQLITE_AFF_ ** macros defined in sqliteInt.h. ** -** If P4 is NULL then all index fields have the affinity BLOB. +** If P4 is NULL then all index fields have the affinity NONE. */ case OP_MakeRecord: { u8 *zNewRecord; /* A buffer to hold the data for the new record */ @@ -76369,7 +70086,7 @@ case OP_MakeRecord: { u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ i64 nByte; /* Data space required for this record */ - i64 nZero; /* Number of zero bytes at the end of the record */ + int nZero; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ Mem *pData0; /* First field to be combined into the record */ @@ -76379,7 +70096,7 @@ case OP_MakeRecord: { int file_format; /* File format to use for encoding */ int i; /* Space used in zNewRecord[] header */ int j; /* Space used in zNewRecord[] content */ - u32 len; /* Length of a field */ + int len; /* Length of a field */ /* Assuming the record contains N fields, the record format looks ** like this: @@ -76389,7 +70106,7 @@ case OP_MakeRecord: { ** ------------------------------------------------------------------------ ** ** Data(0) is taken from register P1. Data(1) comes from register P1+1 - ** and so forth. + ** and so froth. ** ** Each type field is a varint representing the serial type of the ** corresponding data element (see sqlite3VdbeSerialType()). The @@ -76429,10 +70146,11 @@ case OP_MakeRecord: { pRec = pLast; do{ assert( memIsValid(pRec) ); - pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); + serial_type = sqlite3VdbeSerialType(pRec, file_format); + len = sqlite3VdbeSerialTypeLen(serial_type); if( pRec->flags & MEM_Zero ){ if( nData ){ - if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + sqlite3VdbeMemExpandBlob(pRec); }else{ nZero += pRec->u.nZero; len -= pRec->u.nZero; @@ -76444,10 +70162,7 @@ case OP_MakeRecord: { nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); }while( (--pRec)>=pData0 ); - /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint - ** which determines the total number of bytes in the header. The varint - ** value is the size of the header in bytes including the size varint - ** itself. */ + /* Add the initial header varint and total the size */ testcase( nHdr==126 ); testcase( nHdr==127 ); if( nHdr<=126 ){ @@ -76460,16 +70175,16 @@ case OP_MakeRecord: { if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to - ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). + ** sqlite3VdbeMemGrow() could clobber the value before it is used). */ - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){ goto no_mem; } zNewRecord = (u8 *)pOut->z; @@ -76480,12 +70195,8 @@ case OP_MakeRecord: { assert( pData0<=pLast ); pRec = pData0; do{ - serial_type = pRec->uTemp; - /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more - ** additional varints, one per column. */ + serial_type = sqlite3VdbeSerialType(pRec, file_format); i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ - /* EVIDENCE-OF: R-64536-51728 The values for each column in the record - ** immediately follow the header. */ j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ }while( (++pRec)<=pLast ); assert( i==nHdr ); @@ -76494,6 +70205,7 @@ case OP_MakeRecord: { assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut->n = (int)nByte; pOut->flags = MEM_Blob; + pOut->xDel = 0; if( nZero ){ pOut->u.nZero = nZero; pOut->flags |= MEM_Zero; @@ -76511,16 +70223,14 @@ case OP_MakeRecord: { ** opened by cursor P1 in register P2 */ #ifndef SQLITE_OMIT_BTREECOUNT -case OP_Count: { /* out2 */ +case OP_Count: { /* out2-prerelease */ i64 nEntry; BtCursor *pCrsr; - assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE ); - pCrsr = p->apCsr[pOp->p1]->uc.pCursor; + pCrsr = p->apCsr[pOp->p1]->pCursor; assert( pCrsr ); nEntry = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3BtreeCount(pCrsr, &nEntry); - pOut = out2Prerelease(p, pOp); pOut->u.i = nEntry; break; } @@ -76559,7 +70269,8 @@ case OP_Savepoint: { /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ - sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress"); + sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - " + "SQL statements in progress"); rc = SQLITE_BUSY; }else{ nName = sqlite3Strlen30(zName); @@ -76610,14 +70321,15 @@ case OP_Savepoint: { iSavepoint++; } if( !pSavepoint ){ - sqlite3VdbeError(p, "no such savepoint: %s", zName); + sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); rc = SQLITE_ERROR; }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ - sqlite3VdbeError(p, "cannot release savepoint - " - "SQL statements in progress"); + sqlite3SetString(&p->zErrMsg, db, + "cannot release savepoint - SQL statements in progress" + ); rc = SQLITE_BUSY; }else{ @@ -76632,7 +70344,7 @@ case OP_Savepoint: { } db->autoCommit = 1; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); + p->pc = pc; db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; @@ -76640,18 +70352,11 @@ case OP_Savepoint: { db->isTransactionSavepoint = 0; rc = p->rc; }else{ - int isSchemaChange; iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ - isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; for(ii=0; iinDb; ii++){ - rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, - SQLITE_ABORT_ROLLBACK, - isSchemaChange==0); - if( rc!=SQLITE_OK ) goto abort_due_to_error; + sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); } - }else{ - isSchemaChange = 0; } for(ii=0; iinDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); @@ -76659,7 +70364,7 @@ case OP_Savepoint: { goto abort_due_to_error; } } - if( isSchemaChange ){ + if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); @@ -76691,7 +70396,7 @@ case OP_Savepoint: { db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } - if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ + if( !isTransaction ){ rc = sqlite3VtabSavepoint(db, p1, iSavepoint); if( rc!=SQLITE_OK ) goto abort_due_to_error; } @@ -76723,12 +70428,23 @@ case OP_AutoCommit: { assert( db->nVdbeActive>0 ); /* At least this one VM is active */ assert( p->bIsReader ); +#if 0 + if( turnOnAC && iRollback && db->nVdbeActive>1 ){ + /* If this instruction implements a ROLLBACK and other VMs are + ** still running, and a transaction is active, return an error indicating + ** that the other VMs must complete first. + */ + sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " + "SQL statements in progress"); + rc = SQLITE_BUSY; + }else +#endif if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing ** return an error indicating that the other VMs must complete first. */ - sqlite3VdbeError(p, "cannot commit transaction - " - "SQL statements in progress"); + sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " + "SQL statements in progress"); rc = SQLITE_BUSY; }else if( desiredAutoCommit!=db->autoCommit ){ if( iRollback ){ @@ -76739,12 +70455,12 @@ case OP_AutoCommit: { goto vdbe_return; }else{ db->autoCommit = (u8)desiredAutoCommit; - } - if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - db->autoCommit = (u8)(1-desiredAutoCommit); - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ + p->pc = pc; + db->autoCommit = (u8)(1-desiredAutoCommit); + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } } assert( db->nStatement==0 ); sqlite3CloseSavepoints(db); @@ -76755,7 +70471,7 @@ case OP_AutoCommit: { } goto vdbe_return; }else{ - sqlite3VdbeError(p, + sqlite3SetString(&p->zErrMsg, db, (!desiredAutoCommit)?"cannot start a transaction within a transaction":( (iRollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); @@ -76807,7 +70523,7 @@ case OP_Transaction: { assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ rc = SQLITE_READONLY; goto abort_due_to_error; @@ -76816,11 +70532,9 @@ case OP_Transaction: { if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); - testcase( rc==SQLITE_BUSY_SNAPSHOT ); - testcase( rc==SQLITE_BUSY_RECOVERY ); - if( (rc&0xff)==SQLITE_BUSY ){ - p->pc = (int)(pOp - aOp); - p->rc = rc; + if( rc==SQLITE_BUSY ){ + p->pc = pc; + p->rc = rc = SQLITE_BUSY; goto vdbe_return; } if( rc!=SQLITE_OK ){ @@ -76849,12 +70563,7 @@ case OP_Transaction: { p->nStmtDefImmCons = db->nDeferredImmCons; } - /* Gather the schema version number for checking: - ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite - ** each time a query is executed to ensure that the internal cache of the - ** schema used when compiling the SQL query matches the schema of the - ** database against which the compiled query is actually executed. - */ + /* Gather the schema version number for checking */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ @@ -76898,7 +70607,7 @@ case OP_Transaction: { ** must be started or there must be an open cursor) before ** executing this instruction. */ -case OP_ReadCookie: { /* out2 */ +case OP_ReadCookie: { /* out2-prerelease */ int iMeta; int iDb; int iCookie; @@ -76909,10 +70618,9 @@ case OP_ReadCookie: { /* out2 */ assert( pOp->p3=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); - assert( DbMaskTest(p->btreeMask, iDb) ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb].pBt, iCookie, (u32 *)&iMeta); - pOut = out2Prerelease(p, pOp); pOut->u.i = iMeta; break; } @@ -76931,7 +70639,7 @@ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); @@ -76986,21 +70694,7 @@ case OP_SetCookie: { /* in3 */ ** sequence of the index being opened. Otherwise, if P4 is an integer ** value, it is set to the number of columns in the table. ** -** See also: OpenWrite, ReopenIdx -*/ -/* Opcode: ReopenIdx P1 P2 P3 P4 P5 -** Synopsis: root=P2 iDb=P3 -** -** The ReopenIdx opcode works exactly like ReadOpen except that it first -** checks to see if the cursor on P1 is already open with a root page -** number of P2 and if it is this opcode becomes a no-op. In other words, -** if the cursor is already open, do not reopen it. -** -** The ReopenIdx opcode may only be used with P5==0 and with P4 being -** a P4_KEYINFO object. Furthermore, the P3 value must be the same as -** every other ReopenIdx or OpenRead for the same cursor number. -** -** See the OpenRead opcode documentation for additional information. +** See also OpenWrite. */ /* Opcode: OpenWrite P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 @@ -77022,7 +70716,8 @@ case OP_SetCookie: { /* in3 */ ** ** See also OpenRead. */ -case OP_ReopenIdx: { +case OP_OpenRead: +case OP_OpenWrite: { int nField; KeyInfo *pKeyInfo; int p2; @@ -77032,25 +70727,13 @@ case OP_ReopenIdx: { VdbeCursor *pCur; Db *pDb; - assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); - assert( pOp->p4type==P4_KEYINFO ); - pCur = p->apCsr[pOp->p1]; - if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ - assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ - goto open_cursor_set_hints; - } - /* If the cursor is not currently open or is open on a different - ** index, then fall through into OP_OpenRead to force a reopen */ -case OP_OpenRead: -case OP_OpenWrite: - - assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); + assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); assert( p->bIsReader ); - assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx - || p->readOnly==0 ); + assert( pOp->opcode==OP_OpenRead || p->readOnly==0 ); if( p->expired ){ - rc = SQLITE_ABORT_ROLLBACK; + rc = SQLITE_ABORT; break; } @@ -77059,13 +70742,12 @@ case OP_OpenWrite: p2 = pOp->p2; iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); - assert( DbMaskTest(p->btreeMask, iDb) ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); if( pOp->opcode==OP_OpenWrite ){ - assert( OPFLAG_FORDELETE==BTREE_FORDELETE ); - wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE); + wrFlag = 1; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( pDb->pSchema->file_format < p->minWriteFileFormat ){ p->minWriteFileFormat = pDb->pSchema->file_format; @@ -77101,28 +70783,24 @@ case OP_OpenWrite: assert( pOp->p1>=0 ); assert( nField>=0 ); testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); + pCur = allocateCursor(p, pOp->p1, nField, iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; pCur->isOrdered = 1; - pCur->pgnoRoot = p2; - rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; + assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); + sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); + + /* Since it performs no memory allocation or IO, the only value that + ** sqlite3BtreeCursor() may return is SQLITE_OK. */ + assert( rc==SQLITE_OK ); + /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; - -open_cursor_set_hints: - assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); - testcase( pOp->p5 & OPFLAG_BULKCSR ); -#ifdef SQLITE_ENABLE_CURSOR_HINTS - testcase( pOp->p2 & OPFLAG_SEEKEQ ); -#endif - sqlite3BtreeCursorHintFlags(pCur->uc.pCursor, - (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); break; } @@ -77165,7 +70843,7 @@ case OP_OpenEphemeral: { SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; @@ -77189,13 +70867,11 @@ case OP_OpenEphemeral: { assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); pCx->pKeyInfo = pKeyInfo; - rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, - pKeyInfo, pCx->uc.pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor); } pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, - 0, pCx->uc.pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); pCx->isTable = 1; } } @@ -77203,45 +70879,23 @@ case OP_OpenEphemeral: { break; } -/* Opcode: SorterOpen P1 P2 P3 P4 * +/* Opcode: SorterOpen P1 P2 * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. -** -** If argument P3 is non-zero, then it indicates that the sorter may -** assume that a stable sort considering the first P3 fields of each -** key is sufficient to produce the required results. */ case OP_SorterOpen: { VdbeCursor *pCx; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER); + pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; assert( pCx->pKeyInfo->db==db ); assert( pCx->pKeyInfo->enc==ENC(db) ); - rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx); - break; -} - -/* Opcode: SequenceTest P1 P2 * * * -** Synopsis: if( cursor[P1].ctr++ ) pc = P2 -** -** P1 is a sorter cursor. If the sequence counter is currently zero, jump -** to P2. Regardless of whether or not the jump is taken, increment the -** the sequence value. -*/ -case OP_SequenceTest: { - VdbeCursor *pC; - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( isSorter(pC) ); - if( (pC->seqCount++)==0 ){ - goto jump_to_p2; - } + rc = sqlite3VdbeSorterInit(db, pCx); break; } @@ -77266,10 +70920,10 @@ case OP_OpenPseudo: { assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; - pCx->uc.pseudoTableReg = pOp->p2; + pCx->pseudoTableReg = pOp->p2; pCx->isTable = 1; assert( pOp->p5==0 ); break; @@ -77287,27 +70941,7 @@ case OP_Close: { break; } -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK -/* Opcode: ColumnsUsed P1 * * P4 * -** -** This opcode (which only exists if SQLite was compiled with -** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the -** table or index for cursor P1 are used. P4 is a 64-bit integer -** (P4_INT64) in which the first 63 bits are one for each of the -** first 63 columns of the table or index that are actually used -** by the cursor. The high-order bit is set if any column after -** the 64th is used. -*/ -case OP_ColumnsUsed: { - VdbeCursor *pC; - pC = p->apCsr[pOp->p1]; - assert( pC->eCurType==CURTYPE_BTREE ); - pC->maskUsed = *(u64*)pOp->p4.pI64; - break; -} -#endif - -/* Opcode: SeekGE P1 P2 P3 P4 * +/* Opcode: SeekGe P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), @@ -77319,20 +70953,9 @@ case OP_ColumnsUsed: { ** is greater than or equal to the key value. If there are no records ** greater than or equal to the key and P2 is not zero, then jump to P2. ** -** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will always land on a record that equally equals the key, or -** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this -** opcode must be followed by an IdxLE opcode with the same arguments. -** The IdxLE opcode will be skipped if this opcode succeeds, but the -** IdxLE opcode will be used on subsequent loop iterations. -** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. -** ** See also: Found, NotFound, SeekLt, SeekGt, SeekLe */ -/* Opcode: SeekGT P1 P2 P3 P4 * +/* Opcode: SeekGt P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), @@ -77344,13 +70967,9 @@ case OP_ColumnsUsed: { ** is greater than the key value. If there are no records greater than ** the key and P2 is not zero, then jump to P2. ** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. -** ** See also: Found, NotFound, SeekLt, SeekGe, SeekLe */ -/* Opcode: SeekLT P1 P2 P3 P4 * +/* Opcode: SeekLt P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), @@ -77362,13 +70981,9 @@ case OP_ColumnsUsed: { ** is less than the key value. If there are no records less than ** the key and P2 is not zero, then jump to P2. ** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. -** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLe */ -/* Opcode: SeekLE P1 P2 P3 P4 * +/* Opcode: SeekLe P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] ** ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), @@ -77380,60 +70995,39 @@ case OP_ColumnsUsed: { ** is less than or equal to the key value. If there are no records ** less than or equal to the key and P2 is not zero, then jump to P2. ** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. -** -** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this -** opcode will always land on a record that equally equals the key, or -** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this -** opcode must be followed by an IdxGE opcode with the same arguments. -** The IdxGE opcode will be skipped if this opcode succeeds, but the -** IdxGE opcode will be used on subsequent loop iterations. -** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ case OP_SeekLT: /* jump, in3 */ case OP_SeekLE: /* jump, in3 */ case OP_SeekGE: /* jump, in3 */ case OP_SeekGT: { /* jump, in3 */ - int res; /* Comparison result */ - int oc; /* Opcode */ - VdbeCursor *pC; /* The cursor to seek */ - UnpackedRecord r; /* The key to seek for */ - int nField; /* Number of columns or fields in the key */ - i64 iKey; /* The rowid we are to seek to */ - int eqOnly; /* Only interested in == results */ + int res; + int oc; + VdbeCursor *pC; + UnpackedRecord r; + int nField; + i64 iKey; /* The rowid we are to seek to */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p2!=0 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->pseudoTableReg==0 ); assert( OP_SeekLE == OP_SeekLT+1 ); assert( OP_SeekGE == OP_SeekLT+2 ); assert( OP_SeekGT == OP_SeekLT+3 ); assert( pC->isOrdered ); - assert( pC->uc.pCursor!=0 ); + assert( pC->pCursor!=0 ); oc = pOp->opcode; - eqOnly = 0; pC->nullRow = 0; -#ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; -#endif - if( pC->isTable ){ - /* The BTREE_SEEK_EQ flag is only set on index cursors */ - assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 ); - /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do - ** the seek, so convert it. */ + ** the seek, so covert it. */ pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ - applyNumericAffinity(pIn3, 0); - } + applyNumericAffinity(pIn3); iKey = sqlite3VdbeIntValue(pIn3); + pC->rowidIsValid = 0; /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ @@ -77441,7 +71035,7 @@ case OP_SeekGT: { /* jump, in3 */ if( (pIn3->flags & MEM_Real)==0 ){ /* If the P3 value cannot be converted into any kind of a number, ** then the seek is not possible, so jump to P2 */ - VdbeBranchTaken(1,2); goto jump_to_p2; + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); break; } @@ -77452,7 +71046,7 @@ case OP_SeekGT: { /* jump, in3 */ ** (x > 4.9) -> (x >= 5) ** (x <= 4.9) -> (x < 5) */ - if( pIn3->u.r<(double)iKey ){ + if( pIn3->r<(double)iKey ){ assert( OP_SeekGE==(OP_SeekGT-1) ); assert( OP_SeekLT==(OP_SeekLE-1) ); assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); @@ -77461,33 +71055,22 @@ case OP_SeekGT: { /* jump, in3 */ /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ - else if( pIn3->u.r>(double)iKey ){ + else if( pIn3->r>(double)iKey ){ assert( OP_SeekLE==(OP_SeekLT+1) ); assert( OP_SeekGT==(OP_SeekGE+1) ); assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } } - rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res); - pC->movetoTarget = iKey; /* Used by OP_Delete */ + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - }else{ - /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and - ** OP_SeekLE opcodes are allowed, and these must be immediately followed - ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. - */ - if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){ - eqOnly = 1; - assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); - assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - assert( pOp[1].p1==pOp[0].p1 ); - assert( pOp[1].p2==pOp[0].p2 ); - assert( pOp[1].p3==pOp[0].p3 ); - assert( pOp[1].p4.i==pOp[0].p4.i ); + if( res==0 ){ + pC->rowidIsValid = 1; + pC->lastRowid = iKey; } - + }else{ nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); assert( nField>0 ); @@ -77512,15 +71095,11 @@ case OP_SeekGT: { /* jump, in3 */ { int i; for(i=0; iuc.pCursor, &r, 0, 0, &res); + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - if( eqOnly && r.eqSeen==0 ){ - assert( res!=0 ); - goto seek_not_found; - } + pC->rowidIsValid = 0; } pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -77530,8 +71109,9 @@ case OP_SeekGT: { /* jump, in3 */ if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); if( res<0 || (res==0 && oc==OP_SeekGT) ){ res = 0; - rc = sqlite3BtreeNext(pC->uc.pCursor, &res); + rc = sqlite3BtreeNext(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; }else{ res = 0; } @@ -77539,23 +71119,20 @@ case OP_SeekGT: { /* jump, in3 */ assert( oc==OP_SeekLT || oc==OP_SeekLE ); if( res>0 || (res==0 && oc==OP_SeekLT) ){ res = 0; - rc = sqlite3BtreePrevious(pC->uc.pCursor, &res); + rc = sqlite3BtreePrevious(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; }else{ /* res might be negative because the table is empty. Check to ** see if this is the case. */ - res = sqlite3BtreeEof(pC->uc.pCursor); + res = sqlite3BtreeEof(pC->pCursor); } } -seek_not_found: assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ - goto jump_to_p2; - }else if( eqOnly ){ - assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); - pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ + pc = pOp->p2 - 1; } break; } @@ -77576,12 +71153,12 @@ case OP_Seek: { /* in2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); + assert( pC->pCursor!=0 ); assert( pC->isTable ); pC->nullRow = 0; pIn2 = &aMem[pOp->p2]; pC->movetoTarget = sqlite3VdbeIntValue(pIn2); + pC->rowidIsValid = 0; pC->deferredMoveto = 1; break; } @@ -77598,10 +71175,6 @@ case OP_Seek: { /* in2 */ ** is a prefix of any entry in P1 then a jump is made to P2 and ** P1 is left pointing at the matching entry. ** -** This operation leaves the cursor in a state where it can be -** advanced in the forward direction. The Next instruction will work, -** but not the Prev instruction. -** ** See also: NotFound, NoConflict, NotExists. SeekGe */ /* Opcode: NotFound P1 P2 P3 P4 * @@ -77617,10 +71190,6 @@ case OP_Seek: { /* in2 */ ** falls through to the next instruction and P1 is left pointing at the ** matching entry. ** -** This operation leaves the cursor in a state where it cannot be -** advanced in either direction. In other words, the Next and Prev -** opcodes do not work after this operation. -** ** See also: Found, NotExists, NoConflict */ /* Opcode: NoConflict P1 P2 P3 P4 * @@ -77640,17 +71209,12 @@ case OP_Seek: { /* in2 */ ** This opcode is similar to OP_NotFound with the exceptions that the ** branch is always taken if any part of the search key input is NULL. ** -** This operation leaves the cursor in a state where it cannot be -** advanced in either direction. In other words, the Next and Prev -** opcodes do not work after this operation. -** ** See also: NotFound, Found, NotExists */ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; - int takeJump; int ii; VdbeCursor *pC; int res; @@ -77667,14 +71231,10 @@ case OP_Found: { /* jump, in3 */ assert( pOp->p4type==P4_INT32 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); -#ifdef SQLITE_DEBUG - pC->seekOp = pOp->opcode; -#endif pIn3 = &aMem[pOp->p3]; - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); + assert( pC->pCursor!=0 ); assert( pC->isTable==0 ); - pFree = 0; + pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; @@ -77690,27 +71250,28 @@ case OP_Found: { /* jump, in3 */ }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree - ); + ); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); - ExpandBlob(pIn3); + assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; - takeJump = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not ** conflict */ - for(ii=0; iinField; ii++){ - if( pIdxKey->aMem[ii].flags & MEM_Null ){ - takeJump = 1; + for(ii=0; iip2 - 1; VdbeBranchTaken(1,2); break; } } } - rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res); - sqlite3DbFree(db, pFree); + rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); + if( pOp->p4.i==0 ){ + sqlite3DbFree(db, pFree); + } if( rc!=SQLITE_OK ){ break; } @@ -77721,10 +71282,10 @@ case OP_Found: { /* jump, in3 */ pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ VdbeBranchTaken(alreadyExists!=0,2); - if( alreadyExists ) goto jump_to_p2; + if( alreadyExists ) pc = pOp->p2 - 1; }else{ - VdbeBranchTaken(takeJump||alreadyExists==0,2); - if( takeJump || !alreadyExists ) goto jump_to_p2; + VdbeBranchTaken(alreadyExists==0,2); + if( !alreadyExists ) pc = pOp->p2 - 1; } break; } @@ -77734,18 +71295,13 @@ case OP_Found: { /* jump, in3 */ ** ** P1 is the index of a cursor open on an SQL table btree (with integer ** keys). P3 is an integer rowid. If P1 does not contain a record with -** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an -** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then -** leave the cursor pointing at that record and fall through to the next -** instruction. +** rowid P3 then jump immediately to P2. If P1 does contain a record +** with rowid P3 then leave the cursor pointing at that record and fall +** through to the next instruction. ** ** The OP_NotFound opcode performs the same operation on index btrees ** (with arbitrary multi-value keys). ** -** This opcode leaves the cursor in a state where it cannot be advanced -** in either direction. In other words, the Next and Prev opcodes will -** not work following this opcode. -** ** See also: Found, NotFound, NoConflict */ case OP_NotExists: { /* jump, in3 */ @@ -77759,31 +71315,24 @@ case OP_NotExists: { /* jump, in3 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); -#ifdef SQLITE_DEBUG - pC->seekOp = 0; -#endif assert( pC->isTable ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; + assert( pC->pseudoTableReg==0 ); + pCrsr = pC->pCursor; assert( pCrsr!=0 ); res = 0; iKey = pIn3->u.i; rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); - assert( rc==SQLITE_OK || res==0 ); - pC->movetoTarget = iKey; /* Used by OP_Delete */ + pC->lastRowid = pIn3->u.i; + pC->rowidIsValid = res==0 ?1:0; pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; VdbeBranchTaken(res!=0,2); - pC->seekResult = res; if( res!=0 ){ - assert( rc==SQLITE_OK ); - if( pOp->p2==0 ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - goto jump_to_p2; - } + pc = pOp->p2 - 1; + assert( pC->rowidIsValid==0 ); } + pC->seekResult = res; break; } @@ -77795,11 +71344,9 @@ case OP_NotExists: { /* jump, in3 */ ** The sequence number on the cursor is incremented after this ** instruction. */ -case OP_Sequence: { /* out2 */ +case OP_Sequence: { /* out2-prerelease */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( p->apCsr[pOp->p1]!=0 ); - assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB ); - pOut = out2Prerelease(p, pOp); pOut->u.i = p->apCsr[pOp->p1]->seqCount++; break; } @@ -77820,7 +71367,7 @@ case OP_Sequence: { /* out2 */ ** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. */ -case OP_NewRowid: { /* out2 */ +case OP_NewRowid: { /* out2-prerelease */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ int res; /* Result of an sqlite3BtreeLast() */ @@ -77830,13 +71377,12 @@ case OP_NewRowid: { /* out2 */ v = 0; res = 0; - pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - { + if( NEVER(pC->pCursor==0) ){ + /* The zero initialization above is all that is needed */ + }else{ /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. ** @@ -77863,15 +71409,15 @@ case OP_NewRowid: { /* out2 */ #endif if( !pC->useRandomRowid ){ - rc = sqlite3BtreeLast(pC->uc.pCursor, &res); + rc = sqlite3BtreeLast(pC->pCursor, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res ){ v = 1; /* IMP: R-61914-48074 */ }else{ - assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) ); - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); + assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ if( v>=MAX_ROWID ){ pC->useRandomRowid = 1; @@ -77918,20 +71464,32 @@ case OP_NewRowid: { /* out2 */ ** it finds one that is not previously used. */ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is ** an AUTOINCREMENT table. */ + /* on the first attempt, simply do one more than previous */ + v = lastRowid; + v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ + v++; /* ensure non-zero */ cnt = 0; - do{ - sqlite3_randomness(sizeof(v), &v); - v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ - }while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v, + while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v, 0, &res))==SQLITE_OK) && (res==0) - && (++cnt<100)); + && (++cnt<100)){ + /* collision - try another random rowid */ + sqlite3_randomness(sizeof(v), &v); + if( cnt<5 ){ + /* try "small" random rowids for the initial attempts */ + v &= 0xffffff; + }else{ + v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ + } + v++; /* ensure non-zero */ + } if( rc==SQLITE_OK && res==0 ){ rc = SQLITE_FULL; /* IMP: R-38219-53002 */ goto abort_due_to_error; } assert( v>0 ); /* EV: R-40812-03570 */ } + pC->rowidIsValid = 0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } @@ -78002,8 +71560,8 @@ case OP_InsertInt: { assert( memIsValid(pData) ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); + assert( pC->pCursor!=0 ); + assert( pC->pseudoTableReg==0 ); assert( pC->isTable ); REGISTER_TRACE(pOp->p2, pData); @@ -78032,10 +71590,11 @@ case OP_InsertInt: { }else{ nZero = 0; } - rc = sqlite3BtreeInsert(pC->uc.pCursor, 0, iKey, + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pData->z, pData->n, nZero, (pOp->p5 & OPFLAG_APPEND)!=0, seekResult ); + pC->rowidIsValid = 0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -78051,15 +71610,14 @@ case OP_InsertInt: { break; } -/* Opcode: Delete P1 P2 * P4 P5 +/* Opcode: Delete P1 P2 * P4 * ** ** Delete the record at which the P1 cursor is currently pointing. ** -** If the P5 parameter is non-zero, the cursor will be left pointing at -** either the next or the previous record in the table. If it is left -** pointing at the next record, then the next Next instruction will be a -** no-op. As a result, in this case it is OK to delete a record from within a -** Next loop. If P5 is zero, then the cursor is left in an undefined state. +** The cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op. Hence it is OK to delete +** a record from within an Next loop. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is ** incremented (otherwise not). @@ -78073,39 +71631,33 @@ case OP_InsertInt: { ** using OP_NotFound prior to invoking this opcode. */ case OP_Delete: { + i64 iKey; VdbeCursor *pC; - u8 hasUpdateCallback; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); + assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + iKey = pC->lastRowid; /* Only used for the update hook */ + + /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or + ** OP_Column on the same table without any intervening operations that + ** might move or invalidate the cursor. Hence cursor pC is always pointing + ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation + ** below is always a no-op and cannot fail. We will run it anyhow, though, + ** to guard against future changes to the code generator. + **/ assert( pC->deferredMoveto==0 ); + rc = sqlite3VdbeCursorMoveto(pC); + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable; - if( pOp->p5 && hasUpdateCallback ){ - sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); - } - -#ifdef SQLITE_DEBUG - /* The seek operation that positioned the cursor prior to OP_Delete will - ** have also set the pC->movetoTarget field to the rowid of the row that - ** is being deleted */ - if( pOp->p4.z && pC->isTable && pOp->p5==0 ){ - i64 iKey = 0; - sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); - assert( pC->movetoTarget==iKey ); - } -#endif - - rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); + rc = sqlite3BtreeDelete(pC->pCursor); pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && hasUpdateCallback ){ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, - db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget); + db->aDb[pC->iDb].zName, pOp->p4.z, iKey); assert( pC->iDb>=0 ); } if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; @@ -78125,12 +71677,12 @@ case OP_ResetCount: { } /* Opcode: SorterCompare P1 P2 P3 P4 -** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2 +** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 ** ** P1 is a sorter cursor. This instruction compares a prefix of the -** record blob in register P3 against a prefix of the entry that -** the sorter cursor currently points to. Only the first P4 fields -** of r[P3] and the sorter record are compared. +** the record blob in register P3 against a prefix of the entry that +** the sorter cursor currently points to. The final P4 fields of both +** the P3 and sorter record are ignored. ** ** If either P3 or the sorter contains a NULL in one of their significant ** fields (not counting the P4 fields at the end which are ignored) then @@ -78142,31 +71694,25 @@ case OP_ResetCount: { case OP_SorterCompare: { VdbeCursor *pC; int res; - int nKeyCol; + int nIgnore; pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); assert( pOp->p4type==P4_INT32 ); pIn3 = &aMem[pOp->p3]; - nKeyCol = pOp->p4.i; - res = 0; - rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); + nIgnore = pOp->p4.i; + rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res); VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; + if( res ){ + pc = pOp->p2-1; + } break; }; -/* Opcode: SorterData P1 P2 P3 * * +/* Opcode: SorterData P1 P2 * * * ** Synopsis: r[P2]=data ** ** Write into register P2 the current sorter data for sorter cursor P1. -** Then clear the column header cache on cursor P3. -** -** This opcode is normally use to move a record out of the sorter and into -** a register that is the source for a pseudo-table cursor created using -** OpenPseudo. That pseudo-table cursor is the one that is identified by -** parameter P3. Clearing the P3 column cache as part of this opcode saves -** us from having to issue a separate NullRow instruction to clear that cache. */ case OP_SorterData: { VdbeCursor *pC; @@ -78176,8 +71722,6 @@ case OP_SorterData: { assert( isSorter(pC) ); rc = sqlite3VdbeSorterRowkey(pC, pOut); assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; break; } @@ -78216,28 +71760,24 @@ case OP_RowData: { /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); assert( isSorter(pC)==0 ); assert( pC->isTable || pOp->opcode!=OP_RowData ); assert( pC->isTable==0 || pOp->opcode==OP_RowData ); + assert( pC!=0 ); assert( pC->nullRow==0 ); - assert( pC->uc.pCursor!=0 ); - pCrsr = pC->uc.pCursor; + assert( pC->pseudoTableReg==0 ); + assert( pC->pCursor!=0 ); + pCrsr = pC->pCursor; + assert( sqlite3BtreeCursorIsValid(pCrsr) ); /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or ** OP_Rewind/Op_Next with no intervening instructions that might invalidate - ** the cursor. If this where not the case, on of the following assert()s - ** would fail. Should this ever change (because of changes in the code - ** generator) then the fix would be to insert a call to - ** sqlite3VdbeCursorMoveto(). + ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always + ** a no-op and can never fail. But we leave it in place as a safety. */ assert( pC->deferredMoveto==0 ); - assert( sqlite3BtreeCursorIsValid(pCrsr) ); -#if 0 /* Not required due to the previous to assert() statements */ rc = sqlite3VdbeCursorMoveto(pC); - if( rc!=SQLITE_OK ) goto abort_due_to_error; -#endif + if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; if( pC->isTable==0 ){ assert( !pC->isTable ); @@ -78254,8 +71794,7 @@ case OP_RowData: { goto too_big; } } - testcase( n==0 ); - if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ + if( sqlite3VdbeMemGrow(pOut, n, 0) ){ goto no_mem; } pOut->n = n; @@ -78281,42 +71820,39 @@ case OP_RowData: { ** be a separate OP_VRowid opcode for use with virtual tables, but this ** one opcode now works for both table types. */ -case OP_Rowid: { /* out2 */ +case OP_Rowid: { /* out2-prerelease */ VdbeCursor *pC; i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; - pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); + assert( pC->pseudoTableReg==0 || pC->nullRow ); if( pC->nullRow ){ pOut->flags = MEM_Null; break; }else if( pC->deferredMoveto ){ v = pC->movetoTarget; #ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( pC->eCurType==CURTYPE_VTAB ){ - assert( pC->uc.pVCur!=0 ); - pVtab = pC->uc.pVCur->pVtab; + }else if( pC->pVtabCursor ){ + pVtab = pC->pVtabCursor->pVtab; pModule = pVtab->pModule; assert( pModule->xRowid ); - rc = pModule->xRowid(pC->uc.pVCur, &v); + rc = pModule->xRowid(pC->pVtabCursor, &v); sqlite3VtabImportErrmsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0 ); - rc = sqlite3VdbeCursorRestore(pC); + assert( pC->pCursor!=0 ); + rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; - if( pC->nullRow ){ - pOut->flags = MEM_Null; - break; + if( pC->rowidIsValid ){ + v = pC->lastRowid; + }else{ + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */ } - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); - assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ } pOut->u.i = v; break; @@ -78335,25 +71871,21 @@ case OP_NullRow: { pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pC->nullRow = 1; + pC->rowidIsValid = 0; pC->cacheStatus = CACHE_STALE; - if( pC->eCurType==CURTYPE_BTREE ){ - assert( pC->uc.pCursor!=0 ); - sqlite3BtreeClearCursor(pC->uc.pCursor); + if( pC->pCursor ){ + sqlite3BtreeClearCursor(pC->pCursor); } break; } -/* Opcode: Last P1 P2 P3 * * +/* Opcode: Last P1 P2 * * * ** -** The next use of the Rowid or Column or Prev instruction for P1 +** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. -** -** This opcode leaves the cursor configured to move in reverse order, -** from the end toward the beginning. In other words, the cursor is -** configured to use Prev, not Next. */ case OP_Last: { /* jump */ VdbeCursor *pC; @@ -78363,21 +71895,17 @@ case OP_Last: { /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; + pCrsr = pC->pCursor; res = 0; assert( pCrsr!=0 ); rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = (u8)res; pC->deferredMoveto = 0; + pC->rowidIsValid = 0; pC->cacheStatus = CACHE_STALE; - pC->seekResult = pOp->p3; -#ifdef SQLITE_DEBUG - pC->seekOp = OP_Last; -#endif if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; + if( res ) pc = pOp->p2 - 1; } break; } @@ -78408,13 +71936,9 @@ case OP_Sort: { /* jump */ ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. -** If the table or index is empty, jump immediately to P2. -** If the table or index is not empty, fall through to the following -** instruction. -** -** This opcode leaves the cursor configured to move in forward order, -** from the beginning toward the end. In other words, the cursor is -** configured to use Next, not Prev. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. */ case OP_Rewind: { /* jump */ VdbeCursor *pC; @@ -78426,23 +71950,22 @@ case OP_Rewind: { /* jump */ assert( pC!=0 ); assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); res = 1; -#ifdef SQLITE_DEBUG - pC->seekOp = OP_Rewind; -#endif if( isSorter(pC) ){ - rc = sqlite3VdbeSorterRewind(pC, &res); + rc = sqlite3VdbeSorterRewind(db, pC, &res); }else{ - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; + pCrsr = pC->pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + pC->rowidIsValid = 0; } pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; + if( res ){ + pc = pOp->p2 - 1; + } break; } @@ -78453,10 +71976,6 @@ case OP_Rewind: { /* jump */ ** to the following instruction. But if the cursor advance was successful, ** jump immediately to P2. ** -** The Next opcode is only valid following an SeekGT, SeekGE, or -** OP_Rewind opcode used to position the cursor. Next is not allowed -** to follow SeekLT, SeekLE, or OP_Last. -** ** The P1 cursor must be for a real table, not a pseudo-table. P1 must have ** been opened prior to this opcode or the program will segfault. ** @@ -78475,7 +71994,7 @@ case OP_Rewind: { /* jump */ */ /* Opcode: NextIfOpen P1 P2 P3 P4 P5 ** -** This opcode works just like Next except that if cursor P1 is not +** This opcode works just like OP_Next except that if cursor P1 is not ** open it behaves a no-op. */ /* Opcode: Prev P1 P2 P3 P4 P5 @@ -78485,11 +72004,6 @@ case OP_Rewind: { /* jump */ ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. ** -** -** The Prev opcode is only valid following an SeekLT, SeekLE, or -** OP_Last opcode used to position the cursor. Prev is not allowed -** to follow SeekGT, SeekGE, or OP_Rewind. -** ** The P1 cursor must be for a real table, not a pseudo-table. If P1 is ** not open then the behavior is undefined. ** @@ -78506,7 +72020,7 @@ case OP_Rewind: { /* jump */ */ /* Opcode: PrevIfOpen P1 P2 P3 P4 P5 ** -** This opcode works just like Prev except that if cursor P1 is not +** This opcode works just like OP_Prev except that if cursor P1 is not ** open it behaves a no-op. */ case OP_SorterNext: { /* jump */ @@ -78530,37 +72044,28 @@ case OP_Next: /* jump */ res = pOp->p3; assert( pC!=0 ); assert( pC->deferredMoveto==0 ); - assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->pCursor ); assert( res==0 || (res==1 && pC->isTable==0) ); testcase( res==1 ); assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); - - /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. - ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ - assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen - || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE - || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); - assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen - || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last ); - - rc = pOp->p4.xAdvance(pC->uc.pCursor, &res); + rc = pOp->p4.xAdvance(pC->pCursor, &res); next_tail: pC->cacheStatus = CACHE_STALE; VdbeBranchTaken(res==0,2); if( res==0 ){ pC->nullRow = 0; + pc = pOp->p2 - 1; p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif - goto jump_to_p2_and_check_for_interrupt; }else{ pC->nullRow = 1; } + pC->rowidIsValid = 0; goto check_for_interrupt; } @@ -78588,6 +72093,7 @@ next_tail: case OP_SorterInsert: /* in2 */ case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; + BtCursor *pCrsr; int nKey; const char *zKey; @@ -78597,17 +72103,18 @@ case OP_IdxInsert: { /* in2 */ assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; assert( pIn2->flags & MEM_Blob ); + pCrsr = pC->pCursor; if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert ); + assert( pCrsr!=0 ); assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ - if( pOp->opcode==OP_SorterInsert ){ - rc = sqlite3VdbeSorterWrite(pC, pIn2); + if( isSorter(pC) ){ + rc = sqlite3VdbeSorterWrite(db, pC, pIn2); }else{ nKey = pIn2->n; zKey = pIn2->z; - rc = sqlite3BtreeInsert(pC->uc.pCursor, zKey, nKey, "", 0, 0, pOp->p3, + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); @@ -78635,8 +72142,7 @@ case OP_IdxDelete: { assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; + pCrsr = pC->pCursor; assert( pCrsr!=0 ); assert( pOp->p5==0 ); r.pKeyInfo = pC->pKeyInfo; @@ -78648,7 +72154,7 @@ case OP_IdxDelete: { #endif rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ - rc = sqlite3BtreeDelete(pCrsr, 0); + rc = sqlite3BtreeDelete(pCrsr); } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; @@ -78664,29 +72170,21 @@ case OP_IdxDelete: { ** ** See also: Rowid, MakeRecord. */ -case OP_IdxRowid: { /* out2 */ +case OP_IdxRowid: { /* out2-prerelease */ BtCursor *pCrsr; VdbeCursor *pC; i64 rowid; - pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; + pCrsr = pC->pCursor; assert( pCrsr!=0 ); pOut->flags = MEM_Null; - assert( pC->isTable==0 ); + rc = sqlite3VdbeCursorMoveto(pC); + if( NEVER(rc) ) goto abort_due_to_error; assert( pC->deferredMoveto==0 ); - - /* sqlite3VbeCursorRestore() can only fail if the record has been deleted - ** out from under the cursor. That will never happend for an IdxRowid - ** opcode, hence the NEVER() arround the check of the return value. - */ - rc = sqlite3VdbeCursorRestore(pC); - if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - + assert( pC->isTable==0 ); if( !pC->nullRow ){ rowid = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); @@ -78755,8 +72253,7 @@ case OP_IdxGE: { /* jump */ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->isOrdered ); - assert( pC->eCurType==CURTYPE_BTREE ); - assert( pC->uc.pCursor!=0); + assert( pC->pCursor!=0); assert( pC->deferredMoveto==0 ); assert( pOp->p5==0 || pOp->p5==1 ); assert( pOp->p4type==P4_INT32 ); @@ -78774,7 +72271,7 @@ case OP_IdxGE: { /* jump */ { int i; for(i=0; iopcode&1)==(OP_IdxLT&1) ){ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); @@ -78784,7 +72281,9 @@ case OP_IdxGE: { /* jump */ res++; } VdbeBranchTaken(res>0,2); - if( res>0 ) goto jump_to_p2; + if( res>0 ){ + pc = pOp->p2 - 1 ; + } break; } @@ -78808,19 +72307,33 @@ case OP_IdxGE: { /* jump */ ** ** See also: Clear */ -case OP_Destroy: { /* out2 */ +case OP_Destroy: { /* out2-prerelease */ int iMoved; + int iCnt; + Vdbe *pVdbe; int iDb; assert( p->readOnly==0 ); - pOut = out2Prerelease(p, pOp); +#ifndef SQLITE_OMIT_VIRTUALTABLE + iCnt = 0; + for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ + if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader + && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 + ){ + iCnt++; + } + } +#else + iCnt = db->nVdbeRead; +#endif pOut->flags = MEM_Null; - if( db->nVdbeRead > db->nVDestroy+1 ){ + if( iCnt>1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ iDb = pOp->p3; - assert( DbMaskTest(p->btreeMask, iDb) ); + assert( iCnt==1 ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; @@ -78860,7 +72373,7 @@ case OP_Clear: { nChange = 0; assert( p->readOnly==0 ); - assert( DbMaskTest(p->btreeMask, pOp->p2) ); + assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); @@ -78889,12 +72402,11 @@ case OP_ResetSorter: { assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - if( isSorter(pC) ){ - sqlite3VdbeSorterReset(db, pC->uc.pSorter); + if( pC->pSorter ){ + sqlite3VdbeSorterReset(db, pC->pSorter); }else{ - assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->isEphemeral ); - rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor); + rc = sqlite3BtreeClearTableOfCursor(pC->pCursor); } break; } @@ -78923,16 +72435,15 @@ case OP_ResetSorter: { ** ** See documentation on OP_CreateTable for additional information. */ -case OP_CreateIndex: /* out2 */ -case OP_CreateTable: { /* out2 */ +case OP_CreateIndex: /* out2-prerelease */ +case OP_CreateTable: { /* out2-prerelease */ int pgno; int flags; Db *pDb; - pOut = out2Prerelease(p, pOp); pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); @@ -79020,8 +72531,7 @@ case OP_LoadAnalysis: { ** ** Remove the internal (in-memory) data structures that describe ** the table named P4 in database P1. This is called after a table -** is dropped from disk (using the Destroy opcode) in order to keep -** the internal representation of the +** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTable: { @@ -79033,8 +72543,7 @@ case OP_DropTable: { ** ** Remove the internal (in-memory) data structures that describe ** the index named P4 in database P1. This is called after an index -** is dropped from disk (using the Destroy opcode) -** in order to keep the internal representation of the +** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropIndex: { @@ -79046,8 +72555,7 @@ case OP_DropIndex: { ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P4 in database P1. This is called after a trigger -** is dropped from disk (using the Destroy opcode) in order to keep -** the internal representation of the +** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTrigger: { @@ -79100,7 +72608,7 @@ case OP_IntegrityCk: { } aRoot[j] = 0; assert( pOp->p5nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p5) ); + assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, (int)pnErr->u.i, &nErr); sqlite3DbFree(db, aRoot); @@ -79155,12 +72663,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */ ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); - goto jump_to_p2_and_check_for_interrupt; }else{ /* A value was pulled from the index */ - VdbeBranchTaken(0,2); sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); + VdbeBranchTaken(0,2); } goto check_for_interrupt; } @@ -79211,7 +72719,10 @@ case OP_RowSetTest: { /* jump, in1, in3 */ if( iSet ){ exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); VdbeBranchTaken(exists!=0,2); - if( exists ) goto jump_to_p2; + if( exists ){ + pc = pOp->p2 - 1; + break; + } } if( iSet>=0 ){ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); @@ -79270,7 +72781,7 @@ case OP_Program: { /* jump */ if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ rc = SQLITE_ERROR; - sqlite3VdbeError(p, "too many levels of trigger recursion"); + sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion"); break; } @@ -79300,7 +72811,7 @@ case OP_Program: { /* jump */ pFrame->v = p; pFrame->nChildMem = nMem; pFrame->nChildCsr = pProgram->nCsr; - pFrame->pc = (int)(pOp - aOp); + pFrame->pc = pc; pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; @@ -79310,9 +72821,6 @@ case OP_Program: { /* jump */ pFrame->token = pProgram->token; pFrame->aOnceFlag = p->aOnceFlag; pFrame->nOnceFlag = p->nOnceFlag; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pFrame->anExec = p->anExec; -#endif pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ @@ -79323,14 +72831,13 @@ case OP_Program: { /* jump */ pFrame = pRt->u.pFrame; assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); assert( pProgram->nCsr==pFrame->nChildCsr ); - assert( (int)(pOp - aOp)==pFrame->pc ); + assert( pc==pFrame->pc ); } p->nFrame++; pFrame->pParent = p->pFrame; pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; - pFrame->nDbChange = p->db->nChange; p->nChange = 0; p->pFrame = pFrame; p->aMem = aMem = &VdbeFrameMem(pFrame)[-1]; @@ -79341,10 +72848,7 @@ case OP_Program: { /* jump */ p->nOp = pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; p->nOnceFlag = pProgram->nOnce; -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - p->anExec = 0; -#endif - pOp = &aOp[-1]; + pc = -1; memset(p->aOnceFlag, 0, p->nOnceFlag); break; @@ -79362,10 +72866,9 @@ case OP_Program: { /* jump */ ** the value of the P1 argument to the value of the P1 argument to the ** calling OP_Program instruction. */ -case OP_Param: { /* out2 */ +case OP_Param: { /* out2-prerelease */ VdbeFrame *pFrame; Mem *pIn; - pOut = out2Prerelease(p, pOp); pFrame = p->pFrame; pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); @@ -79409,10 +72912,10 @@ case OP_FkCounter: { case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); - if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); - if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; } @@ -79449,189 +72952,122 @@ case OP_MemMax: { /* in2 */ } #endif /* SQLITE_OMIT_AUTOINCREMENT */ -/* Opcode: IfPos P1 P2 P3 * * -** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 +/* Opcode: IfPos P1 P2 * * * +** Synopsis: if r[P1]>0 goto P2 ** -** Register P1 must contain an integer. -** If the value of register P1 is 1 or greater, subtract P3 from the -** value in P1 and jump to P2. +** If the value of register P1 is 1 or greater, jump to P2. ** -** If the initial value of register P1 is less than 1, then the -** value is unchanged and control passes through to the next instruction. +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken( pIn1->u.i>0, 2); if( pIn1->u.i>0 ){ - pIn1->u.i -= pOp->p3; - goto jump_to_p2; + pc = pOp->p2 - 1; } break; } -/* Opcode: SetIfNotPos P1 P2 P3 * * -** Synopsis: if r[P1]<=0 then r[P2]=P3 +/* Opcode: IfNeg P1 P2 * * * +** Synopsis: if r[P1]<0 goto P2 ** -** Register P1 must contain an integer. -** If the value of register P1 is not positive (if it is less than 1) then -** set the value of register P2 to be the integer P3. -*/ -case OP_SetIfNotPos: { /* in1, in2 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i<=0 ){ - pOut = out2Prerelease(p, pOp); - pOut->u.i = pOp->p3; - } - break; -} - -/* Opcode: IfNotZero P1 P2 P3 * * -** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 +** If the value of register P1 is less than zero, jump to P2. ** -** Register P1 must contain an integer. If the content of register P1 is -** initially nonzero, then subtract P3 from the value in register P1 and -** jump to P2. If register P1 is initially zero, leave it unchanged -** and fall through. +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. */ -case OP_IfNotZero: { /* jump, in1 */ +case OP_IfNeg: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken(pIn1->u.i<0, 2); - if( pIn1->u.i ){ - pIn1->u.i -= pOp->p3; - goto jump_to_p2; + if( pIn1->u.i<0 ){ + pc = pOp->p2 - 1; } break; } -/* Opcode: DecrJumpZero P1 P2 * * * -** Synopsis: if (--r[P1])==0 goto P2 +/* Opcode: IfZero P1 P2 P3 * * +** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2 ** -** Register P1 must hold an integer. Decrement the value in register P1 -** then jump to P2 if the new value is exactly zero. +** The register P1 must contain an integer. Add literal P3 to the +** value in register P1. If the result is exactly 0, jump to P2. +** +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. */ -case OP_DecrJumpZero: { /* jump, in1 */ +case OP_IfZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); - pIn1->u.i--; + pIn1->u.i += pOp->p3; VdbeBranchTaken(pIn1->u.i==0, 2); - if( pIn1->u.i==0 ) goto jump_to_p2; + if( pIn1->u.i==0 ){ + pc = pOp->p2 - 1; + } break; } - -/* Opcode: JumpZeroIncr P1 P2 * * * -** Synopsis: if (r[P1]++)==0 ) goto P2 -** -** The register P1 must contain an integer. If register P1 is initially -** zero, then jump to P2. Increment register P1 regardless of whether or -** not the jump is taken. -*/ -case OP_JumpZeroIncr: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - VdbeBranchTaken(pIn1->u.i==0, 2); - if( (pIn1->u.i++)==0 ) goto jump_to_p2; - break; -} - -/* Opcode: AggStep0 * P2 P3 P4 P5 -** Synopsis: accum=r[P3] step(r[P2@P5]) -** -** Execute the step function for an aggregate. The -** function has P5 arguments. P4 is a pointer to the FuncDef -** structure that specifies the function. Register P3 is the -** accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -*/ /* Opcode: AggStep * P2 P3 P4 P5 ** Synopsis: accum=r[P3] step(r[P2@P5]) ** ** Execute the step function for an aggregate. The -** function has P5 arguments. P4 is a pointer to an sqlite3_context -** object that is used to run the function. Register P3 is -** as the accumulator. +** function has P5 arguments. P4 is a pointer to the FuncDef +** structure that specifies the function. Use register +** P3 as the accumulator. ** ** The P5 arguments are taken from register P2 and its ** successors. -** -** This opcode is initially coded as OP_AggStep0. On first evaluation, -** the FuncDef stored in P4 is converted into an sqlite3_context and -** the opcode is changed. In this way, the initialization of the -** sqlite3_context only happens once, instead of on each call to the -** step function. */ -case OP_AggStep0: { - int n; - sqlite3_context *pCtx; - - assert( pOp->p4type==P4_FUNCDEF ); - n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); - if( pCtx==0 ) goto no_mem; - pCtx->pMem = 0; - pCtx->pFunc = pOp->p4.pFunc; - pCtx->iOp = (int)(pOp - aOp); - pCtx->pVdbe = p; - pCtx->argc = n; - pOp->p4type = P4_FUNCCTX; - pOp->p4.pCtx = pCtx; - pOp->opcode = OP_AggStep; - /* Fall through into OP_AggStep */ -} case OP_AggStep: { + int n; int i; - sqlite3_context *pCtx; Mem *pMem; - Mem t; + Mem *pRec; + sqlite3_context ctx; + sqlite3_value **apVal; - assert( pOp->p4type==P4_FUNCCTX ); - pCtx = pOp->p4.pCtx; - pMem = &aMem[pOp->p3]; - - /* 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 */ - if( pCtx->pMem != pMem ){ - pCtx->pMem = pMem; - for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; + n = pOp->p5; + assert( n>=0 ); + pRec = &aMem[pOp->p2]; + apVal = p->apArg; + assert( apVal || n==0 ); + for(i=0; iargc; i++){ - assert( memIsValid(pCtx->argv[i]) ); - REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); - } -#endif - + ctx.pFunc = pOp->p4.pFunc; + assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); + ctx.pMem = pMem = &aMem[pOp->p3]; pMem->n++; - sqlite3VdbeMemInit(&t, db, MEM_Null); - pCtx->pOut = &t; - pCtx->fErrorOrAux = 0; - pCtx->skipFlag = 0; - (pCtx->pFunc->xStep)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); - rc = pCtx->isError; - } - sqlite3VdbeMemRelease(&t); - }else{ - assert( t.flags==MEM_Null ); + ctx.s.flags = MEM_Null; + ctx.s.z = 0; + ctx.s.zMalloc = 0; + ctx.s.xDel = 0; + ctx.s.db = db; + ctx.isError = 0; + ctx.pColl = 0; + ctx.skipFlag = 0; + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + assert( pOp>p->aOp ); + assert( pOp[-1].p4type==P4_COLLSEQ ); + assert( pOp[-1].opcode==OP_CollSeq ); + ctx.pColl = pOp[-1].p4.pColl; } - if( pCtx->skipFlag ){ + (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; + } + if( ctx.skipFlag ){ assert( pOp[-1].opcode==OP_CollSeq ); i = pOp[-1].p1; if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } + + sqlite3VdbeMemRelease(&ctx.s); + break; } @@ -79655,7 +73091,7 @@ case OP_AggFinal: { assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); if( rc ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); @@ -79669,8 +73105,8 @@ case OP_AggFinal: { /* Opcode: Checkpoint P1 P2 P3 * * ** ** Checkpoint database P1. This is a no-op if P1 is not currently in -** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, -** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL +** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns ** SQLITE_BUSY or not, respectively. Write the number of pages in the ** WAL after the checkpoint into mem[P3+1] and the number of pages ** in the WAL that have been checkpointed after the checkpoint @@ -79688,7 +73124,6 @@ case OP_Checkpoint: { assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART - || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); if( rc==SQLITE_BUSY ){ @@ -79714,7 +73149,7 @@ case OP_Checkpoint: { ** ** Write a string containing the final journal-mode to register P2. */ -case OP_JournalMode: { /* out2 */ +case OP_JournalMode: { /* out2-prerelease */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ @@ -79723,7 +73158,6 @@ case OP_JournalMode: { /* out2 */ const char *zFilename; /* Name of database file for pPager */ #endif - pOut = out2Prerelease(p, pOp); eNew = pOp->p3; assert( eNew==PAGER_JOURNALMODE_DELETE || eNew==PAGER_JOURNALMODE_TRUNCATE @@ -79760,7 +73194,7 @@ case OP_JournalMode: { /* out2 */ ){ if( !db->autoCommit || db->nVdbeRead>1 ){ rc = SQLITE_ERROR; - sqlite3VdbeError(p, + sqlite3SetString(&p->zErrMsg, db, "cannot change %s wal mode from within a transaction", (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") ); @@ -79799,6 +73233,7 @@ case OP_JournalMode: { /* out2 */ } eNew = sqlite3PagerSetJournalMode(pPager, eNew); + pOut = &aMem[pOp->p2]; pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = (char *)sqlite3JournalModename(eNew); pOut->n = sqlite3Strlen30(pOut->z); @@ -79833,14 +73268,14 @@ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ + pc = pOp->p2 - 1; rc = SQLITE_OK; - goto jump_to_p2; } break; } @@ -79848,13 +73283,12 @@ case OP_IncrVacuum: { /* jump */ /* Opcode: Expire P1 * * * * ** -** Cause precompiled statements to expire. When an expired statement -** is executed using sqlite3_step() it will either automatically -** reprepare itself (if it was originally created using sqlite3_prepare_v2()) -** or it will fail with SQLITE_SCHEMA. +** Cause precompiled statements to become expired. An expired statement +** fails with an error code of SQLITE_SCHEMA if it is ever executed +** (via sqlite3_step()). ** ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, -** then only the currently executing statement is expired. +** then only the currently executing statement is affected. */ case OP_Expire: { if( !pOp->p1 ){ @@ -79886,12 +73320,12 @@ case OP_TableLock: { if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ int p1 = pOp->p1; assert( p1>=0 && p1nDb ); - assert( DbMaskTest(p->btreeMask, p1) ); + assert( (p->btreeMask & (((yDbMask)1)<aDb[p1].pBt, pOp->p2, isWriteLock); if( (rc&0xFF)==SQLITE_LOCKED ){ const char *z = pOp->p4.z; - sqlite3VdbeError(p, "database table is locked: %s", z); + sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z); } } break; @@ -79918,29 +73352,13 @@ case OP_VBegin: { #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCreate P1 P2 * * * +/* Opcode: VCreate P1 * * P4 * ** -** P2 is a register that holds the name of a virtual table in database -** P1. Call the xCreate method for that table. +** P4 is the name of a virtual table in database P1. Call the xCreate method +** for that table. */ case OP_VCreate: { - Mem sMem; /* For storing the record being decoded */ - const char *zTab; /* Name of the virtual table */ - - memset(&sMem, 0, sizeof(sMem)); - sMem.db = db; - /* Because P2 is always a static string, it is impossible for the - ** sqlite3VdbeMemCopy() to fail */ - assert( (aMem[pOp->p2].flags & MEM_Str)!=0 ); - assert( (aMem[pOp->p2].flags & MEM_Static)!=0 ); - rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]); - assert( rc==SQLITE_OK ); - zTab = (const char*)sqlite3_value_text(&sMem); - assert( zTab || db->mallocFailed ); - if( zTab ){ - rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); - } - sqlite3VdbeMemRelease(&sMem); + rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -79952,9 +73370,9 @@ case OP_VCreate: { ** of that table. */ case OP_VDestroy: { - db->nVDestroy++; + p->inVtabMethod = 2; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); - db->nVDestroy--; + p->inVtabMethod = 0; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -79968,34 +73386,29 @@ case OP_VDestroy: { */ case OP_VOpen: { VdbeCursor *pCur; - sqlite3_vtab_cursor *pVCur; + sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; - const sqlite3_module *pModule; + sqlite3_module *pModule; assert( p->bIsReader ); pCur = 0; - pVCur = 0; + pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; - if( pVtab==0 || NEVER(pVtab->pModule==0) ){ - rc = SQLITE_LOCKED; - break; - } - pModule = pVtab->pModule; - rc = pModule->xOpen(pVtab, &pVCur); + pModule = (sqlite3_module *)pVtab->pModule; + assert(pVtab && pModule); + rc = pModule->xOpen(pVtab, &pVtabCursor); sqlite3VtabImportErrmsg(p, pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ - pVCur->pVtab = pVtab; + pVtabCursor->pVtab = pVtab; /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); + pCur = allocateCursor(p, pOp->p1, 0, -1, 0); if( pCur ){ - pCur->uc.pVCur = pVCur; - pVtab->nRef++; + pCur->pVtabCursor = pVtabCursor; }else{ - assert( db->mallocFailed ); - pModule->xClose(pVCur); - goto no_mem; + db->mallocFailed = 1; + pModule->xClose(pVtabCursor); } } break; @@ -80028,7 +73441,7 @@ case OP_VFilter: { /* jump */ const sqlite3_module *pModule; Mem *pQuery; Mem *pArgc; - sqlite3_vtab_cursor *pVCur; + sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; VdbeCursor *pCur; int res; @@ -80040,9 +73453,9 @@ case OP_VFilter: { /* jump */ pCur = p->apCsr[pOp->p1]; assert( memIsValid(pQuery) ); REGISTER_TRACE(pOp->p3, pQuery); - assert( pCur->eCurType==CURTYPE_VTAB ); - pVCur = pCur->uc.pVCur; - pVtab = pVCur->pVtab; + assert( pCur->pVtabCursor ); + pVtabCursor = pCur->pVtabCursor; + pVtab = pVtabCursor->pVtab; pModule = pVtab->pModule; /* Grab the index number and argc parameters */ @@ -80051,19 +73464,27 @@ case OP_VFilter: { /* jump */ iQuery = (int)pQuery->u.i; /* Invoke the xFilter method */ - res = 0; - apArg = p->apArg; - for(i = 0; ixFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg); - sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pVCur); + { + res = 0; + apArg = p->apArg; + for(i = 0; iinVtabMethod = 1; + rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + p->inVtabMethod = 0; + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pVtabCursor); + } + VdbeBranchTaken(res!=0,2); + if( res ){ + pc = pOp->p2 - 1; + } } pCur->nullRow = 0; - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; + break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -80083,7 +73504,7 @@ case OP_VColumn: { sqlite3_context sContext; VdbeCursor *pCur = p->apCsr[pOp->p1]; - assert( pCur->eCurType==CURTYPE_VTAB ); + assert( pCur->pVtabCursor ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); @@ -80091,18 +73512,31 @@ case OP_VColumn: { sqlite3VdbeMemSetNull(pDest); break; } - pVtab = pCur->uc.pVCur->pVtab; + pVtab = pCur->pVtabCursor->pVtab; pModule = pVtab->pModule; assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); - sContext.pOut = pDest; - MemSetTypeFlag(pDest, MEM_Null); - rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); + + /* The output cell may already have a buffer allocated. Move + ** the current contents to sContext.s so in case the user-function + ** can use the already allocated buffer instead of allocating a + ** new one. + */ + sqlite3VdbeMemMove(&sContext.s, pDest); + MemSetTypeFlag(&sContext.s, MEM_Null); + + rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); sqlite3VtabImportErrmsg(p, pVtab); if( sContext.isError ){ rc = sContext.isError; } - sqlite3VdbeChangeEncoding(pDest, encoding); + + /* Copy the result of the function to the P3 register. We + ** do this regardless of whether or not an error occurred to ensure any + ** dynamic allocation in sContext.s (a Mem struct) is released. + */ + sqlite3VdbeChangeEncoding(&sContext.s, encoding); + sqlite3VdbeMemMove(pDest, &sContext.s); REGISTER_TRACE(pOp->p3, pDest); UPDATE_MAX_BLOBSIZE(pDest); @@ -80128,11 +73562,11 @@ case OP_VNext: { /* jump */ res = 0; pCur = p->apCsr[pOp->p1]; - assert( pCur->eCurType==CURTYPE_VTAB ); + assert( pCur->pVtabCursor ); if( pCur->nullRow ){ break; } - pVtab = pCur->uc.pVCur->pVtab; + pVtab = pCur->pVtabCursor->pVtab; pModule = pVtab->pModule; assert( pModule->xNext ); @@ -80142,15 +73576,17 @@ case OP_VNext: { /* jump */ ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ - rc = pModule->xNext(pCur->uc.pVCur); + p->inVtabMethod = 1; + rc = pModule->xNext(pCur->pVtabCursor); + p->inVtabMethod = 0; sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ - res = pModule->xEof(pCur->uc.pVCur); + res = pModule->xEof(pCur->pVtabCursor); } VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ - goto jump_to_p2_and_check_for_interrupt; + pc = pOp->p2 - 1; } goto check_for_interrupt; } @@ -80217,7 +73653,7 @@ case OP_VRename: { */ case OP_VUpdate: { sqlite3_vtab *pVtab; - const sqlite3_module *pModule; + sqlite3_module *pModule; int nArg; int i; sqlite_int64 rowid; @@ -80229,11 +73665,7 @@ case OP_VUpdate: { ); assert( p->readOnly==0 ); pVtab = pOp->p4.pVtab->pVtab; - if( pVtab==0 || NEVER(pVtab->pModule==0) ){ - rc = SQLITE_LOCKED; - break; - } - pModule = pVtab->pModule; + pModule = (sqlite3_module *)pVtab->pModule; nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ @@ -80273,8 +73705,7 @@ case OP_VUpdate: { ** ** Write the current number of pages in database P1 to memory cell P2. */ -case OP_Pagecount: { /* out2 */ - pOut = out2Prerelease(p, pOp); +case OP_Pagecount: { /* out2-prerelease */ pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); break; } @@ -80290,11 +73721,10 @@ case OP_Pagecount: { /* out2 */ ** ** Store the maximum page count after the change in register P2. */ -case OP_MaxPgcnt: { /* out2 */ +case OP_MaxPgcnt: { /* out2-prerelease */ unsigned int newMax; Btree *pBt; - pOut = out2Prerelease(p, pOp); pBt = db->aDb[pOp->p1].pBt; newMax = 0; if( pOp->p3 ){ @@ -80323,6 +73753,9 @@ case OP_Init: { /* jump */ char *zTrace; char *z; + if( pOp->p2 ){ + pc = pOp->p2 - 1; + } #ifndef SQLITE_OMIT_TRACE if( db->xTrace && !p->doingRerun @@ -80337,7 +73770,7 @@ case OP_Init: { /* jump */ if( zTrace ){ int i; for(i=0; inDb; i++){ - if( DbMaskTest(p->btreeMask, i)==0 ) continue; + if( (MASKBIT(i) & p->btreeMask)==0 ) continue; sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); } } @@ -80350,32 +73783,9 @@ case OP_Init: { /* jump */ } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ - if( pOp->p2 ) goto jump_to_p2; break; } -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* Opcode: CursorHint P1 * * P4 * -** -** Provide a hint to cursor P1 that it only needs to return rows that -** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer -** to values currently held in registers. TK_COLUMN terms in the P4 -** expression refer to columns in the b-tree to which cursor P1 is pointing. -*/ -case OP_CursorHint: { - VdbeCursor *pC; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p4type==P4_EXPR ); - pC = p->apCsr[pOp->p1]; - if( pC ){ - assert( pC->eCurType==CURTYPE_BTREE ); - sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE, - pOp->p4.pExpr, aMem); - } - break; -} -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ /* Opcode: Noop * * * * * ** @@ -80404,8 +73814,8 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { u64 endTime = sqlite3Hwtime(); - if( endTime>start ) pOrigOp->cycles += endTime - start; - pOrigOp->cnt++; + if( endTime>start ) pOp->cycles += endTime - start; + pOp->cnt++; } #endif @@ -80415,16 +73825,16 @@ default: { /* This is really OP_Noop and OP_Explain */ ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ #ifndef NDEBUG - assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] ); + assert( pc>=-1 && pcnOp ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ if( rc!=0 ) printf("rc=%d\n",rc); - if( pOrigOp->opflags & (OPFLG_OUT2) ){ - registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); + if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){ + registerTrace(pOp->p2, &aMem[pOp->p2]); } - if( pOrigOp->opflags & OPFLG_OUT3 ){ - registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); + if( pOp->opflags & OPFLG_OUT3 ){ + registerTrace(pOp->p3, &aMem[pOp->p3]); } } #endif /* SQLITE_DEBUG */ @@ -80439,7 +73849,7 @@ vdbe_error_halt: p->rc = rc; testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", - (int)(pOp - aOp), p->zSql, p->zErrMsg); + pc, p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; @@ -80461,7 +73871,7 @@ vdbe_return: ** is encountered. */ too_big: - sqlite3VdbeError(p, "string or blob too big"); + sqlite3SetString(&p->zErrMsg, db, "string or blob too big"); rc = SQLITE_TOOBIG; goto vdbe_error_halt; @@ -80469,7 +73879,7 @@ too_big: */ no_mem: db->mallocFailed = 1; - sqlite3VdbeError(p, "out of memory"); + sqlite3SetString(&p->zErrMsg, db, "out of memory"); rc = SQLITE_NOMEM; goto vdbe_error_halt; @@ -80480,7 +73890,7 @@ abort_due_to_error: assert( p->zErrMsg==0 ); if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc!=SQLITE_IOERR_NOMEM ){ - sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); } goto vdbe_error_halt; @@ -80491,7 +73901,7 @@ abort_due_to_interrupt: assert( db->u1.isInterrupted ); rc = SQLITE_INTERRUPT; p->rc = rc; - sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); goto vdbe_error_halt; } @@ -80513,8 +73923,6 @@ abort_due_to_interrupt: ** This file contains code used to implement incremental BLOB I/O. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_INCRBLOB @@ -80576,7 +73984,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ }else{ p->iOffset = pC->aType[p->iCol + pC->nField]; p->nByte = sqlite3VdbeSerialTypeLen(type); - p->pCsr = pC->uc.pCursor; + p->pCsr = pC->pCursor; sqlite3BtreeIncrblobCursor(p->pCsr); } } @@ -80604,7 +74012,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ /* ** Open a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( +SQLITE_API int sqlite3_blob_open( sqlite3* db, /* The database connection */ const char *zDb, /* The attached database containing the blob */ const char *zTable, /* The table containing the blob */ @@ -80653,18 +74061,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( Parse *pParse = 0; Incrblob *pBlob = 0; -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppBlob==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - *ppBlob = 0; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif flags = !!flags; /* flags = (flags ? 1 : 0); */ + *ppBlob = 0; sqlite3_mutex_enter(db->mutex); @@ -80747,8 +74145,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open( for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int j; for(j=0; jnKeyCol; j++){ - /* FIXME: Be smarter about indexes that use expressions */ - if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){ + if( pIdx->aiColumn[j]==iCol ){ zFault = "indexed"; } } @@ -80829,7 +74226,7 @@ blob_open_out: if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3ParserReset(pParse); sqlite3StackFree(db, pParse); @@ -80842,7 +74239,7 @@ blob_open_out: ** Close a blob handle that was previously created using ** sqlite3_blob_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; int rc; sqlite3 *db; @@ -80879,9 +74276,10 @@ static int blobReadWrite( sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; - if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ + if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; + sqlite3Error(db, SQLITE_ERROR, 0); }else if( v==0 ){ /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. @@ -80899,10 +74297,10 @@ static int blobReadWrite( sqlite3VdbeFinalize(v); p->pStmt = 0; }else{ + db->errCode = rc; v->rc = rc; } } - sqlite3Error(db, rc); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -80911,14 +74309,14 @@ static int blobReadWrite( /* ** Read data from a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); } /* ** Write data to a blob handle. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); } @@ -80928,7 +74326,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob ** so no mutex is required for access. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; return (p && p->pStmt) ? p->nByte : 0; } @@ -80943,7 +74341,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) ** immediately return SQLITE_ABORT. */ -SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ int rc; Incrblob *p = (Incrblob *)pBlob; sqlite3 *db; @@ -80961,7 +74359,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_i char *zErr; rc = blobSeekToRow(p, iRow, &zErr); if( rc!=SQLITE_OK ){ - sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); } assert( rc!=SQLITE_SCHEMA ); @@ -80978,7 +74376,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_i /************** End of vdbeblob.c ********************************************/ /************** Begin file vdbesort.c ****************************************/ /* -** 2011-07-09 +** 2011 July 9 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -80989,205 +74387,42 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_i ** ************************************************************************* ** This file contains code for the VdbeSorter object, used in concert with -** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements -** or by SELECT statements with ORDER BY clauses that cannot be satisfied -** using indexes and without LIMIT clauses. -** -** The VdbeSorter object implements a multi-threaded external merge sort -** algorithm that is efficient even if the number of elements being sorted -** exceeds the available memory. -** -** Here is the (internal, non-API) interface between this module and the -** rest of the SQLite system: -** -** sqlite3VdbeSorterInit() Create a new VdbeSorter object. -** -** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter -** object. The row is a binary blob in the -** OP_MakeRecord format that contains both -** the ORDER BY key columns and result columns -** in the case of a SELECT w/ ORDER BY, or -** the complete record for an index entry -** in the case of a CREATE INDEX. -** -** sqlite3VdbeSorterRewind() Sort all content previously added. -** Position the read cursor on the -** first sorted element. -** -** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted -** element. -** -** sqlite3VdbeSorterRowkey() Return the complete binary blob for the -** row currently under the read cursor. -** -** sqlite3VdbeSorterCompare() Compare the binary blob for the row -** currently under the read cursor against -** another binary blob X and report if -** X is strictly less than the read cursor. -** Used to enforce uniqueness in a -** CREATE UNIQUE INDEX statement. -** -** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim -** all resources. -** -** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This -** is like Close() followed by Init() only -** much faster. -** -** The interfaces above must be called in a particular order. Write() can -** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and -** Compare() can only occur in between Rewind() and Close()/Reset(). i.e. -** -** Init() -** for each record: Write() -** Rewind() -** Rowkey()/Compare() -** Next() -** Close() -** -** Algorithm: -** -** Records passed to the sorter via calls to Write() are initially held -** unsorted in main memory. Assuming the amount of memory used never exceeds -** a threshold, when Rewind() is called the set of records is sorted using -** an in-memory merge sort. In this case, no temporary files are required -** and subsequent calls to Rowkey(), Next() and Compare() read records -** directly from main memory. -** -** If the amount of space used to store records in main memory exceeds the -** threshold, then the set of records currently in memory are sorted and -** written to a temporary file in "Packed Memory Array" (PMA) format. -** A PMA created at this point is known as a "level-0 PMA". Higher levels -** of PMAs may be created by merging existing PMAs together - for example -** merging two or more level-0 PMAs together creates a level-1 PMA. -** -** The threshold for the amount of main memory to use before flushing -** 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 -** that returned by "PRAGMA main.cache_size", in bytes. -** -** If the sorter is running in single-threaded mode, then all PMAs generated -** are appended to a single temporary file. Or, if the sorter is running in -** multi-threaded mode then up to (N+1) temporary files may be opened, where -** N is the configured number of worker threads. In this case, instead of -** sorting the records and writing the PMA to a temporary file itself, the -** calling thread usually launches a worker thread to do so. Except, if -** there are already N worker threads running, the main thread does the work -** itself. -** -** The sorter is running in multi-threaded mode if (a) the library was built -** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater -** than zero, and (b) worker threads have been enabled at runtime by calling -** "PRAGMA threads=N" with some value of N greater than 0. -** -** When Rewind() is called, any data remaining in memory is flushed to a -** final PMA. So at this point the data is stored in some number of sorted -** PMAs within temporary files on disk. -** -** If there are fewer than SORTER_MAX_MERGE_COUNT PMAs in total and the -** sorter is running in single-threaded mode, then these PMAs are merged -** incrementally as keys are retreived from the sorter by the VDBE. The -** MergeEngine object, described in further detail below, performs this -** merge. -** -** Or, if running in multi-threaded mode, then a background thread is -** launched to merge the existing PMAs. Once the background thread has -** merged T bytes of data into a single sorted PMA, the main thread -** begins reading keys from that PMA while the background thread proceeds -** with merging the next T bytes of data. And so on. -** -** Parameter T is set to half the value of the memory threshold used -** by Write() above to determine when to create a new PMA. -** -** If there are more than SORTER_MAX_MERGE_COUNT PMAs in total when -** Rewind() is called, then a hierarchy of incremental-merges is used. -** First, T bytes of data from the first SORTER_MAX_MERGE_COUNT PMAs on -** disk are merged together. Then T bytes of data from the second set, and -** so on, such that no operation ever merges more than SORTER_MAX_MERGE_COUNT -** PMAs at a time. This done is to improve locality. -** -** If running in multi-threaded mode and there are more than -** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more -** than one background thread may be created. Specifically, there may be -** one background thread for each temporary file on disk, and one background -** thread to merge the output of each of the others to a single PMA for -** the main thread to read from. +** a VdbeCursor to sort large numbers of keys (as may be required, for +** example, by CREATE INDEX statements on tables too large to fit in main +** memory). */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ -/* -** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various -** messages to stderr that may be helpful in understanding the performance -** characteristics of the sorter in multi-threaded mode. -*/ -#if 0 -# define SQLITE_DEBUG_SORTER_THREADS 1 -#endif + + +typedef struct VdbeSorterIter VdbeSorterIter; +typedef struct SorterRecord SorterRecord; +typedef struct FileWriter FileWriter; /* -** Hard-coded maximum amount of data to accumulate in memory before flushing -** to a level 0 PMA. The purpose of this limit is to prevent various integer -** overflows. 512MiB. -*/ -#define SQLITE_MAX_PMASZ (1<<29) - -/* -** Private objects used by the sorter -*/ -typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ -typedef struct PmaReader PmaReader; /* Incrementally read one PMA */ -typedef struct PmaWriter PmaWriter; /* Incrementally write one PMA */ -typedef struct SorterRecord SorterRecord; /* A record being sorted */ -typedef struct SortSubtask SortSubtask; /* A sub-task in the sort process */ -typedef struct SorterFile SorterFile; /* Temporary file object wrapper */ -typedef struct SorterList SorterList; /* In-memory list of records */ -typedef struct IncrMerger IncrMerger; /* Read & merge multiple PMAs */ - -/* -** A container for a temp file handle and the current amount of data -** stored in the file. -*/ -struct SorterFile { - sqlite3_file *pFd; /* File handle */ - i64 iEof; /* Bytes of data stored in pFd */ -}; - -/* -** An in-memory list of objects to be sorted. +** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: ** -** If aMemory==0 then each object is allocated separately and the objects -** are connected using SorterRecord.u.pNext. If aMemory!=0 then all objects -** are stored in the aMemory[] bulk memory, one right after the other, and -** are connected using SorterRecord.u.iNext. -*/ -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 */ -}; - -/* -** The MergeEngine object is used to combine two or more smaller PMAs into -** one big PMA using a merge operation. Separate PMAs all need to be -** combined into one big PMA in order to be able to step through the sorted -** records in order. +** As keys are added to the sorter, they are written to disk in a series +** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly +** the same as the cache-size allowed for temporary databases. In order +** to allow the caller to extract keys from the sorter in sorted order, +** all PMAs currently stored on disk must be merged together. This comment +** describes the data structure used to do so. The structure supports +** merging any number of arrays in a single pass with no redundant comparison +** operations. ** -** The aReadr[] array contains a PmaReader object for each of the PMAs being -** merged. An aReadr[] object either points to a valid key or else is at EOF. -** ("EOF" means "End Of File". When aReadr[] is at EOF there is no more data.) -** For the purposes of the paragraphs below, we assume that the array is -** actually N elements in size, where N is the smallest power of 2 greater -** to or equal to the number of PMAs being merged. The extra aReadr[] elements -** are treated as if they are empty (always at EOF). +** The aIter[] array contains an iterator for each of the PMAs being merged. +** An aIter[] iterator either points to a valid key or else is at EOF. For +** the purposes of the paragraphs below, we assume that the array is actually +** N elements in size, where N is the smallest power of 2 greater to or equal +** to the number of iterators being merged. The extra aIter[] elements are +** treated as if they are empty (always at EOF). ** ** The aTree[] array is also N elements in size. The value of N is stored in -** the MergeEngine.nTree variable. +** the VdbeSorter.nTree variable. ** ** The final (N/2) elements of aTree[] contain the results of comparing -** pairs of PMA keys together. Element i contains the result of -** comparing aReadr[2*i-N] and aReadr[2*i-N+1]. Whichever key is smaller, the +** pairs of iterator keys together. Element i contains the result of +** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the ** aTree element is set to the index of it. ** ** For the purposes of this comparison, EOF is considered greater than any @@ -81195,34 +74430,34 @@ struct SorterList { ** values), it doesn't matter which index is stored. ** ** The (N/4) elements of aTree[] that precede the final (N/2) described -** above contains the index of the smallest of each block of 4 PmaReaders -** And so on. So that aTree[1] contains the index of the PmaReader that +** above contains the index of the smallest of each block of 4 iterators. +** And so on. So that aTree[1] contains the index of the iterator that ** currently points to the smallest key value. aTree[0] is unused. ** ** Example: ** -** aReadr[0] -> Banana -** aReadr[1] -> Feijoa -** aReadr[2] -> Elderberry -** aReadr[3] -> Currant -** aReadr[4] -> Grapefruit -** aReadr[5] -> Apple -** aReadr[6] -> Durian -** aReadr[7] -> EOF +** aIter[0] -> Banana +** aIter[1] -> Feijoa +** aIter[2] -> Elderberry +** aIter[3] -> Currant +** aIter[4] -> Grapefruit +** aIter[5] -> Apple +** aIter[6] -> Durian +** aIter[7] -> EOF ** ** aTree[] = { X, 5 0, 5 0, 3, 5, 6 } ** ** The current element is "Apple" (the value of the key indicated by -** PmaReader 5). When the Next() operation is invoked, PmaReader 5 will +** iterator 5). When the Next() operation is invoked, iterator 5 will ** be advanced to the next key in its segment. Say the next key is ** "Eggplant": ** -** aReadr[5] -> Eggplant +** aIter[5] -> Eggplant ** -** The contents of aTree[] are updated first by comparing the new PmaReader -** 5 key to the current key of PmaReader 4 (still "Grapefruit"). The PmaReader +** The contents of aTree[] are updated first by comparing the new iterator +** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator ** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree. -** The value of PmaReader 6 - "Durian" - is now smaller than that of PmaReader +** The value of iterator 6 - "Durian" - is now smaller than that of iterator ** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Bananafile2. And instead of using a -** background thread to prepare data for the PmaReader, with a single -** threaded IncrMerger the allocate part of pTask->file2 is "refilled" with -** keys from pMerger by the calling thread whenever the PmaReader runs out -** of data. +** The following type is an iterator for a PMA. It caches the current key in +** variables nKey/aKey. If the iterator is at EOF, pFile==0. */ -struct IncrMerger { - SortSubtask *pTask; /* Task that owns this merger */ - MergeEngine *pMerger; /* Merge engine thread reads data from */ - i64 iStartOff; /* Offset to start writing file at */ - int mxSz; /* Maximum bytes of data to store */ - int bEof; /* Set to true when merge is finished */ - int bUseThread; /* True to use a bg thread for this object */ - SorterFile aFile[2]; /* aFile[0] for reading, [1] for writing */ +struct VdbeSorterIter { + i64 iReadOff; /* Current read offset */ + i64 iEof; /* 1 byte past EOF for this iterator */ + int nAlloc; /* Bytes of space at aAlloc */ + int nKey; /* Number of bytes in key */ + sqlite3_file *pFile; /* File iterator is reading from */ + u8 *aAlloc; /* Allocated space */ + u8 *aKey; /* Pointer to current key */ + u8 *aBuffer; /* Current read buffer */ + int nBuffer; /* Size of read buffer in bytes */ }; /* -** An instance of this object is used for writing a PMA. -** -** The PMA is written one record at a time. Each record is of an arbitrary -** size. But I/O is more efficient if it occurs in page-sized blocks where -** each block is aligned on a page boundary. This object caches writes to -** the PMA so that aligned, page-size blocks are written. +** An instance of this structure is used to organize the stream of records +** being written to files by the merge-sort code into aligned, page-sized +** blocks. Doing all I/O in aligned page-sized blocks helps I/O to go +** faster on many operating systems. */ -struct PmaWriter { +struct FileWriter { int eFWErr; /* Non-zero if in an error state */ u8 *aBuffer; /* Pointer to write buffer */ int nBuffer; /* Size of write buffer in bytes */ int iBufStart; /* First byte of buffer to write */ int iBufEnd; /* Last byte of buffer to write */ i64 iWriteOff; /* Offset of start of buffer in file */ - sqlite3_file *pFd; /* File handle to write to */ + sqlite3_file *pFile; /* File to write to */ }; /* -** This object is the header on a single record while that record is being -** held in memory and prior to being written out as part of a PMA. -** -** How the linked list is connected depends on how memory is being managed -** by this module. If using a separate allocation for each in-memory record -** (VdbeSorter.list.aMemory==0), then the list is always connected using the -** SorterRecord.u.pNext pointers. -** -** Or, if using the single large allocation method (VdbeSorter.list.aMemory!=0), -** then while records are being accumulated the list is linked using the -** SorterRecord.u.iNext offset. This is because the aMemory[] array may -** be sqlite3Realloc()ed while records are being accumulated. Once the VM -** has finished passing records to the sorter, or when the in-memory buffer -** is full, the list is sorted. As part of the sorting process, it is -** converted to use the SorterRecord.u.pNext pointers. See function -** vdbeSorterSort() for details. +** A structure to store a single record. All in-memory records are connected +** together into a linked list headed at VdbeSorter.pRecord using the +** SorterRecord.pNext pointer. */ struct SorterRecord { - int nVal; /* Size of the record in bytes */ - union { - SorterRecord *pNext; /* Pointer to next record in list */ - int iNext; /* Offset within aMemory of next record */ - } u; - /* The data for the record immediately follows this header */ + void *pVal; + int nVal; + SorterRecord *pNext; }; -/* Return a pointer to the buffer containing the record data for SorterRecord -** object p. Should be used as if: -** -** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } -*/ -#define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) +/* Minimum allowable value for the VdbeSorter.nWorking variable */ +#define SORTER_MIN_WORKING 10 - -/* Maximum number of PMAs that a single MergeEngine can merge */ +/* Maximum number of segments to merge in a single pass. */ #define SORTER_MAX_MERGE_COUNT 16 -static int vdbeIncrSwap(IncrMerger*); -static void vdbeIncrFree(IncrMerger *); - /* -** Free all memory belonging to the PmaReader object passed as the +** Free all memory belonging to the VdbeSorterIter object passed as the second ** argument. All structure fields are set to zero before returning. */ -static void vdbePmaReaderClear(PmaReader *pReadr){ - sqlite3_free(pReadr->aAlloc); - sqlite3_free(pReadr->aBuffer); - if( pReadr->aMap ) sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); - vdbeIncrFree(pReadr->pIncr); - memset(pReadr, 0, sizeof(PmaReader)); +static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){ + sqlite3DbFree(db, pIter->aAlloc); + sqlite3DbFree(db, pIter->aBuffer); + memset(pIter, 0, sizeof(VdbeSorterIter)); } /* -** Read the next nByte bytes of data from the PMA p. +** Read nByte bytes of data from the stream of data iterated by object p. ** If successful, set *ppOut to point to a buffer containing the data ** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite ** error code. ** -** The buffer returned in *ppOut is only valid until the +** The buffer indicated by *ppOut may only be considered valid until the ** next call to this function. */ -static int vdbePmaReadBlob( - PmaReader *p, /* PmaReader from which to take the blob */ +static int vdbeSorterIterRead( + sqlite3 *db, /* Database handle (for malloc) */ + VdbeSorterIter *p, /* Iterator */ int nByte, /* Bytes of data to read */ u8 **ppOut /* OUT: Pointer to buffer containing data */ ){ int iBuf; /* Offset within buffer to read from */ int nAvail; /* Bytes of data available in buffer */ - - if( p->aMap ){ - *ppOut = &p->aMap[p->iReadOff]; - p->iReadOff += nByte; - return SQLITE_OK; - } - assert( p->aBuffer ); /* If there is no more data to be read from the buffer, read the next @@ -81494,8 +74576,8 @@ static int vdbePmaReadBlob( } assert( nRead>0 ); - /* Readr data from the file. Return early if an error occurs. */ - rc = sqlite3OsRead(p->pFd, p->aBuffer, nRead, p->iReadOff); + /* Read data from the file. Return early if an error occurs. */ + rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff); assert( rc!=SQLITE_IOERR_SHORT_READ ); if( rc!=SQLITE_OK ) return rc; } @@ -81515,13 +74597,11 @@ static int vdbePmaReadBlob( /* Extend the p->aAlloc[] allocation if required. */ if( p->nAllocnAlloc*2); + int nNew = p->nAlloc*2; while( nByte>nNew ) nNew = nNew*2; - aNew = sqlite3Realloc(p->aAlloc, nNew); - if( !aNew ) return SQLITE_NOMEM; + p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew); + if( !p->aAlloc ) return SQLITE_NOMEM; p->nAlloc = nNew; - p->aAlloc = aNew; } /* Copy as much data as is available in the buffer into the start of @@ -81533,13 +74613,13 @@ static int vdbePmaReadBlob( /* The following loop copies up to p->nBuffer bytes per iteration into ** the p->aAlloc[] buffer. */ while( nRem>0 ){ - int rc; /* vdbePmaReadBlob() return code */ + int rc; /* vdbeSorterIterRead() return code */ int nCopy; /* Number of bytes to copy */ u8 *aNext; /* Pointer to buffer to copy data from */ nCopy = nRem; if( nRem>p->nBuffer ) nCopy = p->nBuffer; - rc = vdbePmaReadBlob(p, nCopy, &aNext); + rc = vdbeSorterIterRead(db, p, nCopy, &aNext); if( rc!=SQLITE_OK ) return rc; assert( aNext!=p->aAlloc ); memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); @@ -81556,445 +74636,235 @@ static int vdbePmaReadBlob( ** Read a varint from the stream of data accessed by p. Set *pnOut to ** the value read. */ -static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){ +static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ int iBuf; - if( p->aMap ){ - p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut); + iBuf = p->iReadOff % p->nBuffer; + if( iBuf && (p->nBuffer-iBuf)>=9 ){ + p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); }else{ - iBuf = p->iReadOff % p->nBuffer; - if( iBuf && (p->nBuffer-iBuf)>=9 ){ - p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); - }else{ - u8 aVarint[16], *a; - int i = 0, rc; - do{ - rc = vdbePmaReadBlob(p, 1, &a); - if( rc ) return rc; - aVarint[(i++)&0xf] = a[0]; - }while( (a[0]&0x80)!=0 ); - sqlite3GetVarint(aVarint, pnOut); - } + u8 aVarint[16], *a; + int i = 0, rc; + do{ + rc = vdbeSorterIterRead(db, p, 1, &a); + if( rc ) return rc; + aVarint[(i++)&0xf] = a[0]; + }while( (a[0]&0x80)!=0 ); + sqlite3GetVarint(aVarint, pnOut); } return SQLITE_OK; } -/* -** Attempt to memory map file pFile. If successful, set *pp to point to the -** new mapping and return SQLITE_OK. If the mapping is not attempted -** (because the file is too large or the VFS layer is configured not to use -** mmap), return SQLITE_OK and set *pp to NULL. -** -** Or, if an error occurs, return an SQLite error code. The final value of -** *pp is undefined in this case. -*/ -static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){ - int rc = SQLITE_OK; - if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){ - sqlite3_file *pFd = pFile->pFd; - if( pFd->pMethods->iVersion>=3 ){ - rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp); - testcase( rc!=SQLITE_OK ); - } - } - return rc; -} /* -** Attach PmaReader pReadr to file pFile (if it is not already attached to -** that file) and seek it to offset iOff within the file. Return SQLITE_OK -** if successful, or an SQLite error code if an error occurs. -*/ -static int vdbePmaReaderSeek( - SortSubtask *pTask, /* Task context */ - PmaReader *pReadr, /* Reader whose cursor is to be moved */ - SorterFile *pFile, /* Sorter file to read from */ - i64 iOff /* Offset in pFile */ -){ - int rc = SQLITE_OK; - - assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 ); - - if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ; - if( pReadr->aMap ){ - sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap); - pReadr->aMap = 0; - } - pReadr->iReadOff = iOff; - pReadr->iEof = pFile->iEof; - pReadr->pFd = pFile->pFd; - - rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap); - if( rc==SQLITE_OK && pReadr->aMap==0 ){ - int pgsz = pTask->pSorter->pgsz; - int iBuf = pReadr->iReadOff % pgsz; - if( pReadr->aBuffer==0 ){ - pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz); - if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM; - pReadr->nBuffer = pgsz; - } - if( rc==SQLITE_OK && iBuf ){ - int nRead = pgsz - iBuf; - if( (pReadr->iReadOff + nRead) > pReadr->iEof ){ - nRead = (int)(pReadr->iEof - pReadr->iReadOff); - } - rc = sqlite3OsRead( - pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff - ); - testcase( rc!=SQLITE_OK ); - } - } - - return rc; -} - -/* -** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if +** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if ** no error occurs, or an SQLite error code if one does. */ -static int vdbePmaReaderNext(PmaReader *pReadr){ - int rc = SQLITE_OK; /* Return Code */ +static int vdbeSorterIterNext( + sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */ + VdbeSorterIter *pIter /* Iterator to advance */ +){ + int rc; /* Return Code */ u64 nRec = 0; /* Size of record in bytes */ - - if( pReadr->iReadOff>=pReadr->iEof ){ - IncrMerger *pIncr = pReadr->pIncr; - int bEof = 1; - if( pIncr ){ - rc = vdbeIncrSwap(pIncr); - if( rc==SQLITE_OK && pIncr->bEof==0 ){ - rc = vdbePmaReaderSeek( - pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff - ); - bEof = 0; - } - } - - if( bEof ){ - /* This is an EOF condition */ - vdbePmaReaderClear(pReadr); - testcase( rc!=SQLITE_OK ); - return rc; - } + if( pIter->iReadOff>=pIter->iEof ){ + /* This is an EOF condition */ + vdbeSorterIterZero(db, pIter); + return SQLITE_OK; } + rc = vdbeSorterIterVarint(db, pIter, &nRec); if( rc==SQLITE_OK ){ - rc = vdbePmaReadVarint(pReadr, &nRec); - } - if( rc==SQLITE_OK ){ - pReadr->nKey = (int)nRec; - rc = vdbePmaReadBlob(pReadr, (int)nRec, &pReadr->aKey); - testcase( rc!=SQLITE_OK ); + pIter->nKey = (int)nRec; + rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey); } return rc; } /* -** Initialize PmaReader pReadr to scan through the PMA stored in file pFile +** Initialize iterator pIter to scan through the PMA stored in file pFile ** starting at offset iStart and ending at offset iEof-1. This function -** leaves the PmaReader pointing to the first key in the PMA (or EOF if the +** leaves the iterator pointing to the first key in the PMA (or EOF if the ** PMA is empty). -** -** If the pnByte parameter is NULL, then it is assumed that the file -** contains a single PMA, and that that PMA omits the initial length varint. */ -static int vdbePmaReaderInit( - SortSubtask *pTask, /* Task context */ - SorterFile *pFile, /* Sorter file to read from */ +static int vdbeSorterIterInit( + sqlite3 *db, /* Database handle */ + const VdbeSorter *pSorter, /* Sorter object */ i64 iStart, /* Start offset in pFile */ - PmaReader *pReadr, /* PmaReader to populate */ + VdbeSorterIter *pIter, /* Iterator to populate */ i64 *pnByte /* IN/OUT: Increment this value by PMA size */ ){ - int rc; + int rc = SQLITE_OK; + int nBuf; - assert( pFile->iEof>iStart ); - assert( pReadr->aAlloc==0 && pReadr->nAlloc==0 ); - assert( pReadr->aBuffer==0 ); - assert( pReadr->aMap==0 ); + nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); - rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart); - if( rc==SQLITE_OK ){ - u64 nByte; /* Size of PMA in bytes */ - rc = vdbePmaReadVarint(pReadr, &nByte); - pReadr->iEof = pReadr->iReadOff + nByte; - *pnByte += nByte; + assert( pSorter->iWriteOff>iStart ); + assert( pIter->aAlloc==0 ); + assert( pIter->aBuffer==0 ); + pIter->pFile = pSorter->pTemp1; + pIter->iReadOff = iStart; + pIter->nAlloc = 128; + pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); + pIter->nBuffer = nBuf; + pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); + + if( !pIter->aBuffer ){ + rc = SQLITE_NOMEM; + }else{ + int iBuf; + + iBuf = iStart % nBuf; + if( iBuf ){ + int nRead = nBuf - iBuf; + if( (iStart + nRead) > pSorter->iWriteOff ){ + nRead = (int)(pSorter->iWriteOff - iStart); + } + rc = sqlite3OsRead( + pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart + ); + } + + if( rc==SQLITE_OK ){ + u64 nByte; /* Size of PMA in bytes */ + pIter->iEof = pSorter->iWriteOff; + rc = vdbeSorterIterVarint(db, pIter, &nByte); + pIter->iEof = pIter->iReadOff + nByte; + *pnByte += nByte; + } } if( rc==SQLITE_OK ){ - rc = vdbePmaReaderNext(pReadr); + rc = vdbeSorterIterNext(db, pIter); } return rc; } -/* -** A version of vdbeSorterCompare() that assumes that it has already been -** determined that the first field of key1 is equal to the first field of -** key2. -*/ -static int vdbeSorterCompareTail( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - UnpackedRecord *r2 = pTask->pUnpacked; - if( *pbKey2Cached==0 ){ - sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); - *pbKey2Cached = 1; - } - return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); -} /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, -** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences -** used by the comparison. Return the result of the comparison. +** size nKey2 bytes). Argument pKeyInfo supplies the collation functions +** used by the comparison. If an error occurs, return an SQLite error code. +** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive +** value, depending on whether key1 is smaller, equal to or larger than key2. ** -** If IN/OUT parameter *pbKey2Cached is true when this function is called, -** it is assumed that (pTask->pUnpacked) contains the unpacked version -** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked -** version of key2 and *pbKey2Cached set to true before returning. +** If the bOmitRowid argument is non-zero, assume both keys end in a rowid +** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid +** is true and key1 contains even a single NULL value, it is considered to +** be less than key2. Even if key2 also contains NULL values. ** -** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set -** to SQLITE_NOMEM. +** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace +** has been allocated and contains an unpacked record that is used as key2. */ -static int vdbeSorterCompare( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ +static void vdbeSorterCompare( + const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */ + int nIgnore, /* Ignore the last nIgnore fields */ const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ + const void *pKey2, int nKey2, /* Right side of comparison */ + int *pRes /* OUT: Result of comparison */ ){ - UnpackedRecord *r2 = pTask->pUnpacked; - if( !*pbKey2Cached ){ - sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); - *pbKey2Cached = 1; - } - return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); -} + KeyInfo *pKeyInfo = pCsr->pKeyInfo; + VdbeSorter *pSorter = pCsr->pSorter; + UnpackedRecord *r2 = pSorter->pUnpacked; + int i; -/* -** A specially optimized version of vdbeSorterCompare() that assumes that -** the first field of each key is a TEXT value and that the collation -** sequence to compare them with is BINARY. -*/ -static int vdbeSorterCompareText( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - const u8 * const p1 = (const u8 * const)pKey1; - const u8 * const p2 = (const u8 * const)pKey2; - const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ - const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ - - int n1; - int n2; - int res; - - getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; - getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; - res = memcmp(v1, v2, MIN(n1, n2)); - if( res==0 ){ - res = n1 - n2; + if( pKey2 ){ + sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2); } - if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompareTail( - pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 - ); - } - }else{ - if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ - res = res * -1; - } - } - - return res; -} - -/* -** A specially optimized version of vdbeSorterCompare() that assumes that -** the first field of each key is an INTEGER value. -*/ -static int vdbeSorterCompareInt( - SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ - int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2 /* Right side of comparison */ -){ - const u8 * const p1 = (const u8 * const)pKey1; - const u8 * const p2 = (const u8 * const)pKey2; - const int s1 = p1[1]; /* Left hand serial type */ - const int s2 = p2[1]; /* Right hand serial type */ - const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ - const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ - int res; /* Return value */ - - assert( (s1>0 && s1<7) || s1==8 || s1==9 ); - assert( (s2>0 && s2<7) || s2==8 || s2==9 ); - - if( s1>7 && s2>7 ){ - res = s1 - s2; - }else{ - if( s1==s2 ){ - if( (*v1 ^ *v2) & 0x80 ){ - /* The two values have different signs */ - res = (*v1 & 0x80) ? -1 : +1; - }else{ - /* The two values have the same sign. Compare using memcmp(). */ - static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 }; - int i; - res = 0; - for(i=0; inField = pKeyInfo->nField - nIgnore; + assert( r2->nField>0 ); + for(i=0; inField; i++){ + if( r2->aMem[i].flags & MEM_Null ){ + *pRes = -1; + return; } + } + assert( r2->default_rc==0 ); + } + + *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0); +} + +/* +** This function is called to compare two iterator keys when merging +** multiple b-tree segments. Parameter iOut is the index of the aTree[] +** value to recalculate. +*/ +static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){ + VdbeSorter *pSorter = pCsr->pSorter; + int i1; + int i2; + int iRes; + VdbeSorterIter *p1; + VdbeSorterIter *p2; + + assert( iOutnTree && iOut>0 ); + + if( iOut>=(pSorter->nTree/2) ){ + i1 = (iOut - pSorter->nTree/2) * 2; + i2 = i1 + 1; + }else{ + i1 = pSorter->aTree[iOut*2]; + i2 = pSorter->aTree[iOut*2+1]; + } + + p1 = &pSorter->aIter[i1]; + p2 = &pSorter->aIter[i2]; + + if( p1->pFile==0 ){ + iRes = i2; + }else if( p2->pFile==0 ){ + iRes = i1; + }else{ + int res; + assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */ + vdbeSorterCompare( + pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res + ); + if( res<=0 ){ + iRes = i1; }else{ - if( s2>7 ){ - res = +1; - }else if( s1>7 ){ - res = -1; - }else{ - res = s1 - s2; - } - assert( res!=0 ); - - if( res>0 ){ - if( *v1 & 0x80 ) res = -1; - }else{ - if( *v2 & 0x80 ) res = +1; - } + iRes = i2; } } - if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompareTail( - pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 - ); - } - }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ - res = res * -1; - } - - return res; + pSorter->aTree[iOut] = iRes; + return SQLITE_OK; } /* ** Initialize the temporary index cursor just opened as a sorter cursor. -** -** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField) -** to determine the number of fields that should be compared from the -** records being sorted. However, if the value passed as argument nField -** is non-zero and the sorter is able to guarantee a stable sort, nField -** is used instead. This is used when sorting records for a CREATE INDEX -** statement. In this case, keys are always delivered to the sorter in -** order of the primary key, which happens to be make up the final part -** of the records being sorted. So if the sort is stable, there is never -** any reason to compare PK fields and they can be ignored for a small -** performance boost. -** -** The sorter can guarantee a stable sort when running in single-threaded -** mode, but not in multi-threaded mode. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ -SQLITE_PRIVATE int sqlite3VdbeSorterInit( - sqlite3 *db, /* Database connection (for malloc()) */ - int nField, /* Number of key fields in each record */ - VdbeCursor *pCsr /* Cursor that holds the new sorter */ -){ +SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ int pgsz; /* Page size of main database */ - int i; /* Used to iterate through aTask[] */ int mxCache; /* Cache size */ VdbeSorter *pSorter; /* The new sorter */ - KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */ - int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */ - int sz; /* Size of pSorter in bytes */ - int rc = SQLITE_OK; -#if SQLITE_MAX_WORKER_THREADS==0 -# define nWorker 0 -#else - int nWorker; -#endif - - /* Initialize the upper limit on the number of worker threads */ -#if SQLITE_MAX_WORKER_THREADS>0 - if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){ - nWorker = 0; - }else{ - nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS]; - } -#endif - - /* Do not allow the total number of threads (main thread + all workers) - ** to exceed the maximum merge count */ -#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT - if( nWorker>=SORTER_MAX_MERGE_COUNT ){ - nWorker = SORTER_MAX_MERGE_COUNT-1; - } -#endif + char *d; /* Dummy */ assert( pCsr->pKeyInfo && pCsr->pBt==0 ); - assert( pCsr->eCurType==CURTYPE_SORTER ); - szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); - sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); - - pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); - pCsr->uc.pSorter = pSorter; + pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter)); if( pSorter==0 ){ - rc = SQLITE_NOMEM; - }else{ - pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); - memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); - pKeyInfo->db = 0; - if( nField && nWorker==0 ){ - pKeyInfo->nXField += (pKeyInfo->nField - nField); - pKeyInfo->nField = nField; - } - pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); - pSorter->nTask = nWorker + 1; - pSorter->iPrev = (u8)(nWorker - 1); - pSorter->bUseThreads = (pSorter->nTask>1); - pSorter->db = db; - for(i=0; inTask; i++){ - SortSubtask *pTask = &pSorter->aTask[i]; - pTask->pSorter = pSorter; - } + return SQLITE_NOMEM; + } + + pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d); + if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM; + assert( pSorter->pUnpacked==(UnpackedRecord *)d ); - if( !sqlite3TempInMemory(db) ){ - u32 szPma = sqlite3GlobalConfig.szPma; - pSorter->mnPmaSize = szPma * pgsz; - mxCache = db->aDb[0].pSchema->cache_size; - if( mxCache<(int)szPma ) mxCache = (int)szPma; - pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); - - /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of - ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary - ** large heap allocations. - */ - if( sqlite3GlobalConfig.pScratch==0 ){ - assert( pSorter->iMemory==0 ); - pSorter->nMemory = pgsz; - pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); - if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; - } - } - - if( (pKeyInfo->nField+pKeyInfo->nXField)<13 - && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) - ){ - pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; - } + if( !sqlite3TempInMemory(db) ){ + pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); + pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; + mxCache = db->aDb[0].pSchema->cache_size; + if( mxCachemxPmaSize = mxCache * pgsz; } - return rc; + return SQLITE_OK; } -#undef nWorker /* Defined at the top of this function */ /* ** Free the list of sorted records starting at pRecord. @@ -82003,343 +74873,93 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ SorterRecord *p; SorterRecord *pNext; for(p=pRecord; p; p=pNext){ - pNext = p->u.pNext; + pNext = p->pNext; sqlite3DbFree(db, p); } } -/* -** Free all resources owned by the object indicated by argument pTask. All -** fields of *pTask are zeroed before returning. -*/ -static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ - sqlite3DbFree(db, pTask->pUnpacked); -#if SQLITE_MAX_WORKER_THREADS>0 - /* pTask->list.aMemory can only be non-zero if it was handed memory - ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ - if( pTask->list.aMemory ){ - sqlite3_free(pTask->list.aMemory); - }else -#endif - { - assert( pTask->list.aMemory==0 ); - vdbeSorterRecordFree(0, pTask->list.pList); - } - if( pTask->file.pFd ){ - sqlite3OsCloseFree(pTask->file.pFd); - } - if( pTask->file2.pFd ){ - sqlite3OsCloseFree(pTask->file2.pFd); - } - memset(pTask, 0, sizeof(SortSubtask)); -} - -#ifdef SQLITE_DEBUG_SORTER_THREADS -static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ - i64 t; - int iTask = (pTask - pTask->pSorter->aTask); - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); -} -static void vdbeSorterRewindDebug(const char *zEvent){ - i64 t; - sqlite3OsCurrentTimeInt64(sqlite3_vfs_find(0), &t); - fprintf(stderr, "%lld:X %s\n", t, zEvent); -} -static void vdbeSorterPopulateDebug( - SortSubtask *pTask, - const char *zEvent -){ - i64 t; - int iTask = (pTask - pTask->pSorter->aTask); - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:bg%d %s\n", t, iTask, zEvent); -} -static void vdbeSorterBlockDebug( - SortSubtask *pTask, - int bBlocked, - const char *zEvent -){ - if( bBlocked ){ - i64 t; - sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); - fprintf(stderr, "%lld:main %s\n", t, zEvent); - } -} -#else -# define vdbeSorterWorkDebug(x,y) -# define vdbeSorterRewindDebug(y) -# define vdbeSorterPopulateDebug(x,y) -# define vdbeSorterBlockDebug(x,y,z) -#endif - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** Join thread pTask->thread. -*/ -static int vdbeSorterJoinThread(SortSubtask *pTask){ - int rc = SQLITE_OK; - if( pTask->pThread ){ -#ifdef SQLITE_DEBUG_SORTER_THREADS - int bDone = pTask->bDone; -#endif - void *pRet = SQLITE_INT_TO_PTR(SQLITE_ERROR); - vdbeSorterBlockDebug(pTask, !bDone, "enter"); - (void)sqlite3ThreadJoin(pTask->pThread, &pRet); - vdbeSorterBlockDebug(pTask, !bDone, "exit"); - rc = SQLITE_PTR_TO_INT(pRet); - assert( pTask->bDone==1 ); - pTask->bDone = 0; - pTask->pThread = 0; - } - return rc; -} - -/* -** Launch a background thread to run xTask(pIn). -*/ -static int vdbeSorterCreateThread( - SortSubtask *pTask, /* Thread will use this task object */ - void *(*xTask)(void*), /* Routine to run in a separate thread */ - void *pIn /* Argument passed into xTask() */ -){ - assert( pTask->pThread==0 && pTask->bDone==0 ); - return sqlite3ThreadCreate(&pTask->pThread, xTask, pIn); -} - -/* -** Join all outstanding threads launched by SorterWrite() to create -** level-0 PMAs. -*/ -static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){ - int rc = rcin; - int i; - - /* This function is always called by the main user thread. - ** - ** If this function is being called after SorterRewind() has been called, - ** it is possible that thread pSorter->aTask[pSorter->nTask-1].pThread - ** is currently attempt to join one of the other threads. To avoid a race - ** condition where this thread also attempts to join the same object, join - ** thread pSorter->aTask[pSorter->nTask-1].pThread first. */ - for(i=pSorter->nTask-1; i>=0; i--){ - SortSubtask *pTask = &pSorter->aTask[i]; - int rc2 = vdbeSorterJoinThread(pTask); - if( rc==SQLITE_OK ) rc = rc2; - } - return rc; -} -#else -# define vdbeSorterJoinAll(x,rcin) (rcin) -# define vdbeSorterJoinThread(pTask) SQLITE_OK -#endif - -/* -** Allocate a new MergeEngine object capable of handling up to -** nReader PmaReader inputs. -** -** nReader is automatically rounded up to the next power of two. -** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up. -*/ -static MergeEngine *vdbeMergeEngineNew(int nReader){ - int N = 2; /* Smallest power of two >= nReader */ - int nByte; /* Total bytes of space to allocate */ - MergeEngine *pNew; /* Pointer to allocated object to return */ - - assert( nReader<=SORTER_MAX_MERGE_COUNT ); - - while( NnTree = N; - pNew->pTask = 0; - pNew->aReadr = (PmaReader*)&pNew[1]; - pNew->aTree = (int*)&pNew->aReadr[N]; - } - return pNew; -} - -/* -** Free the MergeEngine object passed as the only argument. -*/ -static void vdbeMergeEngineFree(MergeEngine *pMerger){ - int i; - if( pMerger ){ - for(i=0; inTree; i++){ - vdbePmaReaderClear(&pMerger->aReadr[i]); - } - } - sqlite3_free(pMerger); -} - -/* -** Free all resources associated with the IncrMerger object indicated by -** the first argument. -*/ -static void vdbeIncrFree(IncrMerger *pIncr){ - if( pIncr ){ -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - vdbeSorterJoinThread(pIncr->pTask); - if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd); - if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd); - } -#endif - vdbeMergeEngineFree(pIncr->pMerger); - sqlite3_free(pIncr); - } -} - /* ** Reset a sorting cursor back to its original empty state. */ SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ - int i; - (void)vdbeSorterJoinAll(pSorter, SQLITE_OK); - assert( pSorter->bUseThreads || pSorter->pReader==0 ); -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->pReader ){ - vdbePmaReaderClear(pSorter->pReader); - sqlite3DbFree(db, pSorter->pReader); - pSorter->pReader = 0; + if( pSorter->aIter ){ + int i; + for(i=0; inTree; i++){ + vdbeSorterIterZero(db, &pSorter->aIter[i]); + } + sqlite3DbFree(db, pSorter->aIter); + pSorter->aIter = 0; } -#endif - vdbeMergeEngineFree(pSorter->pMerger); - pSorter->pMerger = 0; - for(i=0; inTask; i++){ - SortSubtask *pTask = &pSorter->aTask[i]; - vdbeSortSubtaskCleanup(db, pTask); - pTask->pSorter = pSorter; + if( pSorter->pTemp1 ){ + sqlite3OsCloseFree(pSorter->pTemp1); + pSorter->pTemp1 = 0; } - if( pSorter->list.aMemory==0 ){ - vdbeSorterRecordFree(0, pSorter->list.pList); - } - pSorter->list.pList = 0; - pSorter->list.szPMA = 0; - pSorter->bUsePMA = 0; - pSorter->iMemory = 0; - pSorter->mxKeysize = 0; - sqlite3DbFree(db, pSorter->pUnpacked); - pSorter->pUnpacked = 0; + vdbeSorterRecordFree(db, pSorter->pRecord); + pSorter->pRecord = 0; + pSorter->iWriteOff = 0; + pSorter->iReadOff = 0; + pSorter->nInMemory = 0; + pSorter->nTree = 0; + pSorter->nPMA = 0; + pSorter->aTree = 0; } + /* ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. */ SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ - VdbeSorter *pSorter; - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; + VdbeSorter *pSorter = pCsr->pSorter; if( pSorter ){ sqlite3VdbeSorterReset(db, pSorter); - sqlite3_free(pSorter->list.aMemory); + sqlite3DbFree(db, pSorter->pUnpacked); sqlite3DbFree(db, pSorter); - pCsr->uc.pSorter = 0; + pCsr->pSorter = 0; } } -#if SQLITE_MAX_MMAP_SIZE>0 -/* -** The first argument is a file-handle open on a temporary file. The file -** is guaranteed to be nByte bytes or smaller in size. This function -** attempts to extend the file to nByte bytes in size and to ensure that -** the VFS has memory mapped it. -** -** Whether or not the file does end up memory mapped of course depends on -** the specific VFS implementation. -*/ -static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ - if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ - void *p = 0; - int chunksize = 4*1024; - sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); - sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); - sqlite3OsFetch(pFd, 0, (int)nByte, &p); - sqlite3OsUnfetch(pFd, 0, p); - } -} -#else -# define vdbeSorterExtendFile(x,y,z) -#endif - /* ** Allocate space for a file-handle and open a temporary file. If successful, -** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK. -** Otherwise, set *ppFd to 0 and return an SQLite error code. +** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK. +** Otherwise, set *ppFile to 0 and return an SQLite error code. */ -static int vdbeSorterOpenTempFile( - sqlite3 *db, /* Database handle doing sort */ - i64 nExtend, /* Attempt to extend file to this size */ - sqlite3_file **ppFd -){ - int rc; - if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS; - rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd, +static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){ + int dummy; + return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile, SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy ); - if( rc==SQLITE_OK ){ - i64 max = SQLITE_MAX_MMAP_SIZE; - sqlite3OsFileControlHint(*ppFd, SQLITE_FCNTL_MMAP_SIZE, (void*)&max); - if( nExtend>0 ){ - vdbeSorterExtendFile(db, *ppFd, nExtend); - } - } - return rc; } -/* -** If it has not already been allocated, allocate the UnpackedRecord -** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or -** if no allocation was required), or SQLITE_NOMEM otherwise. -*/ -static int vdbeSortAllocUnpacked(SortSubtask *pTask){ - if( pTask->pUnpacked==0 ){ - char *pFree; - pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord( - pTask->pSorter->pKeyInfo, 0, 0, &pFree - ); - assert( pTask->pUnpacked==(UnpackedRecord*)pFree ); - if( pFree==0 ) return SQLITE_NOMEM; - pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; - pTask->pUnpacked->errCode = 0; - } - return SQLITE_OK; -} - - /* ** Merge the two sorted lists p1 and p2 into a single list. ** Set *ppOut to the head of the new list. */ static void vdbeSorterMerge( - SortSubtask *pTask, /* Calling thread context */ + const VdbeCursor *pCsr, /* For pKeyInfo */ SorterRecord *p1, /* First list to merge */ SorterRecord *p2, /* Second list to merge */ SorterRecord **ppOut /* OUT: Head of merged list */ ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; - int bCached = 0; + void *pVal2 = p2 ? p2->pVal : 0; while( p1 && p2 ){ int res; - res = pTask->xCompare( - pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal - ); - + vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res); if( res<=0 ){ *pp = p1; - pp = &p1->u.pNext; - p1 = p1->u.pNext; + pp = &p1->pNext; + p1 = p1->pNext; + pVal2 = 0; }else{ *pp = p2; - pp = &p2->u.pNext; - p2 = p2->u.pNext; - bCached = 0; + pp = &p2->pNext; + p2 = p2->pNext; + if( p2==0 ) break; + pVal2 = p2->pVal; } } *pp = p1 ? p1 : p2; @@ -82347,56 +74967,27 @@ static void vdbeSorterMerge( } /* -** Return the SorterCompare function to compare values collected by the -** sorter object passed as the only argument. +** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK +** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error +** occurs. */ -static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ - if( p->typeMask==SORTER_TYPE_INTEGER ){ - return vdbeSorterCompareInt; - }else if( p->typeMask==SORTER_TYPE_TEXT ){ - return vdbeSorterCompareText; - } - return vdbeSorterCompare; -} - -/* -** Sort the linked list of records headed at pTask->pList. Return -** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if -** an error occurs. -*/ -static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ +static int vdbeSorterSort(const VdbeCursor *pCsr){ int i; SorterRecord **aSlot; SorterRecord *p; - int rc; - - rc = vdbeSortAllocUnpacked(pTask); - if( rc!=SQLITE_OK ) return rc; - - p = pList->pList; - pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); + VdbeSorter *pSorter = pCsr->pSorter; aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ return SQLITE_NOMEM; } + p = pSorter->pRecord; while( p ){ - SorterRecord *pNext; - if( pList->aMemory ){ - if( (u8*)p==pList->aMemory ){ - pNext = 0; - }else{ - assert( p->u.iNextaMemory) ); - pNext = (SorterRecord*)&pList->aMemory[p->u.iNext]; - } - }else{ - pNext = p->u.pNext; - } - - p->u.pNext = 0; + SorterRecord *pNext = p->pNext; + p->pNext = 0; for(i=0; aSlot[i]; i++){ - vdbeSorterMerge(pTask, p, aSlot[i], &p); + vdbeSorterMerge(pCsr, p, aSlot[i], &p); aSlot[i] = 0; } aSlot[i] = p; @@ -82405,43 +74996,42 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ p = 0; for(i=0; i<64; i++){ - vdbeSorterMerge(pTask, p, aSlot[i], &p); + vdbeSorterMerge(pCsr, p, aSlot[i], &p); } - pList->pList = p; + pSorter->pRecord = p; sqlite3_free(aSlot); - assert( pTask->pUnpacked->errCode==SQLITE_OK - || pTask->pUnpacked->errCode==SQLITE_NOMEM - ); - return pTask->pUnpacked->errCode; + return SQLITE_OK; } /* -** Initialize a PMA-writer object. +** Initialize a file-writer object. */ -static void vdbePmaWriterInit( - sqlite3_file *pFd, /* File handle to write to */ - PmaWriter *p, /* Object to populate */ - int nBuf, /* Buffer size */ - i64 iStart /* Offset of pFd to begin writing at */ +static void fileWriterInit( + sqlite3 *db, /* Database (for malloc) */ + sqlite3_file *pFile, /* File to write to */ + FileWriter *p, /* Object to populate */ + i64 iStart /* Offset of pFile to begin writing at */ ){ - memset(p, 0, sizeof(PmaWriter)); - p->aBuffer = (u8*)sqlite3Malloc(nBuf); + int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); + + memset(p, 0, sizeof(FileWriter)); + p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); if( !p->aBuffer ){ p->eFWErr = SQLITE_NOMEM; }else{ p->iBufEnd = p->iBufStart = (iStart % nBuf); p->iWriteOff = iStart - p->iBufStart; p->nBuffer = nBuf; - p->pFd = pFd; + p->pFile = pFile; } } /* -** Write nData bytes of data to the PMA. Return SQLITE_OK +** Write nData bytes of data to the file-write object. Return SQLITE_OK ** if successful, or an SQLite error code if an error occurs. */ -static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ +static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){ int nRem = nData; while( nRem>0 && p->eFWErr==0 ){ int nCopy = nRem; @@ -82452,7 +75042,7 @@ static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); p->iBufEnd += nCopy; if( p->iBufEnd==p->nBuffer ){ - p->eFWErr = sqlite3OsWrite(p->pFd, + p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); @@ -82466,44 +75056,43 @@ static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ } /* -** Flush any buffered data to disk and clean up the PMA-writer object. -** The results of using the PMA-writer after this call are undefined. +** Flush any buffered data to disk and clean up the file-writer object. +** The results of using the file-writer after this call are undefined. ** Return SQLITE_OK if flushing the buffered data succeeds or is not ** required. Otherwise, return an SQLite error code. ** ** Before returning, set *piEof to the offset immediately following the ** last byte written to the file. */ -static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){ +static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){ int rc; if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ - p->eFWErr = sqlite3OsWrite(p->pFd, + p->eFWErr = sqlite3OsWrite(p->pFile, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); } *piEof = (p->iWriteOff + p->iBufEnd); - sqlite3_free(p->aBuffer); + sqlite3DbFree(db, p->aBuffer); rc = p->eFWErr; - memset(p, 0, sizeof(PmaWriter)); + memset(p, 0, sizeof(FileWriter)); return rc; } /* -** Write value iVal encoded as a varint to the PMA. Return +** Write value iVal encoded as a varint to the file-write object. Return ** SQLITE_OK if successful, or an SQLite error code if an error occurs. */ -static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){ +static void fileWriterWriteVarint(FileWriter *p, u64 iVal){ int nByte; u8 aByte[10]; nByte = sqlite3PutVarint(aByte, iVal); - vdbePmaWriteBlob(p, aByte, nByte); + fileWriterWrite(p, aByte, nByte); } /* -** Write the current contents of in-memory linked-list pList to a level-0 -** PMA in the temp file belonging to sub-task pTask. Return SQLITE_OK if -** successful, or an SQLite error code otherwise. +** Write the current contents of the in-memory linked-list to a PMA. Return +** SQLITE_OK if successful, or an SQLite error code otherwise. ** ** The format of a PMA is: ** @@ -82514,256 +75103,76 @@ static void vdbePmaWriteVarint(PmaWriter *p, u64 iVal){ ** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ -static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){ - sqlite3 *db = pTask->pSorter->db; +static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ int rc = SQLITE_OK; /* Return code */ - PmaWriter writer; /* Object used to write to the file */ + VdbeSorter *pSorter = pCsr->pSorter; + FileWriter writer; -#ifdef SQLITE_DEBUG - /* Set iSz to the expected size of file pTask->file after writing the PMA. - ** This is used by an assert() statement at the end of this function. */ - i64 iSz = pList->szPMA + sqlite3VarintLen(pList->szPMA) + pTask->file.iEof; -#endif + memset(&writer, 0, sizeof(FileWriter)); - vdbeSorterWorkDebug(pTask, "enter"); - memset(&writer, 0, sizeof(PmaWriter)); - assert( pList->szPMA>0 ); + if( pSorter->nInMemory==0 ){ + assert( pSorter->pRecord==0 ); + return rc; + } + + rc = vdbeSorterSort(pCsr); /* If the first temporary PMA file has not been opened, open it now. */ - if( pTask->file.pFd==0 ){ - rc = vdbeSorterOpenTempFile(db, 0, &pTask->file.pFd); - assert( rc!=SQLITE_OK || pTask->file.pFd ); - assert( pTask->file.iEof==0 ); - assert( pTask->nPMA==0 ); - } - - /* Try to get the file to memory map */ - if( rc==SQLITE_OK ){ - vdbeSorterExtendFile(db, pTask->file.pFd, pTask->file.iEof+pList->szPMA+9); - } - - /* Sort the list */ - if( rc==SQLITE_OK ){ - rc = vdbeSorterSort(pTask, pList); + if( rc==SQLITE_OK && pSorter->pTemp1==0 ){ + rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1); + assert( rc!=SQLITE_OK || pSorter->pTemp1 ); + assert( pSorter->iWriteOff==0 ); + assert( pSorter->nPMA==0 ); } if( rc==SQLITE_OK ){ SorterRecord *p; SorterRecord *pNext = 0; - vdbePmaWriterInit(pTask->file.pFd, &writer, pTask->pSorter->pgsz, - pTask->file.iEof); - pTask->nPMA++; - vdbePmaWriteVarint(&writer, pList->szPMA); - for(p=pList->pList; p; p=pNext){ - pNext = p->u.pNext; - vdbePmaWriteVarint(&writer, p->nVal); - vdbePmaWriteBlob(&writer, SRVAL(p), p->nVal); - if( pList->aMemory==0 ) sqlite3_free(p); - } - pList->pList = p; - rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof); - } - - vdbeSorterWorkDebug(pTask, "exit"); - assert( rc!=SQLITE_OK || pList->pList==0 ); - assert( rc!=SQLITE_OK || pTask->file.iEof==iSz ); - return rc; -} - -/* -** Advance the MergeEngine to its next entry. -** Set *pbEof to true there is no next entry because -** the MergeEngine has reached the end of all its inputs. -** -** Return SQLITE_OK if successful or an error code if an error occurs. -*/ -static int vdbeMergeEngineStep( - MergeEngine *pMerger, /* The merge engine to advance to the next row */ - int *pbEof /* Set TRUE at EOF. Set false for more content */ -){ - int rc; - int iPrev = pMerger->aTree[1];/* Index of PmaReader to advance */ - SortSubtask *pTask = pMerger->pTask; - - /* Advance the current PmaReader */ - rc = vdbePmaReaderNext(&pMerger->aReadr[iPrev]); - - /* Update contents of aTree[] */ - if( rc==SQLITE_OK ){ - int i; /* Index of aTree[] to recalculate */ - PmaReader *pReadr1; /* First PmaReader to compare */ - PmaReader *pReadr2; /* Second PmaReader to compare */ - int bCached = 0; - - /* Find the first two PmaReaders to compare. The one that was just - ** advanced (iPrev) and the one next to it in the array. */ - pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; - pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; - - for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ - /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ - int iRes; - if( pReadr1->pFd==0 ){ - iRes = +1; - }else if( pReadr2->pFd==0 ){ - iRes = -1; - }else{ - iRes = pTask->xCompare(pTask, &bCached, - pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey - ); - } - - /* If pReadr1 contained the smaller value, set aTree[i] to its index. - ** Then set pReadr2 to the next PmaReader to compare to pReadr1. In this - ** case there is no cache of pReadr2 in pTask->pUnpacked, so set - ** pKey2 to point to the record belonging to pReadr2. - ** - ** Alternatively, if pReadr2 contains the smaller of the two values, - ** set aTree[i] to its index and update pReadr1. If vdbeSorterCompare() - ** was actually called above, then pTask->pUnpacked now contains - ** a value equivalent to pReadr2. So set pKey2 to NULL to prevent - ** vdbeSorterCompare() from decoding pReadr2 again. - ** - ** If the two values were equal, then the value from the oldest - ** PMA should be considered smaller. The VdbeSorter.aReadr[] array - ** is sorted from oldest to newest, so pReadr1 contains older values - ** than pReadr2 iff (pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); - pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - bCached = 0; - }else{ - if( pReadr1->pFd ) bCached = 0; - pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); - pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - } - } - *pbEof = (pMerger->aReadr[pMerger->aTree[1]].pFd==0); - } - - return (rc==SQLITE_OK ? pTask->pUnpacked->errCode : rc); -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for background threads that write level-0 PMAs. -*/ -static void *vdbeSorterFlushThread(void *pCtx){ - SortSubtask *pTask = (SortSubtask*)pCtx; - int rc; /* Return code */ - assert( pTask->bDone==0 ); - rc = vdbeSorterListToPMA(pTask, &pTask->list); - pTask->bDone = 1; - return SQLITE_INT_TO_PTR(rc); -} -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - -/* -** Flush the current contents of VdbeSorter.list to a new PMA, possibly -** using a background thread. -*/ -static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ -#if SQLITE_MAX_WORKER_THREADS==0 - pSorter->bUsePMA = 1; - return vdbeSorterListToPMA(&pSorter->aTask[0], &pSorter->list); -#else - int rc = SQLITE_OK; - int i; - SortSubtask *pTask = 0; /* Thread context used to create new PMA */ - int nWorker = (pSorter->nTask-1); - - /* Set the flag to indicate that at least one PMA has been written. - ** Or will be, anyhow. */ - pSorter->bUsePMA = 1; - - /* Select a sub-task to sort and flush the current list of in-memory - ** records to disk. If the sorter is running in multi-threaded mode, - ** round-robin between the first (pSorter->nTask-1) tasks. Except, if - ** the background thread from a sub-tasks previous turn is still running, - ** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy, - ** fall back to using the final sub-task. The first (pSorter->nTask-1) - ** sub-tasks are prefered as they use background threads - the final - ** sub-task uses the main thread. */ - for(i=0; iiPrev + i + 1) % nWorker; - pTask = &pSorter->aTask[iTest]; - if( pTask->bDone ){ - rc = vdbeSorterJoinThread(pTask); - } - if( rc!=SQLITE_OK || pTask->pThread==0 ) break; - } - - if( rc==SQLITE_OK ){ - if( i==nWorker ){ - /* Use the foreground thread for this operation */ - rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list); - }else{ - /* Launch a background thread for this operation */ - u8 *aMem = pTask->list.aMemory; - void *pCtx = (void*)pTask; - - assert( pTask->pThread==0 && pTask->bDone==0 ); - assert( pTask->list.pList==0 ); - assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 ); - - pSorter->iPrev = (u8)(pTask - pSorter->aTask); - pTask->list = pSorter->list; - pSorter->list.pList = 0; - pSorter->list.szPMA = 0; - if( aMem ){ - pSorter->list.aMemory = aMem; - pSorter->nMemory = sqlite3MallocSize(aMem); - }else if( pSorter->list.aMemory ){ - pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory); - if( !pSorter->list.aMemory ) return SQLITE_NOMEM; - } - - rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx); + fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff); + pSorter->nPMA++; + fileWriterWriteVarint(&writer, pSorter->nInMemory); + for(p=pSorter->pRecord; p; p=pNext){ + pNext = p->pNext; + fileWriterWriteVarint(&writer, p->nVal); + fileWriterWrite(&writer, p->pVal, p->nVal); + sqlite3DbFree(db, p); } + pSorter->pRecord = p; + rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff); } return rc; -#endif /* SQLITE_MAX_WORKER_THREADS!=0 */ } /* ** Add a record to the sorter. */ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( - const VdbeCursor *pCsr, /* Sorter cursor */ + sqlite3 *db, /* Database handle */ + const VdbeCursor *pCsr, /* Sorter cursor */ Mem *pVal /* Memory cell containing record */ ){ - VdbeSorter *pSorter; + VdbeSorter *pSorter = pCsr->pSorter; 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 */ - int t; /* serial type of first record field */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - getVarint32((const u8*)&pVal->z[1], t); - if( t>0 && t<10 && t!=7 ){ - pSorter->typeMask &= SORTER_TYPE_INTEGER; - }else if( t>10 && (t & 0x01) ){ - pSorter->typeMask &= SORTER_TYPE_TEXT; - }else{ - pSorter->typeMask = 0; - } assert( pSorter ); + pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n; - /* Figure out whether or not the current contents of memory should be - ** flushed to a PMA before continuing. If so, do so. - ** - ** If using the single large allocation mode (pSorter->aMemory!=0), then - ** flush the contents of memory to a new PMA if (a) at least one value is - ** already in memory and (b) the new value will not fit in memory. - ** - ** Or, if using separate allocations for each record, flush the contents - ** of memory to a PMA if either of the following are true: + pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord)); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + pNew->pVal = (void *)&pNew[1]; + memcpy(pNew->pVal, pVal->z, pVal->n); + pNew->nVal = pVal->n; + pNew->pNext = pSorter->pRecord; + pSorter->pRecord = pNew; + } + + /* See if the contents of the sorter should now be written out. They + ** are written out when either of the following are true: ** ** * The total memory allocated for the in-memory list is greater ** than (page-size * cache-size), or @@ -82771,811 +75180,161 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( ** * The total memory allocated for the in-memory list is greater ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. */ - nReq = pVal->n + sizeof(SorterRecord); - nPMA = pVal->n + sqlite3VarintLen(pVal->n); - if( pSorter->mxPmaSize ){ - if( pSorter->list.aMemory ){ - bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize; - }else{ - bFlush = ( - (pSorter->list.szPMA > pSorter->mxPmaSize) - || (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull()) - ); - } - if( bFlush ){ - rc = vdbeSorterFlushPMA(pSorter); - pSorter->list.szPMA = 0; - pSorter->iMemory = 0; - assert( rc!=SQLITE_OK || pSorter->list.pList==0 ); - } - } - - pSorter->list.szPMA += nPMA; - if( nPMA>pSorter->mxKeysize ){ - pSorter->mxKeysize = nPMA; - } - - if( pSorter->list.aMemory ){ - int nMin = pSorter->iMemory + nReq; - - if( nMin>pSorter->nMemory ){ - u8 *aNew; - int nNew = pSorter->nMemory * 2; - while( nNew < nMin ) nNew = nNew*2; - if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; - if( nNew < nMin ) nNew = nMin; - - aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); - if( !aNew ) return SQLITE_NOMEM; - pSorter->list.pList = (SorterRecord*)( - aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) - ); - pSorter->list.aMemory = aNew; - pSorter->nMemory = nNew; - } - - pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; - pSorter->iMemory += ROUND8(nReq); - pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); - }else{ - pNew = (SorterRecord *)sqlite3Malloc(nReq); - if( pNew==0 ){ - return SQLITE_NOMEM; - } - pNew->u.pNext = pSorter->list.pList; - } - - memcpy(SRVAL(pNew), pVal->z, pVal->n); - pNew->nVal = pVal->n; - pSorter->list.pList = pNew; - - return rc; -} - -/* -** Read keys from pIncr->pMerger and populate pIncr->aFile[1]. The format -** of the data stored in aFile[1] is the same as that used by regular PMAs, -** except that the number-of-bytes varint is omitted from the start. -*/ -static int vdbeIncrPopulate(IncrMerger *pIncr){ - int rc = SQLITE_OK; - int rc2; - i64 iStart = pIncr->iStartOff; - SorterFile *pOut = &pIncr->aFile[1]; - SortSubtask *pTask = pIncr->pTask; - MergeEngine *pMerger = pIncr->pMerger; - PmaWriter writer; - assert( pIncr->bEof==0 ); - - vdbeSorterPopulateDebug(pTask, "enter"); - - vdbePmaWriterInit(pOut->pFd, &writer, pTask->pSorter->pgsz, iStart); - while( rc==SQLITE_OK ){ - int dummy; - PmaReader *pReader = &pMerger->aReadr[ pMerger->aTree[1] ]; - int nKey = pReader->nKey; - i64 iEof = writer.iWriteOff + writer.iBufEnd; - - /* Check if the output file is full or if the input has been exhausted. - ** In either case exit the loop. */ - if( pReader->pFd==0 ) break; - if( (iEof + nKey + sqlite3VarintLen(nKey))>(iStart + pIncr->mxSz) ) break; - - /* Write the next key to the output. */ - vdbePmaWriteVarint(&writer, nKey); - vdbePmaWriteBlob(&writer, pReader->aKey, nKey); - assert( pIncr->pMerger->pTask==pTask ); - rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy); - } - - rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof); - if( rc==SQLITE_OK ) rc = rc2; - vdbeSorterPopulateDebug(pTask, "exit"); - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for background threads that populate aFile[1] of -** multi-threaded IncrMerger objects. -*/ -static void *vdbeIncrPopulateThread(void *pCtx){ - IncrMerger *pIncr = (IncrMerger*)pCtx; - void *pRet = SQLITE_INT_TO_PTR( vdbeIncrPopulate(pIncr) ); - pIncr->pTask->bDone = 1; - return pRet; -} - -/* -** Launch a background thread to populate aFile[1] of pIncr. -*/ -static int vdbeIncrBgPopulate(IncrMerger *pIncr){ - void *p = (void*)pIncr; - assert( pIncr->bUseThread ); - return vdbeSorterCreateThread(pIncr->pTask, vdbeIncrPopulateThread, p); -} + if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && ( + (pSorter->nInMemory>pSorter->mxPmaSize) + || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull()) + )){ +#ifdef SQLITE_DEBUG + i64 nExpect = pSorter->iWriteOff + + sqlite3VarintLen(pSorter->nInMemory) + + pSorter->nInMemory; #endif - -/* -** This function is called when the PmaReader corresponding to pIncr has -** finished reading the contents of aFile[0]. Its purpose is to "refill" -** aFile[0] such that the PmaReader should start rereading it from the -** beginning. -** -** For single-threaded objects, this is accomplished by literally reading -** keys from pIncr->pMerger and repopulating aFile[0]. -** -** For multi-threaded objects, all that is required is to wait until the -** background thread is finished (if it is not already) and then swap -** aFile[0] and aFile[1] in place. If the contents of pMerger have not -** been exhausted, this function also launches a new background thread -** to populate the new aFile[1]. -** -** SQLITE_OK is returned on success, or an SQLite error code otherwise. -*/ -static int vdbeIncrSwap(IncrMerger *pIncr){ - int rc = SQLITE_OK; - -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterJoinThread(pIncr->pTask); - - if( rc==SQLITE_OK ){ - SorterFile f0 = pIncr->aFile[0]; - pIncr->aFile[0] = pIncr->aFile[1]; - pIncr->aFile[1] = f0; - } - - if( rc==SQLITE_OK ){ - if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ - pIncr->bEof = 1; - }else{ - rc = vdbeIncrBgPopulate(pIncr); - } - } - }else -#endif - { - rc = vdbeIncrPopulate(pIncr); - pIncr->aFile[0] = pIncr->aFile[1]; - if( pIncr->aFile[0].iEof==pIncr->iStartOff ){ - pIncr->bEof = 1; - } + rc = vdbeSorterListToPMA(db, pCsr); + pSorter->nInMemory = 0; + assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) ); } return rc; } /* -** Allocate and return a new IncrMerger object to read data from pMerger. -** -** If an OOM condition is encountered, return NULL. In this case free the -** pMerger argument before returning. +** Helper function for sqlite3VdbeSorterRewind(). */ -static int vdbeIncrMergerNew( - SortSubtask *pTask, /* The thread that will be using the new IncrMerger */ - MergeEngine *pMerger, /* The MergeEngine that the IncrMerger will control */ - IncrMerger **ppOut /* Write the new IncrMerger here */ -){ - int rc = SQLITE_OK; - IncrMerger *pIncr = *ppOut = (IncrMerger*) - (sqlite3FaultSim(100) ? 0 : sqlite3MallocZero(sizeof(*pIncr))); - if( pIncr ){ - pIncr->pMerger = pMerger; - pIncr->pTask = pTask; - pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2); - pTask->file2.iEof += pIncr->mxSz; - }else{ - vdbeMergeEngineFree(pMerger); - rc = SQLITE_NOMEM; - } - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** Set the "use-threads" flag on object pIncr. -*/ -static void vdbeIncrMergerSetThreads(IncrMerger *pIncr){ - pIncr->bUseThread = 1; - pIncr->pTask->file2.iEof -= pIncr->mxSz; -} -#endif /* SQLITE_MAX_WORKER_THREADS>0 */ - - - -/* -** Recompute pMerger->aTree[iOut] by comparing the next keys on the -** two PmaReaders that feed that entry. Neither of the PmaReaders -** are advanced. This routine merely does the comparison. -*/ -static void vdbeMergeEngineCompare( - MergeEngine *pMerger, /* Merge engine containing PmaReaders to compare */ - int iOut /* Store the result in pMerger->aTree[iOut] */ -){ - int i1; - int i2; - int iRes; - PmaReader *p1; - PmaReader *p2; - - assert( iOutnTree && iOut>0 ); - - if( iOut>=(pMerger->nTree/2) ){ - i1 = (iOut - pMerger->nTree/2) * 2; - i2 = i1 + 1; - }else{ - i1 = pMerger->aTree[iOut*2]; - i2 = pMerger->aTree[iOut*2+1]; - } - - p1 = &pMerger->aReadr[i1]; - p2 = &pMerger->aReadr[i2]; - - if( p1->pFd==0 ){ - iRes = i2; - }else if( p2->pFd==0 ){ - iRes = i1; - }else{ - SortSubtask *pTask = pMerger->pTask; - int bCached = 0; - int res; - assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ - res = pTask->xCompare( - pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey - ); - if( res<=0 ){ - iRes = i1; - }else{ - iRes = i2; - } - } - - pMerger->aTree[iOut] = iRes; -} - -/* -** Allowed values for the eMode parameter to vdbeMergeEngineInit() -** and vdbePmaReaderIncrMergeInit(). -** -** Only INCRINIT_NORMAL is valid in single-threaded builds (when -** SQLITE_MAX_WORKER_THREADS==0). The other values are only used -** when there exists one or more separate worker threads. -*/ -#define INCRINIT_NORMAL 0 -#define INCRINIT_TASK 1 -#define INCRINIT_ROOT 2 - -/* -** Forward reference required as the vdbeIncrMergeInit() and -** vdbePmaReaderIncrInit() routines are called mutually recursively when -** building a merge tree. -*/ -static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); - -/* -** Initialize the MergeEngine object passed as the second argument. Once this -** function returns, the first key of merged data may be read from the -** MergeEngine object in the usual fashion. -** -** If argument eMode is INCRINIT_ROOT, then it is assumed that any IncrMerge -** objects attached to the PmaReader objects that the merger reads from have -** already been populated, but that they have not yet populated aFile[0] and -** set the PmaReader objects up to read from it. In this case all that is -** required is to call vdbePmaReaderNext() on each PmaReader to point it at -** its first key. -** -** Otherwise, if eMode is any value other than INCRINIT_ROOT, then use -** vdbePmaReaderIncrMergeInit() to initialize each PmaReader that feeds data -** to pMerger. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbeMergeEngineInit( - SortSubtask *pTask, /* Thread that will run pMerger */ - MergeEngine *pMerger, /* MergeEngine to initialize */ - int eMode /* One of the INCRINIT_XXX constants */ +static int vdbeSorterInitMerge( + sqlite3 *db, /* Database handle */ + const VdbeCursor *pCsr, /* Cursor handle for this sorter */ + i64 *pnByte /* Sum of bytes in all opened PMAs */ ){ + VdbeSorter *pSorter = pCsr->pSorter; int rc = SQLITE_OK; /* Return code */ - int i; /* For looping over PmaReader objects */ - int nTree = pMerger->nTree; + int i; /* Used to iterator through aIter[] */ + i64 nByte = 0; /* Total bytes in all opened PMAs */ - /* eMode is always INCRINIT_NORMAL in single-threaded mode */ - assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - - /* Verify that the MergeEngine is assigned to a single thread */ - assert( pMerger->pTask==0 ); - pMerger->pTask = pTask; - - for(i=0; i0 && eMode==INCRINIT_ROOT ){ - /* PmaReaders should be normally initialized in order, as if they are - ** reading from the same temp file this makes for more linear file IO. - ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is - ** in use it will block the vdbePmaReaderNext() call while it uses - ** the main thread to fill its buffer. So calling PmaReaderNext() - ** on this PmaReader before any of the multi-threaded PmaReaders takes - ** better advantage of multi-processor hardware. */ - rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]); - }else{ - rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL); - } - if( rc!=SQLITE_OK ) return rc; + /* Initialize the iterators. */ + for(i=0; iaIter[i]; + rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte); + pSorter->iReadOff = pIter->iEof; + assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff ); + if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break; } - for(i=pMerger->nTree-1; i>0; i--){ - vdbeMergeEngineCompare(pMerger, i); - } - return pTask->pUnpacked->errCode; -} - -/* -** The PmaReader passed as the first argument is guaranteed to be an -** incremental-reader (pReadr->pIncr!=0). This function serves to open -** and/or initialize the temp file related fields of the IncrMerge -** object at (pReadr->pIncr). -** -** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders -** in the sub-tree headed by pReadr are also initialized. Data is then -** loaded into the buffers belonging to pReadr and it is set to point to -** the first key in its range. -** -** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed -** to be a multi-threaded PmaReader and this function is being called in a -** background thread. In this case all PmaReaders in the sub-tree are -** initialized as for INCRINIT_NORMAL and the aFile[1] buffer belonging to -** pReadr is populated. However, pReadr itself is not set up to point -** to its first key. A call to vdbePmaReaderNext() is still required to do -** that. -** -** The reason this function does not call vdbePmaReaderNext() immediately -** in the INCRINIT_TASK case is that vdbePmaReaderNext() assumes that it has -** to block on thread (pTask->thread) before accessing aFile[1]. But, since -** this entire function is being run by thread (pTask->thread), that will -** lead to the current background thread attempting to join itself. -** -** Finally, if argument eMode is set to INCRINIT_ROOT, it may be assumed -** that pReadr->pIncr is a multi-threaded IncrMerge objects, and that all -** child-trees have already been initialized using IncrInit(INCRINIT_TASK). -** In this case vdbePmaReaderNext() is called on all child PmaReaders and -** the current PmaReader set to point to the first key in its range. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ - int rc = SQLITE_OK; - IncrMerger *pIncr = pReadr->pIncr; - SortSubtask *pTask = pIncr->pTask; - sqlite3 *db = pTask->pSorter->db; - - /* eMode is always INCRINIT_NORMAL in single-threaded mode */ - assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - - rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - - /* Set up the required files for pIncr. A multi-theaded IncrMerge object - ** requires two temp files to itself, whereas a single-threaded object - ** only requires a region of pTask->file2. */ - if( rc==SQLITE_OK ){ - int mxSz = pIncr->mxSz; -#if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); - if( rc==SQLITE_OK ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); - } - }else -#endif - /*if( !pIncr->bUseThread )*/{ - if( pTask->file2.pFd==0 ){ - assert( pTask->file2.iEof>0 ); - rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); - pTask->file2.iEof = 0; - } - if( rc==SQLITE_OK ){ - pIncr->aFile[1].pFd = pTask->file2.pFd; - pIncr->iStartOff = pTask->file2.iEof; - pTask->file2.iEof += mxSz; - } - } + /* Initialize the aTree[] array. */ + for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){ + rc = vdbeSorterDoCompare(pCsr, i); } -#if SQLITE_MAX_WORKER_THREADS>0 - if( rc==SQLITE_OK && pIncr->bUseThread ){ - /* Use the current thread to populate aFile[1], even though this - ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, - ** then this function is already running in background thread - ** pIncr->pTask->thread. - ** - ** If this is the INCRINIT_ROOT object, then it is running in the - ** main VDBE thread. But that is Ok, as that thread cannot return - ** control to the VDBE or proceed with anything useful until the - ** first results are ready from this merger object anyway. - */ - assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); - rc = vdbeIncrPopulate(pIncr); - } -#endif - - if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){ - rc = vdbePmaReaderNext(pReadr); - } - - return rc; -} - -#if SQLITE_MAX_WORKER_THREADS>0 -/* -** The main routine for vdbePmaReaderIncrMergeInit() operations run in -** background threads. -*/ -static void *vdbePmaReaderBgIncrInit(void *pCtx){ - PmaReader *pReader = (PmaReader*)pCtx; - void *pRet = SQLITE_INT_TO_PTR( - vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK) - ); - pReader->pIncr->pTask->bDone = 1; - return pRet; -} -#endif - -/* -** If the PmaReader passed as the first argument is not an incremental-reader -** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes -** the vdbePmaReaderIncrMergeInit() function with the parameters passed to -** this routine to initialize the incremental merge. -** -** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), -** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). -** Or, if the IncrMerger is single threaded, the same function is called -** using the current thread. -*/ -static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ - IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */ - int rc = SQLITE_OK; /* Return code */ - if( pIncr ){ -#if SQLITE_MAX_WORKER_THREADS>0 - assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK ); - if( pIncr->bUseThread ){ - void *pCtx = (void*)pReadr; - rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx); - }else -#endif - { - rc = vdbePmaReaderIncrMergeInit(pReadr, eMode); - } - } + *pnByte = nByte; return rc; } /* -** Allocate a new MergeEngine object to merge the contents of nPMA level-0 -** PMAs from pTask->file. If no error occurs, set *ppOut to point to -** the new object and return SQLITE_OK. Or, if an error does occur, set *ppOut -** to NULL and return an SQLite error code. -** -** When this function is called, *piOffset is set to the offset of the -** first PMA to read from pTask->file. Assuming no error occurs, it is -** set to the offset immediately following the last byte of the last -** PMA before returning. If an error does occur, then the final value of -** *piOffset is undefined. +** Once the sorter has been populated, this function is called to prepare +** for iterating through its contents in sorted order. */ -static int vdbeMergeEngineLevel0( - SortSubtask *pTask, /* Sorter task to read from */ - int nPMA, /* Number of PMAs to read */ - i64 *piOffset, /* IN/OUT: Readr offset in pTask->file */ - MergeEngine **ppOut /* OUT: New merge-engine */ -){ - MergeEngine *pNew; /* Merge engine to return */ - i64 iOff = *piOffset; - int i; - int rc = SQLITE_OK; - - *ppOut = pNew = vdbeMergeEngineNew(nPMA); - if( pNew==0 ) rc = SQLITE_NOMEM; - - for(i=0; iaReadr[i]; - rc = vdbePmaReaderInit(pTask, &pTask->file, iOff, pReadr, &nDummy); - iOff = pReadr->iEof; - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pNew); - *ppOut = 0; - } - *piOffset = iOff; - return rc; -} - -/* -** Return the depth of a tree comprising nPMA PMAs, assuming a fanout of -** SORTER_MAX_MERGE_COUNT. The returned value does not include leaf nodes. -** -** i.e. -** -** nPMA<=16 -> TreeDepth() == 0 -** nPMA<=256 -> TreeDepth() == 1 -** nPMA<=65536 -> TreeDepth() == 2 -*/ -static int vdbeSorterTreeDepth(int nPMA){ - int nDepth = 0; - i64 nDiv = SORTER_MAX_MERGE_COUNT; - while( nDiv < (i64)nPMA ){ - nDiv = nDiv * SORTER_MAX_MERGE_COUNT; - nDepth++; - } - return nDepth; -} - -/* -** pRoot is the root of an incremental merge-tree with depth nDepth (according -** to vdbeSorterTreeDepth()). pLeaf is the iSeq'th leaf to be added to the -** tree, counting from zero. This function adds pLeaf to the tree. -** -** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error -** code is returned and pLeaf is freed. -*/ -static int vdbeSorterAddToTree( - SortSubtask *pTask, /* Task context */ - int nDepth, /* Depth of tree according to TreeDepth() */ - int iSeq, /* Sequence number of leaf within tree */ - MergeEngine *pRoot, /* Root of tree */ - MergeEngine *pLeaf /* Leaf to add to tree */ -){ - int rc = SQLITE_OK; - int nDiv = 1; - int i; - MergeEngine *p = pRoot; - IncrMerger *pIncr; - - rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr); - - for(i=1; iaReadr[iIter]; - - if( pReadr->pIncr==0 ){ - MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr); - } - } - if( rc==SQLITE_OK ){ - p = pReadr->pIncr->pMerger; - nDiv = nDiv / SORTER_MAX_MERGE_COUNT; - } - } - - if( rc==SQLITE_OK ){ - p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr; - }else{ - vdbeIncrFree(pIncr); - } - return rc; -} - -/* -** This function is called as part of a SorterRewind() operation on a sorter -** that has already written two or more level-0 PMAs to one or more temp -** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that -** can be used to incrementally merge all PMAs on disk. -** -** If successful, SQLITE_OK is returned and *ppOut set to point to the -** MergeEngine object at the root of the tree before returning. Or, if an -** error occurs, an SQLite error code is returned and the final value -** of *ppOut is undefined. -*/ -static int vdbeSorterMergeTreeBuild( - VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */ - MergeEngine **ppOut /* Write the MergeEngine here */ -){ - MergeEngine *pMain = 0; - int rc = SQLITE_OK; - int iTask; - -#if SQLITE_MAX_WORKER_THREADS>0 - /* If the sorter uses more than one task, then create the top-level - ** MergeEngine here. This MergeEngine will read data from exactly - ** one PmaReader per sub-task. */ - assert( pSorter->bUseThreads || pSorter->nTask==1 ); - if( pSorter->nTask>1 ){ - pMain = vdbeMergeEngineNew(pSorter->nTask); - if( pMain==0 ) rc = SQLITE_NOMEM; - } -#endif - - for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ - SortSubtask *pTask = &pSorter->aTask[iTask]; - assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 ); - if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){ - MergeEngine *pRoot = 0; /* Root node of tree for this task */ - int nDepth = vdbeSorterTreeDepth(pTask->nPMA); - i64 iReadOff = 0; - - if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){ - rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot); - }else{ - int i; - int iSeq = 0; - pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT); - if( pRoot==0 ) rc = SQLITE_NOMEM; - for(i=0; inPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){ - MergeEngine *pMerger = 0; /* New level-0 PMA merger */ - int nReader; /* Number of level-0 PMAs to merge */ - - nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT); - rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger); - if( rc==SQLITE_OK ){ - rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger); - } - } - } - - if( rc==SQLITE_OK ){ -#if SQLITE_MAX_WORKER_THREADS>0 - if( pMain!=0 ){ - rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr); - }else -#endif - { - assert( pMain==0 ); - pMain = pRoot; - } - }else{ - vdbeMergeEngineFree(pRoot); - } - } - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pMain); - pMain = 0; - } - *ppOut = pMain; - return rc; -} - -/* -** This function is called as part of an sqlite3VdbeSorterRewind() operation -** on a sorter that has written two or more PMAs to temporary files. It sets -** up either VdbeSorter.pMerger (for single threaded sorters) or pReader -** (for multi-threaded sorters) so that it can be used to iterate through -** all records stored in the sorter. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ +SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ + VdbeSorter *pSorter = pCsr->pSorter; int rc; /* Return code */ - SortSubtask *pTask0 = &pSorter->aTask[0]; - MergeEngine *pMain = 0; -#if SQLITE_MAX_WORKER_THREADS - sqlite3 *db = pTask0->pSorter->db; - int i; - SorterCompare xCompare = vdbeSorterGetCompare(pSorter); - for(i=0; inTask; i++){ - pSorter->aTask[i].xCompare = xCompare; - } -#endif + sqlite3_file *pTemp2 = 0; /* Second temp file to use */ + i64 iWrite2 = 0; /* Write offset for pTemp2 */ + int nIter; /* Number of iterators used */ + int nByte; /* Bytes of space required for aIter/aTree */ + int N = 2; /* Power of 2 >= nIter */ - rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); - if( rc==SQLITE_OK ){ -#if SQLITE_MAX_WORKER_THREADS - assert( pSorter->bUseThreads==0 || pSorter->nTask>1 ); - if( pSorter->bUseThreads ){ - int iTask; - PmaReader *pReadr = 0; - SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1]; - rc = vdbeSortAllocUnpacked(pLast); - if( rc==SQLITE_OK ){ - pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader)); - pSorter->pReader = pReadr; - if( pReadr==0 ) rc = SQLITE_NOMEM; - } - if( rc==SQLITE_OK ){ - rc = vdbeIncrMergerNew(pLast, pMain, &pReadr->pIncr); - if( rc==SQLITE_OK ){ - vdbeIncrMergerSetThreads(pReadr->pIncr); - for(iTask=0; iTask<(pSorter->nTask-1); iTask++){ - IncrMerger *pIncr; - if( (pIncr = pMain->aReadr[iTask].pIncr) ){ - vdbeIncrMergerSetThreads(pIncr); - assert( pIncr->pTask!=pLast ); - } - } - for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ - /* Check that: - ** - ** a) The incremental merge object is configured to use the - ** right task, and - ** b) If it is using task (nTask-1), it is configured to run - ** in single-threaded mode. This is important, as the - ** root merge (INCRINIT_ROOT) will be using the same task - ** object. - */ - PmaReader *p = &pMain->aReadr[iTask]; - assert( p->pIncr==0 || ( - (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */ - && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */ - )); - rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK); - } - } - pMain = 0; - } - if( rc==SQLITE_OK ){ - rc = vdbePmaReaderIncrMergeInit(pReadr, INCRINIT_ROOT); - } - }else -#endif - { - rc = vdbeMergeEngineInit(pTask0, pMain, INCRINIT_NORMAL); - pSorter->pMerger = pMain; - pMain = 0; - } - } - - if( rc!=SQLITE_OK ){ - vdbeMergeEngineFree(pMain); - } - return rc; -} - - -/* -** Once the sorter has been populated by calls to sqlite3VdbeSorterWrite, -** this function is called to prepare for iterating through the records -** in sorted order. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ - VdbeSorter *pSorter; - int rc = SQLITE_OK; /* Return code */ - - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; assert( pSorter ); /* If no data has been written to disk, then do not do so now. Instead, ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly ** from the in-memory list. */ - if( pSorter->bUsePMA==0 ){ - if( pSorter->list.pList ){ - *pbEof = 0; - rc = vdbeSorterSort(&pSorter->aTask[0], &pSorter->list); - }else{ - *pbEof = 1; + if( pSorter->nPMA==0 ){ + *pbEof = !pSorter->pRecord; + assert( pSorter->aTree==0 ); + return vdbeSorterSort(pCsr); + } + + /* Write the current in-memory list to a PMA. */ + rc = vdbeSorterListToPMA(db, pCsr); + if( rc!=SQLITE_OK ) return rc; + + /* Allocate space for aIter[] and aTree[]. */ + nIter = pSorter->nPMA; + if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT; + assert( nIter>0 ); + while( NaIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte); + if( !pSorter->aIter ) return SQLITE_NOMEM; + pSorter->aTree = (int *)&pSorter->aIter[N]; + pSorter->nTree = N; + + do { + int iNew; /* Index of new, merged, PMA */ + + for(iNew=0; + rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNTnPMA; + iNew++ + ){ + int rc2; /* Return code from fileWriterFinish() */ + FileWriter writer; /* Object used to write to disk */ + i64 nWrite; /* Number of bytes in new PMA */ + + memset(&writer, 0, sizeof(FileWriter)); + + /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1, + ** initialize an iterator for each of them and break out of the loop. + ** These iterators will be incrementally merged as the VDBE layer calls + ** sqlite3VdbeSorterNext(). + ** + ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs, + ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs + ** are merged into a single PMA that is written to file pTemp2. + */ + rc = vdbeSorterInitMerge(db, pCsr, &nWrite); + assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile ); + if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ + break; + } + + /* Open the second temp file, if it is not already open. */ + if( pTemp2==0 ){ + assert( iWrite2==0 ); + rc = vdbeSorterOpenTempFile(db, &pTemp2); + } + + if( rc==SQLITE_OK ){ + int bEof = 0; + fileWriterInit(db, pTemp2, &writer, iWrite2); + fileWriterWriteVarint(&writer, nWrite); + while( rc==SQLITE_OK && bEof==0 ){ + VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ]; + assert( pIter->pFile ); + + fileWriterWriteVarint(&writer, pIter->nKey); + fileWriterWrite(&writer, pIter->aKey, pIter->nKey); + rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); + } + rc2 = fileWriterFinish(db, &writer, &iWrite2); + if( rc==SQLITE_OK ) rc = rc2; + } } - return rc; + + if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ + break; + }else{ + sqlite3_file *pTmp = pSorter->pTemp1; + pSorter->nPMA = iNew; + pSorter->pTemp1 = pTemp2; + pTemp2 = pTmp; + pSorter->iWriteOff = iWrite2; + pSorter->iReadOff = 0; + iWrite2 = 0; + } + }while( rc==SQLITE_OK ); + + if( pTemp2 ){ + sqlite3OsCloseFree(pTemp2); } - - /* Write the current in-memory list to a PMA. When the VdbeSorterWrite() - ** function flushes the contents of memory to disk, it immediately always - ** creates a new list consisting of a single key immediately afterwards. - ** So the list is never empty at this point. */ - assert( pSorter->list.pList ); - rc = vdbeSorterFlushPMA(pSorter); - - /* Join all threads */ - rc = vdbeSorterJoinAll(pSorter, rc); - - vdbeSorterRewindDebug("rewind"); - - /* Assuming no errors have occurred, set up a merger structure to - ** incrementally read and merge all remaining PMAs. */ - assert( pSorter->pReader==0 ); - if( rc==SQLITE_OK ){ - rc = vdbeSorterSetupMerge(pSorter); - *pbEof = 0; - } - - vdbeSorterRewindDebug("rewinddone"); + *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); return rc; } @@ -83583,33 +75342,66 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ ** Advance to the next element in the sorter. */ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ - VdbeSorter *pSorter; + VdbeSorter *pSorter = pCsr->pSorter; int rc; /* Return code */ - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) ); - if( pSorter->bUsePMA ){ - assert( pSorter->pReader==0 || pSorter->pMerger==0 ); - assert( pSorter->bUseThreads==0 || pSorter->pReader ); - assert( pSorter->bUseThreads==1 || pSorter->pMerger ); -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->bUseThreads ){ - rc = vdbePmaReaderNext(pSorter->pReader); - *pbEof = (pSorter->pReader->pFd==0); - }else -#endif - /*if( !pSorter->bUseThreads )*/ { - assert( pSorter->pMerger!=0 ); - assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) ); - rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof); + if( pSorter->aTree ){ + int iPrev = pSorter->aTree[1];/* Index of iterator to advance */ + rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]); + if( rc==SQLITE_OK ){ + int i; /* Index of aTree[] to recalculate */ + VdbeSorterIter *pIter1; /* First iterator to compare */ + VdbeSorterIter *pIter2; /* Second iterator to compare */ + u8 *pKey2; /* To pIter2->aKey, or 0 if record cached */ + + /* Find the first two iterators to compare. The one that was just + ** advanced (iPrev) and the one next to it in the array. */ + pIter1 = &pSorter->aIter[(iPrev & 0xFFFE)]; + pIter2 = &pSorter->aIter[(iPrev | 0x0001)]; + pKey2 = pIter2->aKey; + + for(i=(pSorter->nTree+iPrev)/2; i>0; i=i/2){ + /* Compare pIter1 and pIter2. Store the result in variable iRes. */ + int iRes; + if( pIter1->pFile==0 ){ + iRes = +1; + }else if( pIter2->pFile==0 ){ + iRes = -1; + }else{ + vdbeSorterCompare(pCsr, 0, + pIter1->aKey, pIter1->nKey, pKey2, pIter2->nKey, &iRes + ); + } + + /* If pIter1 contained the smaller value, set aTree[i] to its index. + ** Then set pIter2 to the next iterator to compare to pIter1. In this + ** case there is no cache of pIter2 in pSorter->pUnpacked, so set + ** pKey2 to point to the record belonging to pIter2. + ** + ** Alternatively, if pIter2 contains the smaller of the two values, + ** set aTree[i] to its index and update pIter1. If vdbeSorterCompare() + ** was actually called above, then pSorter->pUnpacked now contains + ** a value equivalent to pIter2. So set pKey2 to NULL to prevent + ** vdbeSorterCompare() from decoding pIter2 again. */ + if( iRes<=0 ){ + pSorter->aTree[i] = (int)(pIter1 - pSorter->aIter); + pIter2 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ]; + pKey2 = pIter2->aKey; + }else{ + if( pIter1->pFile ) pKey2 = 0; + pSorter->aTree[i] = (int)(pIter2 - pSorter->aIter); + pIter1 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ]; + } + + } + *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); } }else{ - SorterRecord *pFree = pSorter->list.pList; - pSorter->list.pList = pFree->u.pNext; - pFree->u.pNext = 0; - if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree); - *pbEof = !pSorter->list.pList; + SorterRecord *pFree = pSorter->pRecord; + pSorter->pRecord = pFree->pNext; + pFree->pNext = 0; + vdbeSorterRecordFree(db, pFree); + *pbEof = !pSorter->pRecord; rc = SQLITE_OK; } return rc; @@ -83624,21 +75416,14 @@ static void *vdbeSorterRowkey( int *pnKey /* OUT: Size of current key in bytes */ ){ void *pKey; - if( pSorter->bUsePMA ){ - PmaReader *pReader; -#if SQLITE_MAX_WORKER_THREADS>0 - if( pSorter->bUseThreads ){ - pReader = pSorter->pReader; - }else -#endif - /*if( !pSorter->bUseThreads )*/{ - pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]]; - } - *pnKey = pReader->nKey; - pKey = pReader->aKey; + if( pSorter->aTree ){ + VdbeSorterIter *pIter; + pIter = &pSorter->aIter[ pSorter->aTree[1] ]; + *pnKey = pIter->nKey; + pKey = pIter->aKey; }else{ - *pnKey = pSorter->list.pList->nVal; - pKey = SRVAL(pSorter->list.pList); + *pnKey = pSorter->pRecord->nVal; + pKey = pSorter->pRecord->pVal; } return pKey; } @@ -83647,13 +75432,11 @@ static void *vdbeSorterRowkey( ** Copy the current sorter key into the memory cell pOut. */ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ - VdbeSorter *pSorter; + VdbeSorter *pSorter = pCsr->pSorter; void *pKey; int nKey; /* Sorter key to copy into pOut */ - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; pKey = vdbeSorterRowkey(pSorter, &nKey); - if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){ + if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){ return SQLITE_NOMEM; } pOut->n = nKey; @@ -83668,52 +75451,22 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ ** passed as the first argument currently points to. For the purposes of ** the comparison, ignore the rowid field at the end of each record. ** -** If the sorter cursor key contains any NULL values, consider it to be -** less than pVal. Even if pVal also contains NULL values. -** ** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). ** Otherwise, set *pRes to a negative, zero or positive value if the ** key in pVal is smaller than, equal to or larger than the current sorter ** key. -** -** This routine forms the core of the OP_SorterCompare opcode, which in -** turn is used to verify uniqueness when constructing a UNIQUE INDEX. */ SQLITE_PRIVATE int sqlite3VdbeSorterCompare( const VdbeCursor *pCsr, /* Sorter cursor */ Mem *pVal, /* Value to compare to current sorter key */ - int nKeyCol, /* Compare this many columns */ + int nIgnore, /* Ignore this many fields at the end */ int *pRes /* OUT: Result of comparison */ ){ - VdbeSorter *pSorter; - UnpackedRecord *r2; - KeyInfo *pKeyInfo; - int i; + VdbeSorter *pSorter = pCsr->pSorter; void *pKey; int nKey; /* Sorter key to compare pVal with */ - assert( pCsr->eCurType==CURTYPE_SORTER ); - pSorter = pCsr->uc.pSorter; - r2 = pSorter->pUnpacked; - pKeyInfo = pCsr->pKeyInfo; - if( r2==0 ){ - char *p; - r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p); - assert( pSorter->pUnpacked==(UnpackedRecord*)p ); - if( r2==0 ) return SQLITE_NOMEM; - r2->nField = nKeyCol; - } - assert( r2->nField==nKeyCol ); - pKey = vdbeSorterRowkey(pSorter, &nKey); - sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2); - for(i=0; iaMem[i].flags & MEM_Null ){ - *pRes = -1; - return SQLITE_OK; - } - } - - *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2); + vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes); return SQLITE_OK; } @@ -83746,7 +75499,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare( ** 2) The sqlite3JournalCreate() function is called. */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE -/* #include "sqliteInt.h" */ /* @@ -83994,7 +75746,6 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ ** The in-memory rollback journal is used to journal transactions for ** ":memory:" databases and when the journal_mode=MEMORY pragma is used. */ -/* #include "sqliteInt.h" */ /* Forward references to internal structures */ typedef struct MemJournal MemJournal; @@ -84006,7 +75757,7 @@ typedef struct FileChunk FileChunk; ** ** The size chosen is a little less than a power of two. That way, ** the FileChunk object will have a size that almost exactly fills -** a power-of-two allocation. This minimizes wasted space in power-of-two +** a power-of-two allocation. This mimimizes wasted space in power-of-two ** memory allocators. */ #define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*))) @@ -84250,14 +76001,13 @@ SQLITE_PRIVATE int sqlite3MemJournalSize(void){ ** This file contains routines used for walking the parser tree for ** an SQL statement. */ -/* #include "sqliteInt.h" */ /* #include */ /* #include */ /* ** Walk an expression tree. Invoke the callback once for each node -** of the expression, while descending. (In other words, the callback +** of the expression, while decending. (In other words, the callback ** is invoked before visiting children.) ** ** The return value from the callback should be one of the WRC_* @@ -84343,11 +76093,6 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ return WRC_Abort; } - if( pItem->fg.isTabFunc - && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } } } return WRC_Continue; @@ -84414,7 +76159,6 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ ** resolve all identifiers by associating them with a particular ** table and column. */ -/* #include "sqliteInt.h" */ /* #include */ /* #include */ @@ -84428,7 +76172,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ ** is a helper function - a callback for the tree walker. */ static int incrAggDepth(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n; + if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i; return WRC_Continue; } static void incrAggFunctionDepth(Expr *pExpr, int N){ @@ -84436,7 +76180,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = incrAggDepth; - w.u.n = N; + w.u.i = N; sqlite3WalkExpr(&w, pExpr); } } @@ -84445,6 +76189,30 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** Turn the pExpr expression into an alias for the iCol-th column of the ** result set in pEList. ** +** If the result set column is a simple column reference, then this routine +** makes an exact copy. But for any other kind of expression, this +** routine make a copy of the result set column as the argument to the +** TK_AS operator. The TK_AS operator causes the expression to be +** evaluated just once and then reused for each alias. +** +** The reason for suppressing the TK_AS term when the expression is a simple +** column reference is so that the column reference will be recognized as +** usable by indices within the WHERE clause processing logic. +** +** The TK_AS operator is inhibited if zType[0]=='G'. This means +** that in a GROUP BY clause, the expression is evaluated twice. Hence: +** +** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x +** +** Is equivalent to: +** +** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 +** +** The result of random()%5 in the GROUP BY clause is probably different +** from the result in the result-set. On the other hand Standard SQL does +** not allow the GROUP BY clause to contain references to result-set columns. +** So this should never come up in well-formed queries. +** ** If the reference is followed by a COLLATE operator, then make sure ** the COLLATE operator is preserved. For example: ** @@ -84455,7 +76223,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; ** ** The nSubquery parameter specifies how many levels of subquery the -** alias is removed from the original expression. The usual value is +** alias is removed from the original expression. The usually value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. @@ -84475,14 +76243,23 @@ static void resolveAlias( assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); + assert( pOrig->flags & EP_Resolved ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup==0 ) return; - if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); + if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ + incrAggFunctionDepth(pDup, nSubquery); + pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); + if( pDup==0 ) return; + ExprSetProperty(pDup, EP_Skip); + if( pEList->a[iCol].u.x.iAlias==0 ){ + pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias); + } + pDup->iTable = pEList->a[iCol].u.x.iAlias; + } if( pExpr->op==TK_COLLATE ){ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); } - ExprSetProperty(pDup, EP_Alias); /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, @@ -84614,10 +76391,9 @@ static int lookupName( testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IsCheck ); if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ - /* Silently ignore database qualifiers inside CHECK constraints and - ** partial indices. Do not raise errors because that might break - ** legacy and because it does not hurt anything to just ignore the - ** database name. */ + /* Silently ignore database qualifiers inside CHECK constraints and partial + ** indices. Do not raise errors because that might break legacy and + ** because it does not hurt anything to just ignore the database name. */ zDb = 0; }else{ for(i=0; inDb; i++){ @@ -84674,7 +76450,7 @@ static int lookupName( ** USING clause, then skip this match. */ if( cnt==1 ){ - if( pItem->fg.jointype & JT_NATURAL ) continue; + if( pItem->jointype & JT_NATURAL ) continue; if( nameInUsingClause(pItem->pUsing, zCol) ) continue; } cnt++; @@ -84688,11 +76464,6 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; - /* RIGHT JOIN not (yet) supported */ - assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); - if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ - ExprSetProperty(pExpr, EP_CanBeNull); - } pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ @@ -84726,8 +76497,9 @@ static int lookupName( break; } } - if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ - /* IMP: R-51414-32910 */ + if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){ + /* IMP: R-24309-18625 */ + /* IMP: R-44911-55124 */ iCol = -1; } if( iColnCol ){ @@ -84754,15 +76526,10 @@ static int lookupName( /* ** Perhaps the name is a reference to the ROWID */ - if( cnt==0 - && cntTab==1 - && pMatch - && (pNC->ncFlags & NC_IdxExpr)==0 - && sqlite3IsRowid(zCol) - && VisibleRowid(pMatch->pTab) - ){ + if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol) + && HasRowid(pMatch->pTab) ){ cnt = 1; - pExpr->iColumn = -1; + pExpr->iColumn = -1; /* IMP: R-44911-55124 */ pExpr->affinity = SQLITE_AFF_INTEGER; } @@ -84779,9 +76546,9 @@ static int lookupName( ** resolved by the time the WHERE clause is resolved. ** ** The ability to use an output result-set column in the WHERE, GROUP BY, - ** or HAVING clauses, or as part of a larger expression in the ORDER BY + ** or HAVING clauses, or as part of a larger expression in the ORDRE BY ** clause is not standard SQL. This is a (goofy) SQLite extension, that - ** is supported for backwards compatibility only. Hence, we issue a warning + ** is supported for backwards compatibility only. TO DO: Issue a warning ** on sqlite3_log() whenever the capability is used. */ if( (pEList = pNC->pEList)!=0 @@ -84878,7 +76645,7 @@ static int lookupName( lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); - if( !ExprHasProperty(pExpr, EP_Alias) ){ + if( pExpr->op!=TK_AS ){ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); } /* Increment the nRef value on all name contexts from TopNC up to @@ -84919,26 +76686,37 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr } /* -** Report an error that an expression is not valid for some set of -** pNC->ncFlags values determined by validMask. +** Report an error that an expression is not valid for a partial index WHERE +** clause. */ -static void notValid( +static void notValidPartIdxWhere( Parse *pParse, /* Leave error message here */ NameContext *pNC, /* The name context */ - const char *zMsg, /* Type of error */ - int validMask /* Set of contexts for which prohibited */ + const char *zMsg /* Type of error */ ){ - assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 ); - if( (pNC->ncFlags & validMask)!=0 ){ - const char *zIn = "partial index WHERE clauses"; - if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; -#ifndef SQLITE_OMIT_CHECK - else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints"; -#endif - sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); + if( (pNC->ncFlags & NC_PartIdx)!=0 ){ + sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses", + zMsg); } } +#ifndef SQLITE_OMIT_CHECK +/* +** Report an error that an expression is not valid for a CHECK constraint. +*/ +static void notValidCheckConstraint( + Parse *pParse, /* Leave error message here */ + NameContext *pNC, /* The name context */ + const char *zMsg /* Type of error */ +){ + if( (pNC->ncFlags & NC_IsCheck)!=0 ){ + sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg); + } +} +#else +# define notValidCheckConstraint(P,N,M) +#endif + /* ** Expression p should encode a floating point value between 1.0 and 0.0. ** Return 1024 times this value. Or return -1 if p is not a floating point @@ -84950,7 +76728,7 @@ static int exprProbability(Expr *p){ sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); assert( r>=0.0 ); if( r>1.0 ) return -1; - return (int)(r*134217728.0); + return (int)(r*1000.0); } /* @@ -85003,8 +76781,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->affinity = SQLITE_AFF_INTEGER; break; } -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) - && !defined(SQLITE_OMIT_SUBQUERY) */ +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ /* A lone identifier is the name of a column. */ @@ -85022,8 +76799,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ Expr *pRight; /* if( pSrcList==0 ) break; */ - notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); - /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; @@ -85053,7 +76828,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - notValid(pParse, pNC, "functions", NC_PartIdx); + notValidPartIdxWhere(pParse, pNC, "functions"); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); @@ -85071,25 +76846,21 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, - "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ - /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is - ** equivalent to likelihood(X, 0.0625). - ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is - ** short-hand for likelihood(X,0.0625). - ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand - ** for likelihood(X,0.9375). - ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent - ** to likelihood(X,0.9375). */ - /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ - pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to + ** likelihood(X, 0.0625). + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for + ** likelihood(X,0.0625). */ + pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ } } + } #ifndef SQLITE_OMIT_AUTHORIZATION + if( pDef ){ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); if( auth!=SQLITE_OK ){ if( auth==SQLITE_DENY ){ @@ -85100,20 +76871,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->op = TK_NULL; return WRC_Prune; } -#endif - if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){ - /* For the purposes of the EP_ConstFunc flag, date and time - ** functions and other functions that change slowly are considered - ** constant because they are constant for the duration of one query */ - ExprSetProperty(pExpr,EP_ConstFunc); - } - if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ - /* Date/time functions that use 'now', and other functions like - ** sqlite_version() that might change over time cannot be used - ** in an index. */ - notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr); - } + if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant); } +#endif if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; @@ -85136,13 +76896,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->op2++; pNC2 = pNC2->pNext; } - assert( pDef!=0 ); - if( pNC2 ){ - assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); - testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); - pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); - - } + if( pNC2 ) pNC2->ncFlags |= NC_HasAgg; pNC->ncFlags |= NC_AllowAgg; } /* FIX ME: Compute pExpr->affinity based on the expected return @@ -85158,7 +76912,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_IN ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ int nRef = pNC->nRef; - notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr); + notValidCheckConstraint(pParse, pNC, "subqueries"); + notValidPartIdxWhere(pParse, pNC, "subqueries"); sqlite3WalkSelect(pWalker, pExpr->x.pSelect); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ @@ -85168,7 +76923,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ break; } case TK_VARIABLE: { - notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); + notValidCheckConstraint(pParse, pNC, "parameters"); + notValidPartIdxWhere(pParse, pNC, "parameters"); break; } } @@ -85362,11 +77118,9 @@ static int resolveCompoundOrderBy( if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ - Expr *pParent = pItem->pExpr; - assert( pParent->op==TK_COLLATE ); - while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; - assert( pParent->pLeft==pE ); - pParent->pLeft = pNew; + assert( pItem->pExpr->op==TK_COLLATE ); + assert( pItem->pExpr->pLeft==pE ); + pItem->pExpr->pLeft = pNew; } sqlite3ExprDelete(db, pE); pItem->u.x.iOrderByCol = (u16)iCol; @@ -85423,8 +77177,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, - zType,0); + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0); } } return 0; @@ -85504,7 +77257,7 @@ static int resolveOrderGroupBy( } /* -** Resolve names in the SELECT statement p and all of its descendants. +** Resolve names in the SELECT statement p and all of its descendents. */ static int resolveSelectStep(Walker *pWalker, Select *p){ NameContext *pOuterNC; /* Context that contains this SELECT */ @@ -85512,6 +77265,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ int isCompound; /* True if p is a compound select */ int nCompound; /* Number of compound terms processed so far */ Parse *pParse; /* Parsing context */ + ExprList *pEList; /* Result set expression list */ int i; /* Loop counter */ ExprList *pGroupBy; /* The GROUP BY clause */ Select *pLeftmost; /* Left-most of SELECT of a compound */ @@ -85556,20 +77310,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } - - /* If the SF_Converted flags is set, then this Select object was - ** was created by the convertCompoundSelectToSubquery() function. - ** In this case the ORDER BY clause (p->pOrderBy) should be resolved - ** as if it were part of the sub-query, not the parent. This block - ** moves the pOrderBy down to the sub-query. It will be moved back - ** after the names have been resolved. */ - if( p->selFlags & SF_Converted ){ - Select *pSub = p->pSrc->a[0].pSelect; - assert( p->pSrc->nSrc==1 && p->pOrderBy ); - assert( pSub->pPrior && pSub->pOrderBy==0 ); - pSub->pOrderBy = p->pOrderBy; - p->pOrderBy = 0; - } /* Recursively resolve names in all subqueries */ @@ -85584,7 +77324,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ ** parent contexts. After resolving references to expressions in ** pItem->pSelect, check if this value has changed. If so, then ** SELECT statement pItem->pSelect must be correlated. Set the - ** pItem->fg.isCorrelated flag if this is the case. */ + ** pItem->isCorrelated flag if this is the case. */ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef; if( pItem->zName ) pParse->zAuthContext = pItem->zName; @@ -85593,8 +77333,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ if( pParse->nErr || db->mallocFailed ) return WRC_Abort; for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; - assert( pItem->fg.isCorrelated==0 && nRef<=0 ); - pItem->fg.isCorrelated = (nRef!=0); + assert( pItem->isCorrelated==0 && nRef<=0 ); + pItem->isCorrelated = (nRef!=0); } } @@ -85606,7 +77346,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sNC.pNext = pOuterNC; /* Resolve names in the result set. */ - if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; + pEList = p->pEList; + assert( pEList!=0 ); + for(i=0; inExpr; i++){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ResolveExprNames(&sNC, pX) ){ + return WRC_Abort; + } + } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. @@ -85614,8 +77361,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ - assert( NC_MinMaxAgg==SF_MinMaxAgg ); - p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg); + p->selFlags |= SF_Aggregate; }else{ sNC.ncFlags &= ~NC_AllowAgg; } @@ -85639,46 +77385,18 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; - /* Resolve names in table-valued-function arguments */ - for(i=0; ipSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - if( pItem->fg.isTabFunc - && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) - ){ - return WRC_Abort; - } - } - /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg; - /* If this is a converted compound query, move the ORDER BY clause from - ** the sub-query back to the parent query. At this point each term - ** within the ORDER BY clause has been transformed to an integer value. - ** These integers will be replaced by copies of the corresponding result - ** set expressions by the call to resolveOrderGroupBy() below. */ - if( p->selFlags & SF_Converted ){ - Select *pSub = p->pSrc->a[0].pSelect; - p->pOrderBy = pSub->pOrderBy; - pSub->pOrderBy = 0; - } - /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled ** below, after all of the result-sets for all of the elements of ** the compound have been resolved. - ** - ** If there is an ORDER BY clause on a term of a compound-select other - ** than the right-most term, then that is a syntax error. But the error - ** is not detected until much later, and so we need to go ahead and - ** resolve those symbols on the incorrect ORDER BY for consistency. */ - if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ - && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") - ){ + if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ return WRC_Abort; } if( db->mallocFailed ){ @@ -85703,13 +77421,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } } - /* If this is part of a compound SELECT, check that it has the right - ** number of expressions in the select list. */ - if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){ - sqlite3SelectWrongNumTermsError(pParse, p->pNext); - return WRC_Abort; - } - /* Advance to the next term of the compound */ p = p->pPrior; @@ -85778,7 +77489,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ - u16 savedHasAgg; + u8 savedHasAgg; Walker w; if( pExpr==0 ) return 0; @@ -85791,8 +77502,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( pParse->nHeight += pExpr->nHeight; } #endif - savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg); + savedHasAgg = pNC->ncFlags & NC_HasAgg; + pNC->ncFlags &= ~NC_HasAgg; memset(&w, 0, sizeof(w)); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; @@ -85807,28 +77518,12 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( } if( pNC->ncFlags & NC_HasAgg ){ ExprSetProperty(pExpr, EP_Agg); + }else if( savedHasAgg ){ + pNC->ncFlags |= NC_HasAgg; } - pNC->ncFlags |= savedHasAgg; return ExprHasProperty(pExpr, EP_Error); } -/* -** 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. -*/ -SQLITE_PRIVATE int sqlite3ResolveExprListNames( - NameContext *pNC, /* Namespace to resolve expressions in. */ - ExprList *pList /* The expression list to be analyzed. */ -){ - int i; - if( pList ){ - for(i=0; inExpr; i++){ - if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort; - } - } - return WRC_Continue; -} /* ** Resolve all names in all expressions of a SELECT and in all @@ -85872,14 +77567,15 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames( SQLITE_PRIVATE void sqlite3ResolveSelfReference( Parse *pParse, /* Parsing context */ Table *pTab, /* The table being referenced */ - int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ + int type, /* NC_IsCheck or NC_PartIdx */ Expr *pExpr, /* Expression to resolve. May be NULL. */ ExprList *pList /* Expression list to resolve. May be NUL. */ ){ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ + int i; /* Loop counter */ - assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr ); + assert( type==NC_IsCheck || type==NC_PartIdx ); memset(&sNC, 0, sizeof(sNC)); memset(&sSrc, 0, sizeof(sSrc)); sSrc.nSrc = 1; @@ -85890,7 +77586,13 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( sNC.pSrcList = &sSrc; sNC.ncFlags = type; if( sqlite3ResolveExprNames(&sNC, pExpr) ) return; - if( pList ) sqlite3ResolveExprListNames(&sNC, pList); + if( pList ){ + for(i=0; inExpr; i++){ + if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ + return; + } + } + } } /************** End of resolve.c *********************************************/ @@ -85909,7 +77611,6 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. */ -/* #include "sqliteInt.h" */ /* ** Return the 'affinity' of the expression pExpr if any. @@ -85919,7 +77620,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( ** affinity of that column is returned. Otherwise, 0x00 is returned, ** indicating no affinity for the expression. ** -** i.e. the WHERE clause expressions in the following statements all +** i.e. the WHERE clause expresssions in the following statements all ** have an affinity: ** ** CREATE TABLE t1(a); @@ -85930,7 +77631,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelfReference( SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ int op; pExpr = sqlite3ExprSkipCollate(pExpr); - if( pExpr->flags & EP_Generic ) return 0; + if( pExpr->flags & EP_Generic ) return SQLITE_AFF_NONE; op = pExpr->op; if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); @@ -85966,11 +77667,10 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken( Parse *pParse, /* Parsing context */ Expr *pExpr, /* Add the "COLLATE" clause to this expression */ - const Token *pCollName, /* Name of collating sequence */ - int dequote /* True to dequote pCollName */ + const Token *pCollName /* Name of collating sequence */ ){ if( pCollName->n>0 ){ - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); if( pNew ){ pNew->pLeft = pExpr; pNew->flags |= EP_Collate|EP_Skip; @@ -85984,11 +77684,11 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con assert( zC!=0 ); s.z = zC; s.n = sqlite3Strlen30(s.z); - return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); + return sqlite3ExprAddCollateToken(pParse, pExpr, &s); } /* -** Skip over any TK_COLLATE operators and any unlikely() +** Skip over any TK_COLLATE or TK_AS operators and any unlikely() ** or likelihood() function at the root of an expression. */ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ @@ -85999,7 +77699,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; }else{ - assert( pExpr->op==TK_COLLATE ); + assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ); pExpr = pExpr->pLeft; } } @@ -86030,9 +77730,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); break; } - if( (op==TK_AGG_COLUMN || op==TK_COLUMN + if( p->pTab!=0 + && (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) - && p->pTab!=0 ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ @@ -86044,25 +77744,10 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } if( p->flags & EP_Collate ){ - if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ + if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - Expr *pNext = p->pRight; - /* The Expr.x union is never used at the same time as Expr.pRight */ - assert( p->x.pList==0 || p->pRight==0 ); - /* p->flags holds EP_Collate and p->pLeft->flags does not. And - ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at - ** least one EP_Collate. Thus the following two ALWAYS. */ - if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ - int i; - for(i=0; ALWAYS(ix.pList->nExpr); i++){ - if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ - pNext = p->x.pList->a[i].pExpr; - break; - } - } - } - p = pNext; + p = p->pRight; } }else{ break; @@ -86088,13 +77773,13 @@ SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){ if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ return SQLITE_AFF_NUMERIC; }else{ - return SQLITE_AFF_BLOB; + return SQLITE_AFF_NONE; } }else if( !aff1 && !aff2 ){ /* Neither side of the comparison is a column. Compare the ** results directly. */ - return SQLITE_AFF_BLOB; + return SQLITE_AFF_NONE; }else{ /* One side is a column, the other is not. Use the columns affinity. */ assert( aff1==0 || aff2==0 ); @@ -86118,7 +77803,7 @@ static char comparisonAffinity(Expr *pExpr){ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); }else if( !aff ){ - aff = SQLITE_AFF_BLOB; + aff = SQLITE_AFF_NONE; } return aff; } @@ -86132,7 +77817,7 @@ static char comparisonAffinity(Expr *pExpr){ SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); switch( aff ){ - case SQLITE_AFF_BLOB: + case SQLITE_AFF_NONE: return 1; case SQLITE_AFF_TEXT: return idx_affinity==SQLITE_AFF_TEXT; @@ -86268,9 +77953,6 @@ static void heightOfSelect(Select *p, int *pnHeight){ ** Expr.pSelect member has a height of 1. Any other expression ** has a height equal to the maximum height of any other ** referenced Expr plus one. -** -** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, -** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; @@ -86278,9 +77960,8 @@ static void exprSetHeight(Expr *p){ heightOfExpr(p->pRight, &nHeight); if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); - }else if( p->x.pList ){ + }else{ heightOfExprList(p->x.pList, &nHeight); - p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } p->nHeight = nHeight + 1; } @@ -86289,12 +77970,8 @@ static void exprSetHeight(Expr *p){ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. -** -** Also propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. */ -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( pParse->nErr ) return; +SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -86308,17 +77985,8 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ -/* -** Propagate all EP_Propagate flags from the Expr.x.pList into -** Expr.flags. -*/ -SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ - if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ - p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); - } -} -#define exprSetHeight(y) +#else + #define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* @@ -86330,7 +77998,7 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ ** is responsible for making sure the node eventually gets freed. ** ** If dequote is true, then the token (if it exists) is dequoted. -** If dequote is false, no dequoting is performed. The deQuote +** If dequote is false, no dequoting is performance. The deQuote ** parameter is ignored if pToken is NULL or if the token does not ** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** then the EP_DblQuoted flag is set on the expression node. @@ -86420,18 +78088,18 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( }else{ if( pRight ){ pRoot->pRight = pRight; - pRoot->flags |= EP_Propagate & pRight->flags; + pRoot->flags |= EP_Collate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; - pRoot->flags |= EP_Propagate & pLeft->flags; + pRoot->flags |= EP_Collate & pLeft->flags; } exprSetHeight(pRoot); } } /* -** Allocate an Expr node which joins as many as two subtrees. +** Allocate a Expr node which joins as many as two subtrees. ** ** One or both of the subtrees can be NULL. Return a pointer to the new ** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed, @@ -86445,11 +78113,11 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( const Token *pToken /* Argument token */ ){ Expr *p; - if( op==TK_AND && pParse->nErr==0 ){ + if( op==TK_AND && pLeft && pRight ){ /* Take advantage of short-circuit false optimization for AND */ p = sqlite3ExprAnd(pParse->db, pLeft, pRight); }else{ - p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1); + p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); } if( p ) { @@ -86524,7 +78192,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * } pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeightAndFlags(pParse, pNew); + sqlite3ExprSetHeight(pParse, pNew); return pNew; } @@ -86541,7 +78209,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token * ** ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number ** as the previous instance of the same wildcard. Or if this is the first -** instance of the wildcard, the next sequential variable number is +** instance of the wildcard, the next sequenial variable number is ** assigned. */ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ @@ -86676,7 +78344,7 @@ static int exprStructSize(Expr *p){ ** During expression analysis, extra information is computed and moved into ** later parts of teh Expr object and that extra information might get chopped ** off if the expression is reduced. Note also that it does not work to -** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal +** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal ** to reduce a pristine expression tree from the parser. The implementation ** of dupedExprStructSize() contain multiple assert() statements that attempt ** to enforce this constraint. @@ -86745,12 +78413,11 @@ static int dupedExprSize(Expr *p, int flags){ ** 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 +** if any. Before returning, *pzBuffer is set to the first byte passed the ** portion of the buffer copied into by this function. */ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ Expr *pNew = 0; /* Value to return */ - assert( flags==0 || flags==EXPRDUP_REDUCE ); if( p ){ const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; @@ -86785,11 +78452,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); }else{ - u32 nSize = (u32)exprStructSize(p); + int nSize = exprStructSize(p); memcpy(zAlloc, p, nSize); - if( nSizezDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); - pNewItem->fg = pOldItem->fg; + pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; - if( pNewItem->fg.isIndexedBy ){ - pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); - } - pNewItem->pIBIndex = pOldItem->pIBIndex; - if( pNewItem->fg.isTabFunc ){ - pNewItem->u1.pFuncArg = - sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); - } + pNewItem->isCorrelated = pOldItem->isCorrelated; + pNewItem->viaCoroutine = pOldItem->viaCoroutine; + pNewItem->isRecursive = pOldItem->isRecursive; + pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); + pNewItem->notIndexed = pOldItem->notIndexed; + pNewItem->pIndex = pOldItem->pIndex; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; @@ -87005,7 +78667,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = withDup(db, p->pWith); - sqlite3SelectSetName(pNew, p->zSelName); return pNew; } #else @@ -87061,20 +78722,6 @@ no_mem: return 0; } -/* -** Set the sort order for the last element on the given ExprList. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ - if( p==0 ) return; - assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 ); - assert( p->nExpr>0 ); - if( iSortOrder<0 ){ - assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC ); - return; - } - p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; -} - /* ** Set the ExprList.a[].zName element of the most recently added item ** on the expression list. @@ -87160,67 +78807,37 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ } /* -** Return the bitwise-OR of all Expr.flags fields in the given -** ExprList. -*/ -SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ - int i; - u32 m = 0; - if( pList ){ - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - if( ALWAYS(pExpr) ) m |= pExpr->flags; - } - } - return m; -} - -/* -** These routines are Walker callbacks used to check expressions to -** see if they are "constant" for some definition of constant. The -** Walker.eCode value determines the type of "constant" we are looking -** for. +** These routines are Walker callbacks. Walker.u.pi is a pointer +** to an integer. These routines are checking an expression to see +** if it is a constant. Set *Walker.u.pi to 0 if the expression is +** not constant. ** ** These callback routines are used to implement the following: ** -** sqlite3ExprIsConstant() pWalker->eCode==1 -** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2 -** sqlite3ExprIsTableConstant() pWalker->eCode==3 -** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5 +** sqlite3ExprIsConstant() +** sqlite3ExprIsConstantNotJoin() +** sqlite3ExprIsConstantOrFunction() ** -** In all cases, the callbacks set Walker.eCode=0 and abort if the expression -** is found to not be a constant. -** -** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions -** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing -** an existing schema and 4 when processing a new statement. A bound -** parameter raises an error for new statements, but is silently converted -** to NULL for existing schemas. This allows sqlite_master tables that -** contain a bound parameter because they were generated by older versions -** of SQLite to be parsed by newer versions of SQLite without raising a -** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ - /* If pWalker->eCode is 2 then any term of the expression that comes from - ** the ON or USING clauses of a left join disqualifies the expression + /* If pWalker->u.i is 3 then any term of the expression that comes from + ** the ON or USING clauses of a join disqualifies the expression ** from being considered constant. */ - if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ - pWalker->eCode = 0; + if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){ + pWalker->u.i = 0; return WRC_Abort; } switch( pExpr->op ){ /* Consider functions to be constant if all their arguments are constant - ** and either pWalker->eCode==4 or 5 or the function has the - ** SQLITE_FUNC_CONST flag. */ + ** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST + ** flag. */ case TK_FUNCTION: - if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ + if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){ return WRC_Continue; - }else{ - pWalker->eCode = 0; - return WRC_Abort; } + /* Fall through */ case TK_ID: case TK_COLUMN: case TK_AGG_FUNCTION: @@ -87229,25 +78846,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); testcase( pExpr->op==TK_AGG_COLUMN ); - if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ - return WRC_Continue; - }else{ - pWalker->eCode = 0; - return WRC_Abort; - } - case TK_VARIABLE: - if( pWalker->eCode==5 ){ - /* Silently convert bound parameters that appear inside of CREATE - ** statements into a NULL when parsing the CREATE statement text out - ** of the sqlite_master table */ - pExpr->op = TK_NULL; - }else if( pWalker->eCode==4 ){ - /* A bound parameter in a CREATE statement that originates from - ** sqlite3_prepare() causes an error */ - pWalker->eCode = 0; - return WRC_Abort; - } - /* Fall through */ + pWalker->u.i = 0; + return WRC_Abort; default: testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ @@ -87256,22 +78856,21 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ } static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ UNUSED_PARAMETER(NotUsed); - pWalker->eCode = 0; + pWalker->u.i = 0; return WRC_Abort; } -static int exprIsConst(Expr *p, int initFlag, int iCur){ +static int exprIsConst(Expr *p, int initFlag){ Walker w; memset(&w, 0, sizeof(w)); - w.eCode = initFlag; + w.u.i = initFlag; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = selectNodeIsConstant; - w.u.iCur = iCur; sqlite3WalkExpr(&w, p); - return w.eCode; + return w.u.i; } /* -** Walk an expression tree. Return non-zero if the expression is constant +** Walk an expression tree. Return 1 if the expression is constant ** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") @@ -87279,31 +78878,21 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){ ** a constant. */ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ - return exprIsConst(p, 1, 0); + return exprIsConst(p, 1); } /* -** Walk an expression tree. Return non-zero if the expression is constant +** Walk an expression tree. Return 1 if the expression is constant ** that does no originate from the ON or USING clauses of a join. ** Return 0 if it involves variables or function calls or terms from ** an ON or USING clause. */ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ - return exprIsConst(p, 2, 0); + return exprIsConst(p, 3); } /* -** Walk an expression tree. Return non-zero if the expression is constant -** for any single row of the table with cursor iCur. In other words, the -** expression must not refer to any non-deterministic function nor any -** table other than iCur. -*/ -SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ - return exprIsConst(p, 3, iCur); -} - -/* -** Walk an expression tree. Return non-zero if the expression is constant +** Walk an expression tree. Return 1 if the expression is constant ** or a function call with constant arguments. Return and 0 if there ** are any variables. ** @@ -87311,27 +78900,10 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ -SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ - assert( isInit==0 || isInit==1 ); - return exprIsConst(p, 4+isInit, 0); +SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){ + return exprIsConst(p, 2); } -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Walk an expression tree. Return 1 if the expression contains a -** subquery of some kind. Return 0 if there are no subqueries. -*/ -SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){ - Walker w; - memset(&w, 0, sizeof(w)); - w.eCode = 1; - w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = selectNodeIsConstant; - sqlite3WalkExpr(&w, p); - return w.eCode==0; -} -#endif - /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer @@ -87394,10 +78966,6 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ case TK_FLOAT: case TK_BLOB: return 0; - case TK_COLUMN: - assert( p->pTab!=0 ); - return ExprHasProperty(p, EP_CanBeNull) || - (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -87415,7 +78983,7 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ */ SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ u8 op; - if( aff==SQLITE_AFF_BLOB ) return 1; + if( aff==SQLITE_AFF_NONE ) return 1; while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } op = p->op; if( op==TK_REGISTER ) op = p->op2; @@ -87505,40 +79073,6 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){ return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); } -/* -** Generate code that checks the left-most column of index table iCur to see if -** it contains any NULL entries. Cause the register at regHasNull to be set -** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull -** to be set to NULL if iCur contains one or more NULL values. -*/ -static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ - int addr1; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull); - addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull); - sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); - VdbeComment((v, "first_entry_in(%d)", iCur)); - sqlite3VdbeJumpHere(v, addr1); -} - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** 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){ - Expr *pLHS; - int res; - assert( !ExprHasProperty(pIn, EP_xIsSelect) ); - pLHS = pIn->pLeft; - pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pIn); - pIn->pLeft = pLHS; - return res; -} -#endif - /* ** This function is used by the implementation of the IN (...) operator. ** The pX parameter is the expression on the RHS of the IN operator, which @@ -87548,7 +79082,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** -** A cursor is opened on the b-tree object that is the RHS of the IN operator +** A cursor is opened on the b-tree object that the RHS of the IN operator ** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: @@ -87558,8 +79092,6 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** 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. -** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be -** implemented as a sequence of comparisons. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: @@ -87568,64 +79100,59 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then -** pX->iTable made to point to the ephemeral table instead of an -** existing table. +** pX->iTable made to point to the ephermeral table instead of an +** existing table. ** -** The inFlags parameter must contain exactly one of the bits -** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains -** IN_INDEX_MEMBERSHIP, then the generated table will be used for a -** fast membership test. When the IN_INDEX_LOOP bit is set, the -** IN index will be used to loop over all values of the RHS of the -** IN operator. -** -** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate -** through the set members) then the b-tree must not contain duplicates. -** An epheremal table must be used unless the selected is guaranteed +** If the prNotFound parameter is 0, then the b-tree will be used to iterate +** through the set members, skipping any duplicates. In this case an +** epheremal table must be used unless the selected is guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or it ** has a UNIQUE constraint or UNIQUE index. ** -** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used -** for fast set membership tests) then an epheremal table must +** If the prNotFound parameter is not 0, then the b-tree will be used +** for fast set membership tests. In this case an epheremal table must ** be used unless is an INTEGER PRIMARY KEY or an index can ** be found with as its left-most column. ** -** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and -** if the RHS of the IN operator is a list (not a subquery) then this -** routine might decide that creating an ephemeral b-tree for membership -** testing is too expensive and return IN_INDEX_NOOP. In that case, the -** calling routine should implement the IN operator using a sequence -** of Eq or Ne comparison operations. -** ** When the b-tree is being used for membership tests, the calling function -** might need to know whether or not the RHS side of the IN operator -** contains a NULL. If prRhsHasNull is not a NULL pointer and -** if there is any chance that the (...) might contain a NULL value at +** needs to know whether or not the structure contains an SQL NULL +** value in order to correctly evaluate expressions like "X IN (Y, Z)". +** If there is any chance that the (...) might contain a NULL value at ** runtime, then a register is allocated and the register number written -** to *prRhsHasNull. If there is no chance that the (...) contains a -** NULL value, then *prRhsHasNull is left unchanged. +** to *prNotFound. If there is no chance that the (...) contains a +** NULL value, then *prNotFound is left unchanged. ** -** If a register is allocated and its location stored in *prRhsHasNull, then -** the value in that register will be NULL if the b-tree contains one or more -** NULL values, and it will be some non-NULL value if the b-tree contains no -** NULL values. +** If a register is allocated and its location stored in *prNotFound, then +** its initial value is NULL. If the (...) does not remain constant +** for the duration of the query (i.e. the SELECT within the (...) +** is a correlated subquery) then the value of the allocated register is +** reset to NULL each time the subquery is rerun. This allows the +** caller to use vdbe code equivalent to the following: +** +** if( register==NULL ){ +** has_null = +** register = 1 +** } +** +** in order to avoid running the +** test more often than is necessary. */ #ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ +SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ - int mustBeUnique; /* True if RHS must be unique */ + int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); - mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; /* Check to see if an existing table or index can be used to ** satisfy the query. This is preferable to generating a new ** ephemeral table. */ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( pParse->nErr==0 && isCandidateForInOpt(p) ){ + if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table . */ Expr *pExpr; /* Expression */ @@ -87675,7 +79202,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ if( (pIdx->aiColumn[0]==iCol) && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq - && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx))) + && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None)) ){ int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); @@ -87684,9 +79211,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ - *prRhsHasNull = ++pParse->nMem; - sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); + if( prNotFound && !pTab->aCol[iCol].notNull ){ + *prNotFound = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } sqlite3VdbeJumpHere(v, iAddr); } @@ -87694,36 +79221,21 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int } } - /* If no preexisting index is available for the IN clause - ** and IN_INDEX_NOOP is an allowed reply - ** and the RHS of the IN operator is a list, not a subquery - ** and the RHS is not contant or has two or fewer terms, - ** then it is not worth creating an ephemeral table to evaluate - ** the IN operator so return IN_INDEX_NOOP. - */ - if( eType==0 - && (inFlags & IN_INDEX_NOOP_OK) - && !ExprHasProperty(pX, EP_xIsSelect) - && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) - ){ - eType = IN_INDEX_NOOP; - } - - if( eType==0 ){ - /* Could not find an existing table or index to use as the RHS b-tree. + /* Could not found an existing table or index to use as the RHS b-tree. ** We will have to generate an ephemeral table to do the job. */ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; eType = IN_INDEX_EPH; - if( inFlags & IN_INDEX_LOOP ){ + if( prNotFound ){ + *prNotFound = rMayHaveNull = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); + }else{ pParse->nQueryLoop = 0; if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ eType = IN_INDEX_ROWID; } - }else if( prRhsHasNull ){ - *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); pParse->nQueryLoop = savedNQueryLoop; @@ -87754,9 +79266,15 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int ** ** If rMayHaveNull is non-zero, that means that the operation is an IN ** (not a SELECT or EXISTS) and that the RHS might contains NULLs. -** All this routine does is initialize the register given by rMayHaveNull -** to NULL. Calling routines will take care of changing this register -** value to non-NULL if the RHS is NULL-free. +** Furthermore, the IN is in a WHERE clause and that we really want +** to iterate over the RHS of the IN operator in order to quickly locate +** all corresponding LHS elements. All this routine does is initialize +** the register given by rMayHaveNull to NULL. Calling routines will take +** care of changing this register value to non-NULL if the RHS is NULL-free. +** +** If rMayHaveNull is zero, that means that the subquery is being used +** for membership testing only. There is no need to initialize any +** registers to indicate the presence or absence of NULLs on the RHS. ** ** For a SELECT or EXISTS operator, return the register that holds the ** result. For IN operators or if an error occurs, the return value is 0. @@ -87765,10 +79283,10 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int SQLITE_PRIVATE int sqlite3CodeSubselect( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ - int rHasNullFlag, /* Register that records whether NULLs exist in RHS */ + int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ int isRowid /* If true, LHS of IN operator is a rowid */ ){ - int jmpIfDynamic = -1; /* One-time test address */ + int testAddr = -1; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return 0; @@ -87785,15 +79303,14 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v); + testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); } #ifndef SQLITE_OMIT_EXPLAIN if( pParse->explain==2 ){ - char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", - jmpIfDynamic>=0?"":"CORRELATED ", - pExpr->op==TK_IN?"LIST":"SCALAR", - pParse->iNextSelectId + char *zMsg = sqlite3MPrintf( + pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ", + pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId ); sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); } @@ -87806,6 +79323,10 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ KeyInfo *pKeyInfo = 0; /* Key information */ + if( rMayHaveNull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); + } + affinity = sqlite3ExprAffinity(pLeft); /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' @@ -87831,7 +79352,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ - Select *pSelect = pExpr->x.pSelect; SelectDest dest; ExprList *pEList; @@ -87839,14 +79359,13 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affSdst = (u8)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); - pSelect->iLimit = 0; - testcase( pSelect->selFlags & SF_Distinct ); + pExpr->x.pSelect->iLimit = 0; testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ - if( sqlite3Select(pParse, pSelect, &dest) ){ + if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){ sqlite3KeyInfoUnref(pKeyInfo); return 0; } - pEList = pSelect->pEList; + pEList = pExpr->x.pSelect->pEList; assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */ assert( pEList!=0 ); assert( pEList->nExpr>0 ); @@ -87867,7 +79386,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( int r1, r2, r3; if( !affinity ){ - affinity = SQLITE_AFF_BLOB; + affinity = SQLITE_AFF_NONE; } if( pKeyInfo ){ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); @@ -87877,7 +79396,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( /* Loop through each expression in . */ r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempReg(pParse); - if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2); + sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; int iValToIns; @@ -87887,9 +79406,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ - if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){ - sqlite3VdbeChangeToNoop(v, jmpIfDynamic); - jmpIfDynamic = -1; + if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, testAddr); + testAddr = -1; } /* Evaluate the expression and insert it into the temp table */ @@ -87939,7 +79458,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; - dest.iSdst = dest.iSDParm; sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); VdbeComment((v, "Init subquery result")); }else{ @@ -87951,7 +79469,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[1]); pSel->iLimit = 0; - pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } @@ -87961,12 +79478,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( } } - if( rHasNullFlag ){ - sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag); - } - - if( jmpIfDynamic>=0 ){ - sqlite3VdbeJumpHere(v, jmpIfDynamic); + if( testAddr>=0 ){ + sqlite3VdbeJumpHere(v, testAddr); } sqlite3ExprCachePop(pParse); @@ -87987,7 +79500,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( ** if the LHS is NULL or if the LHS is not contained within the RHS and the ** RHS contains one or more NULL values. ** -** This routine generates code that jumps to destIfFalse if the LHS is not +** This routine generates code will jump to destIfFalse if the LHS is not ** contained within the RHS. If due to NULLs we cannot determine if the LHS ** is contained in the RHS then jump to destIfNull. If the LHS is contained ** within the RHS then fall through. @@ -88010,9 +79523,7 @@ static void sqlite3ExprCodeIN( v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); - eType = sqlite3FindInIndex(pParse, pExpr, - IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, - destIfFalse==destIfNull ? 0 : &rRhsHasNull); + eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull); /* Figure out the affinity to use to create a key from the results ** of the expression. affinityStr stores a static string suitable for @@ -88026,114 +79537,82 @@ static void sqlite3ExprCodeIN( r1 = sqlite3GetTempReg(pParse); sqlite3ExprCode(pParse, pExpr->pLeft, r1); - /* If sqlite3FindInIndex() did not find or create an index that is - ** suitable for evaluating the IN operator, then evaluate using a - ** sequence of comparisons. + /* If the LHS is NULL, then the result is either false or NULL depending + ** on whether the RHS is empty or not, respectively. */ - if( eType==IN_INDEX_NOOP ){ - ExprList *pList = pExpr->x.pList; - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - int labelOk = sqlite3VdbeMakeLabel(v); - int r2, regToFree; - int regCkNull = 0; - int ii; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - if( destIfNull!=destIfFalse ){ - regCkNull = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull); - } - for(ii=0; iinExpr; ii++){ - r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); - if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ - sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); - } - if( iinExpr-1 || destIfNull!=destIfFalse ){ - sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2, - (void*)pColl, P4_COLLSEQ); - VdbeCoverageIf(v, iinExpr-1); - VdbeCoverageIf(v, ii==pList->nExpr-1); - sqlite3VdbeChangeP5(v, affinity); - }else{ - assert( destIfNull==destIfFalse ); - sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2, - (void*)pColl, P4_COLLSEQ); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL); - } - sqlite3ReleaseTempReg(pParse, regToFree); - } - if( regCkNull ){ - sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfFalse); - } - sqlite3VdbeResolveLabel(v, labelOk); - sqlite3ReleaseTempReg(pParse, regCkNull); + if( destIfNull==destIfFalse ){ + /* Shortcut for the common case where the false and NULL outcomes are + ** the same. */ + sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); }else{ - - /* If the LHS is NULL, then the result is either false or NULL depending - ** on whether the RHS is empty or not, respectively. + int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); + sqlite3VdbeJumpHere(v, addr1); + } + + if( eType==IN_INDEX_ROWID ){ + /* In this case, the RHS is the ROWID of table b-tree */ - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ - if( destIfNull==destIfFalse ){ - /* Shortcut for the common case where the false and NULL outcomes are - ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); - }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfNull); - sqlite3VdbeJumpHere(v, addr1); - } - } - - if( eType==IN_INDEX_ROWID ){ - /* In this case, the RHS is the ROWID of table b-tree + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + VdbeCoverage(v); + }else{ + /* In this case, the RHS is an index b-tree. + */ + sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); + + /* If the set membership test fails, then the result of the + ** "x IN (...)" expression must be either 0 or NULL. If the set + ** contains no NULL values, then the result is 0. If the set + ** contains one or more NULL values, then the result of the + ** expression is also NULL. + */ + if( rRhsHasNull==0 || destIfFalse==destIfNull ){ + /* This branch runs if it is known at compile time that the RHS + ** cannot contain NULL values. This happens as the result + ** of a "NOT NULL" constraint in the database schema. + ** + ** Also run this branch if NULL is equivalent to FALSE + ** for this particular IN operator. */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); VdbeCoverage(v); }else{ - /* In this case, the RHS is an index b-tree. + /* In this branch, the RHS of the IN might contain a NULL and + ** the presence of a NULL on the RHS makes a difference in the + ** outcome. */ - sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); - - /* If the set membership test fails, then the result of the - ** "x IN (...)" expression must be either 0 or NULL. If the set - ** contains no NULL values, then the result is 0. If the set - ** contains one or more NULL values, then the result of the - ** expression is also NULL. + int j1, j2; + + /* First check to see if the LHS is contained in the RHS. If so, + ** then the presence of NULLs in the RHS does not matter, so jump + ** over all of the code that follows. */ - assert( destIfFalse!=destIfNull || rRhsHasNull==0 ); - if( rRhsHasNull==0 ){ - /* This branch runs if it is known at compile time that the RHS - ** cannot contain NULL values. This happens as the result - ** of a "NOT NULL" constraint in the database schema. - ** - ** Also run this branch if NULL is equivalent to FALSE - ** for this particular IN operator. - */ - sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - VdbeCoverage(v); - }else{ - /* In this branch, the RHS of the IN might contain a NULL and - ** the presence of a NULL on the RHS makes a difference in the - ** outcome. - */ - int addr1; - - /* First check to see if the LHS is contained in the RHS. If so, - ** then the answer is TRUE the presence of NULLs in the RHS does - ** not matter. If the LHS is not contained in the RHS, then the - ** answer is NULL if the RHS contains NULLs and the answer is - ** FALSE if the RHS is NULL-free. - */ - addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); - VdbeCoverage(v); - sqlite3VdbeGoto(v, destIfFalse); - sqlite3VdbeJumpHere(v, addr1); - } + j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); + VdbeCoverage(v); + + /* Here we begin generating code that runs if the LHS is not + ** contained within the RHS. Generate additional code that + ** tests the RHS for NULLs. If the RHS contains a NULL then + ** jump to destIfNull. If there are no NULLs in the RHS then + ** jump to destIfFalse. + */ + sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); + + /* The OP_Found at the top of this branch jumps here when true, + ** causing the overall IN expression evaluation to fall through. + */ + sqlite3VdbeJumpHere(v, j1); } } sqlite3ReleaseTempReg(pParse, r1); @@ -88142,6 +79621,17 @@ static void sqlite3ExprCodeIN( } #endif /* SQLITE_OMIT_SUBQUERY */ +/* +** Duplicate an 8-byte value +*/ +static char *dup8bytes(Vdbe *v, const char *in){ + char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); + if( out ){ + memcpy(out, in, 8); + } + return out; +} + #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Generate an instruction that will put the floating point @@ -88154,10 +79644,12 @@ static void sqlite3ExprCodeIN( static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ double value; + char *zV; sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ if( negateFlag ) value = -value; - sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); } } #endif @@ -88181,22 +79673,17 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); - c = sqlite3DecOrHexToI64(z, &value); + c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); if( c==0 || (c==2 && negFlag) ){ + char *zV; if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } - sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); }else{ #ifdef SQLITE_OMIT_FLOATING_POINT sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); #else -#ifndef SQLITE_OMIT_HEX_INTEGER - if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s", z); - }else -#endif - { - codeReal(v, z, negFlag, iMem); - } + codeReal(v, z, negFlag, iMem); #endif } } @@ -88225,8 +79712,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int int idxLru; struct yColCache *p; - /* Unless an error has occurred, register numbers are always positive. */ - assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); + assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used @@ -88350,28 +79836,6 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ } } -/* Generate code that will load into register regOut a value that is -** appropriate for the iIdxCol-th column of index pIdx. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn( - Parse *pParse, /* The parsing context */ - Index *pIdx, /* The index whose column is to be loaded */ - int iTabCur, /* Cursor pointing to a table row */ - int iIdxCol, /* The column of the index to be loaded */ - int regOut /* Store the index column value in this register */ -){ - i16 iTabCol = pIdx->aiColumn[iIdxCol]; - if( iTabCol==XN_EXPR ){ - assert( pIdx->aColExpr ); - assert( pIdx->aColExpr->nExpr>iIdxCol ); - pParse->iSelfTab = iTabCur; - sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); - }else{ - sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, - iTabCol, regOut); - } -} - /* ** Generate code to extract the value of the iCol-th column of a table. */ @@ -88399,12 +79863,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( /* ** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in a register. -** -** An effort is made to store the column value in register iReg. This -** is not garanteeed for GetColumn() - the result can be stored in -** any register. But the result is guaranteed to land in register iReg -** for GetColumnToReg(). +** table pTab and store the column value in a register. An effort +** is made to store the column value in register iReg, but this is +** not guaranteed. The location of the column value is returned. ** ** There must be an open cursor to pTab in iTable when this routine ** is called. If iColumn<0 then code is generated that extracts the rowid. @@ -88415,7 +79876,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg, /* Store results here */ - u8 p5 /* P5 value for OP_Column + FLAGS */ + u8 p5 /* P5 value for OP_Column */ ){ Vdbe *v = pParse->pVdbe; int i; @@ -88437,17 +79898,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( } return iReg; } -SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* Description of the table we are reading from */ - int iColumn, /* Index of the table column */ - int iTable, /* The cursor pointing to the table */ - int iReg /* Store results here */ -){ - int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); - if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); -} - /* ** Clear all column cache entries. @@ -88482,9 +79932,16 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, in ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. */ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + int i; + struct yColCache *p; assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); - sqlite3ExprCacheRemove(pParse, iFrom, nReg); + for(i=0, p=pParse->aColCache; iiReg; + if( x>=iFrom && xiReg += iTo-iFrom; + } + } } #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) @@ -88571,9 +80028,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) inReg = pExpr->iColumn + pParse->ckBase; break; }else{ - /* Coding an expression that is part of an index where column names - ** in the index refer to the table to which the index belongs */ - iTab = pParse->iSelfTab; + /* Deleting from a partial index */ + iTab = pParse->iPartIdxTab; } } inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, @@ -88594,7 +80050,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) #endif case TK_STRING: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3VdbeLoadString(v, target, pExpr->u.zToken); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); break; } case TK_NULL: { @@ -88633,16 +80089,33 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) inReg = pExpr->iTable; break; } + case TK_AS: { + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + break; + } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ + int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + aff = sqlite3AffinityType(pExpr->u.zToken, 0); + to_op = aff - SQLITE_AFF_TEXT + OP_ToText; + assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); + assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); + assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); + assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); + assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + testcase( to_op==OP_ToText ); + testcase( to_op==OP_ToBlob ); + testcase( to_op==OP_ToNumeric ); + testcase( to_op==OP_ToInt ); + testcase( to_op==OP_ToReal ); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } - sqlite3VdbeAddOp2(v, OP_Cast, target, - sqlite3AffinityType(pExpr->u.zToken, 0)); + sqlite3VdbeAddOp1(v, to_op, inReg); testcase( usedAsColumnCache(pParse, inReg, inReg) ); sqlite3ExprCacheAffinityChange(pParse, inReg, 1); break; @@ -88756,7 +80229,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverageIf(v, op==TK_ISNULL); VdbeCoverageIf(v, op==TK_NOTNULL); - sqlite3VdbeAddOp2(v, OP_Integer, 0, target); + sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); break; } @@ -88792,13 +80265,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); - if( pDef==0 || pDef->xFunc==0 ){ + if( pDef==0 ){ sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); break; } /* Attempt a direct implementation of the built-in COALESCE() and - ** IFNULL() functions. This avoids unnecessary evaluation of + ** IFNULL() functions. This avoids unnecessary evalation of ** arguments past the first non-NULL argument. */ if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ @@ -88822,7 +80295,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) */ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); - inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); break; } @@ -88863,7 +80336,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ - sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, + sqlite3ExprCodeExprList(pParse, pFarg, r1, SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ }else{ @@ -88892,7 +80365,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target, + sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); if( nFarg && constMask==0 ){ @@ -89007,10 +80480,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) #ifndef SQLITE_OMIT_FLOATING_POINT /* If the column has REAL affinity, it may currently be stored as an - ** integer. Use OP_RealAffinity to make sure it is really real. - ** - ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to - ** floating point when extracting it from the record. */ + ** integer. Use OP_RealAffinity to make sure it is really real. */ if( pExpr->iColumn>=0 && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL ){ @@ -89087,7 +80557,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); - sqlite3VdbeGoto(v, endLabel); + sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); sqlite3ExprCachePop(pParse); sqlite3VdbeResolveLabel(v, nextCase); } @@ -89218,25 +80688,13 @@ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); }else{ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); - assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); + assert( pParse->pVdbe || pParse->db->mallocFailed ); if( inReg!=target && pParse->pVdbe ){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); } } } -/* -** Make a transient copy of expression pExpr and then code it using -** sqlite3ExprCode(). This routine works just like sqlite3ExprCode() -** except that the input expression is guaranteed to be unchanged. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){ - sqlite3 *db = pParse->db; - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target); - sqlite3ExprDelete(db, pExpr); -} - /* ** Generate code that will evaluate expression pExpr and store the ** results in register target. The results are guaranteed to appear @@ -89252,7 +80710,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int ta } /* -** Generate code that evaluates the given expression and puts the result +** Generate code that evalutes the given expression and puts the result ** in register target. ** ** Also make a copy of the expression results into another "cache" register @@ -89275,6 +80733,278 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ exprToRegister(pExpr, iMem); } +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) +/* +** Generate a human-readable explanation of an expression tree. +*/ +SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){ + int op; /* The opcode being coded */ + const char *zBinOp = 0; /* Binary operator */ + const char *zUniOp = 0; /* Unary operator */ + if( pExpr==0 ){ + op = TK_NULL; + }else{ + op = pExpr->op; + } + switch( op ){ + case TK_AGG_COLUMN: { + sqlite3ExplainPrintf(pOut, "AGG{%d:%d}", + pExpr->iTable, pExpr->iColumn); + break; + } + case TK_COLUMN: { + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn); + }else{ + sqlite3ExplainPrintf(pOut, "{%d:%d}", + pExpr->iTable, pExpr->iColumn); + } + break; + } + case TK_INTEGER: { + if( pExpr->flags & EP_IntValue ){ + sqlite3ExplainPrintf(pOut, "%d", pExpr->u.iValue); + }else{ + sqlite3ExplainPrintf(pOut, "%s", pExpr->u.zToken); + } + break; + } +#ifndef SQLITE_OMIT_FLOATING_POINT + case TK_FLOAT: { + sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken); + break; + } +#endif + case TK_STRING: { + sqlite3ExplainPrintf(pOut,"%Q", pExpr->u.zToken); + break; + } + case TK_NULL: { + sqlite3ExplainPrintf(pOut,"NULL"); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken); + break; + } +#endif + case TK_VARIABLE: { + sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)", + pExpr->u.zToken, pExpr->iColumn); + break; + } + case TK_REGISTER: { + sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable); + break; + } + case TK_AS: { + sqlite3ExplainExpr(pOut, pExpr->pLeft); + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + const char *zAff = "unk"; + switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){ + case SQLITE_AFF_TEXT: zAff = "TEXT"; break; + case SQLITE_AFF_NONE: zAff = "NONE"; break; + case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break; + case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break; + case SQLITE_AFF_REAL: zAff = "REAL"; break; + } + sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff); + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut, ")"); + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: zBinOp = "LT"; break; + case TK_LE: zBinOp = "LE"; break; + case TK_GT: zBinOp = "GT"; break; + case TK_GE: zBinOp = "GE"; break; + case TK_NE: zBinOp = "NE"; break; + case TK_EQ: zBinOp = "EQ"; break; + case TK_IS: zBinOp = "IS"; break; + case TK_ISNOT: zBinOp = "ISNOT"; break; + case TK_AND: zBinOp = "AND"; break; + case TK_OR: zBinOp = "OR"; break; + case TK_PLUS: zBinOp = "ADD"; break; + case TK_STAR: zBinOp = "MUL"; break; + case TK_MINUS: zBinOp = "SUB"; break; + case TK_REM: zBinOp = "REM"; break; + case TK_BITAND: zBinOp = "BITAND"; break; + case TK_BITOR: zBinOp = "BITOR"; break; + case TK_SLASH: zBinOp = "DIV"; break; + case TK_LSHIFT: zBinOp = "LSHIFT"; break; + case TK_RSHIFT: zBinOp = "RSHIFT"; break; + case TK_CONCAT: zBinOp = "CONCAT"; break; + + case TK_UMINUS: zUniOp = "UMINUS"; break; + case TK_UPLUS: zUniOp = "UPLUS"; break; + case TK_BITNOT: zUniOp = "BITNOT"; break; + case TK_NOT: zUniOp = "NOT"; break; + case TK_ISNULL: zUniOp = "ISNULL"; break; + case TK_NOTNULL: zUniOp = "NOTNULL"; break; + + case TK_COLLATE: { + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); + break; + } + + case TK_AGG_FUNCTION: + case TK_FUNCTION: { + ExprList *pFarg; /* List of function arguments */ + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ + pFarg = 0; + }else{ + pFarg = pExpr->x.pList; + } + if( op==TK_AGG_FUNCTION ){ + sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(", + pExpr->op2, pExpr->u.zToken); + }else{ + sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken); + } + if( pFarg ){ + sqlite3ExplainExprList(pOut, pFarg); + } + sqlite3ExplainPrintf(pOut, ")"); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: { + sqlite3ExplainPrintf(pOut, "EXISTS("); + sqlite3ExplainSelect(pOut, pExpr->x.pSelect); + sqlite3ExplainPrintf(pOut,")"); + break; + } + case TK_SELECT: { + sqlite3ExplainPrintf(pOut, "("); + sqlite3ExplainSelect(pOut, pExpr->x.pSelect); + sqlite3ExplainPrintf(pOut, ")"); + break; + } + case TK_IN: { + sqlite3ExplainPrintf(pOut, "IN("); + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut, ","); + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + sqlite3ExplainSelect(pOut, pExpr->x.pSelect); + }else{ + sqlite3ExplainExprList(pOut, pExpr->x.pList); + } + sqlite3ExplainPrintf(pOut, ")"); + break; + } +#endif /* SQLITE_OMIT_SUBQUERY */ + + /* + ** x BETWEEN y AND z + ** + ** This is equivalent to + ** + ** x>=y AND x<=z + ** + ** X is stored in pExpr->pLeft. + ** Y is stored in pExpr->pList->a[0].pExpr. + ** Z is stored in pExpr->pList->a[1].pExpr. + */ + case TK_BETWEEN: { + Expr *pX = pExpr->pLeft; + Expr *pY = pExpr->x.pList->a[0].pExpr; + Expr *pZ = pExpr->x.pList->a[1].pExpr; + sqlite3ExplainPrintf(pOut, "BETWEEN("); + sqlite3ExplainExpr(pOut, pX); + sqlite3ExplainPrintf(pOut, ","); + sqlite3ExplainExpr(pOut, pY); + sqlite3ExplainPrintf(pOut, ","); + sqlite3ExplainExpr(pOut, pZ); + sqlite3ExplainPrintf(pOut, ")"); + break; + } + case TK_TRIGGER: { + /* If the opcode is TK_TRIGGER, then the expression is a reference + ** to a column in the new.* or old.* pseudo-tables available to + ** trigger programs. In this case Expr.iTable is set to 1 for the + ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn + ** is set to the column of the pseudo-table to read, or to -1 to + ** read the rowid field. + */ + sqlite3ExplainPrintf(pOut, "%s(%d)", + pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); + break; + } + case TK_CASE: { + sqlite3ExplainPrintf(pOut, "CASE("); + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut, ","); + sqlite3ExplainExprList(pOut, pExpr->x.pList); + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + const char *zType = "unk"; + switch( pExpr->affinity ){ + case OE_Rollback: zType = "rollback"; break; + case OE_Abort: zType = "abort"; break; + case OE_Fail: zType = "fail"; break; + case OE_Ignore: zType = "ignore"; break; + } + sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken); + break; + } +#endif + } + if( zBinOp ){ + sqlite3ExplainPrintf(pOut,"%s(", zBinOp); + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut,","); + sqlite3ExplainExpr(pOut, pExpr->pRight); + sqlite3ExplainPrintf(pOut,")"); + }else if( zUniOp ){ + sqlite3ExplainPrintf(pOut,"%s(", zUniOp); + sqlite3ExplainExpr(pOut, pExpr->pLeft); + sqlite3ExplainPrintf(pOut,")"); + } +} +#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */ + +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) +/* +** Generate a human-readable explanation of an expression list. +*/ +SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){ + int i; + if( pList==0 || pList->nExpr==0 ){ + sqlite3ExplainPrintf(pOut, "(empty-list)"); + return; + }else if( pList->nExpr==1 ){ + sqlite3ExplainExpr(pOut, pList->a[0].pExpr); + }else{ + sqlite3ExplainPush(pOut); + for(i=0; inExpr; i++){ + sqlite3ExplainPrintf(pOut, "item[%d] = ", i); + sqlite3ExplainPush(pOut); + sqlite3ExplainExpr(pOut, pList->a[i].pExpr); + sqlite3ExplainPop(pOut); + if( pList->a[i].zName ){ + sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); + } + if( pList->a[i].bSpanIsTab ){ + sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); + } + if( inExpr-1 ){ + sqlite3ExplainNL(pOut); + } + } + sqlite3ExplainPop(pOut); + } +} +#endif /* SQLITE_DEBUG */ + /* ** Generate code that pushes the value of every element of the given ** expression list into a sequence of registers beginning at target. @@ -89286,22 +81016,16 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ ** ** The SQLITE_ECEL_FACTOR argument allows constant arguments to be ** factored out into initialization code. -** -** The SQLITE_ECEL_REF flag means that expressions in the list with -** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored -** in registers at srcReg, and so the value can be copied from there. */ SQLITE_PRIVATE int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int target, /* Where to write results */ - int srcReg, /* Source registers if SQLITE_ECEL_REF */ u8 flags /* SQLITE_ECEL_* flags */ ){ struct ExprList_item *pItem; - int i, j, n; + int i, n; u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; - Vdbe *v = pParse->pVdbe; assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ @@ -89309,14 +81033,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; - if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){ - sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); - }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ + if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ VdbeOp *pOp; + Vdbe *v = pParse->pVdbe; if( copyOp==OP_Copy && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy && pOp->p1+pOp->p3+1==inReg @@ -89342,7 +81065,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( ** x>=y AND x<=z ** ** Code it as such, taking care to do the common subexpression -** elimination of x. +** elementation of x. */ static void exprCodeBetween( Parse *pParse, /* Parsing and code generating context */ @@ -89493,14 +81216,14 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = jumpIfNull ? dest : destIfFalse; sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); - sqlite3VdbeGoto(v, dest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); sqlite3VdbeResolveLabel(v, destIfFalse); break; } #endif default: { if( exprAlwaysTrue(pExpr) ){ - sqlite3VdbeGoto(v, dest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); }else if( exprAlwaysFalse(pExpr) ){ /* No-op */ }else{ @@ -89656,7 +81379,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int #endif default: { if( exprAlwaysFalse(pExpr) ){ - sqlite3VdbeGoto(v, dest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); }else if( exprAlwaysTrue(pExpr) ){ /* no-op */ }else{ @@ -89673,21 +81396,6 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int sqlite3ReleaseTempReg(pParse, regFree2); } -/* -** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before -** code generation, and that copy is deleted after code generation. This -** ensures that the original pExpr is unchanged. -*/ -SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ - sqlite3 *db = pParse->db; - Expr *pCopy = sqlite3ExprDup(db, pExpr, 0); - if( db->mallocFailed==0 ){ - sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull); - } - sqlite3ExprDelete(db, pCopy); -} - - /* ** Do a deep comparison of two expression trees. Return 0 if the two ** expressions are completely identical. Return 1 if they differ only @@ -89731,10 +81439,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ } return 2; } - if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ - if( pA->op==TK_FUNCTION ){ - if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; - }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ + if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){ + if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ return pA->op==TK_COLLATE ? 1 : 2; } } @@ -89744,7 +81450,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; - if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ + if( ALWAYS((combinedFlags & EP_Reduced)==0) ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; @@ -89846,11 +81552,10 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ int i; struct SrcCount *p = pWalker->u.pSrcCount; SrcList *pSrc = p->pSrc; - int nSrc = pSrc ? pSrc->nSrc : 0; - for(i=0; inSrc; i++){ if( pExpr->iTable==pSrc->a[i].iCursor ) break; } - if( inSrc ){ p->nThis++; }else{ p->nOther++; @@ -90097,7 +81802,7 @@ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ ** purpose. ** ** If a register is currently being used by the column cache, then -** the deallocation is deferred until the column cache line that uses +** the dallocation is deferred until the column cache line that uses ** the register becomes stale. */ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ @@ -90163,7 +81868,6 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. */ -/* #include "sqliteInt.h" */ /* ** The code in this file only exists if we are not omitting the @@ -90277,7 +81981,6 @@ static void renameParentFunc( n = sqlite3GetToken(z, &token); }while( token==TK_SPACE ); - if( token==TK_ILLEGAL ) break; zParent = sqlite3DbStrNDup(db, (const char *)z, n); if( zParent==0 ) break; sqlite3Dequote(zParent); @@ -90326,8 +82029,8 @@ static void renameTriggerFunc( UNUSED_PARAMETER(NotUsed); /* The principle used to locate the table name in the CREATE TRIGGER - ** statement is that the table name is the first token that is immediately - ** preceded by either TK_ON or TK_DOT and immediately followed by one + ** statement is that the table name is the first token that is immediatedly + ** preceded by either TK_ON or TK_DOT and immediatedly followed by one ** of TK_WHEN, TK_BEGIN or TK_FOR. */ if( zSql ){ @@ -90642,7 +82345,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( #ifndef SQLITE_OMIT_VIRTUALTABLE if( pVTab ){ int i = ++pParse->nMem; - sqlite3VdbeLoadString(v, i, zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); sqlite3MayAbort(pParse); } @@ -90753,14 +82456,14 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minForm if( ALWAYS(v) ){ int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); - int addr1; + int j1; sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } @@ -90842,10 +82545,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ */ if( pDflt ){ sqlite3_value *pVal = 0; - int rc; - rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - if( rc!=SQLITE_OK ){ + if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ db->mallocFailed = 1; return; } @@ -91021,7 +82721,7 @@ exit_begin_add_column: ** not possible to enable both STAT3 and STAT4 at the same time. If they ** are both enabled, then STAT4 takes precedence. ** -** For most applications, sqlite_stat1 provides all the statistics required +** For most applications, sqlite_stat1 provides all the statisics required ** for the query planner to make good choices. ** ** Format of sqlite_stat1: @@ -91126,7 +82826,6 @@ exit_begin_add_column: ** integer in the equivalent columns in sqlite_stat4. */ #ifndef SQLITE_OMIT_ANALYZE -/* #include "sqliteInt.h" */ #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 @@ -91232,7 +82931,6 @@ static void openStatTable( assert( i0 ); + assert( nCol>1 ); /* >1 because it includes the rowid column */ nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol; - nKeyCol = sqlite3_value_int(argv[1]); - assert( nKeyCol<=nCol ); - assert( nKeyCol>0 ); /* Allocate the space required for the Stat4Accum object */ n = sizeof(*p) @@ -91421,7 +83100,6 @@ static void statInit( p->db = db; p->nRow = 0; p->nCol = nCol; - p->nKeyCol = nKeyCol; p->current.anDLt = (tRowcnt*)&p[1]; p->current.anEq = &p->current.anDLt[nColUp]; @@ -91432,9 +83110,9 @@ static void statInit( p->iGet = -1; p->mxSample = mxSample; - p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); + p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1); p->current.anLt = &p->current.anEq[nColUp]; - p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); + p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565; /* Set up the Stat4Accum.a[] and aBest[] arrays */ p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; @@ -91453,14 +83131,11 @@ static void statInit( } #endif - /* Return a pointer to the allocated object to the caller. Note that - ** only the pointer (the 2nd parameter) matters. The size of the object - ** (given by the 3rd parameter) is never used and can be any positive - ** value. */ - sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor); + /* Return a pointer to the allocated object to the caller */ + sqlite3_result_blob(context, p, sizeof(p), stat4Destructor); } static const FuncDef statInitFuncdef = { - 2+IsStat34, /* nArg */ + 1+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ @@ -91684,10 +83359,7 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ ** R Rowid for the current row. Might be a key record for ** WITHOUT ROWID tables. ** -** This SQL function always returns NULL. It's purpose it to accumulate -** statistical data and/or samples in the Stat4Accum object about the -** index being analyzed. The stat_get() SQL function will later be used to -** extract relevant information for constructing the sqlite_statN tables. +** The SQL function always returns NULL. ** ** The R parameter is only used for STAT3 and STAT4 */ @@ -91704,7 +83376,7 @@ static void statPush( UNUSED_PARAMETER( argc ); UNUSED_PARAMETER( context ); - assert( p->nCol>0 ); + assert( p->nCol>1 ); /* Includes rowid field */ assert( iChngnCol ); if( p->nRow==0 ){ @@ -91781,10 +83453,7 @@ static const FuncDef statPushFuncdef = { /* ** Implementation of the stat_get(P,J) SQL function. This routine is -** used to query statistical information that has been gathered into -** the Stat4Accum object by prior calls to stat_push(). The P parameter -** has type BLOB but it is really just a pointer to the Stat4Accum object. -** The content to returned is determined by the parameter J +** used to query the results. Content is returned for parameter J ** which is one of the STAT_GET_xxxx values defined above. ** ** If neither STAT3 nor STAT4 are enabled, then J is always @@ -91835,7 +83504,7 @@ static void statGet( char *z; int i; - char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 ); + char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); return; @@ -91843,7 +83512,7 @@ static void statGet( sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); z = zRet + sqlite3Strlen30(zRet); - for(i=0; inKeyCol; i++){ + for(i=0; i<(p->nCol-1); i++){ u64 nDistinct = p->current.anDLt[i] + 1; u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; sqlite3_snprintf(24, z, " %llu", iVal); @@ -91929,7 +83598,7 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ #else UNUSED_PARAMETER( iParam ); #endif - sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4, regOut); + sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut); sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 1 + IsStat34); } @@ -91976,7 +83645,7 @@ static void analyzeOneTable( /* Do not gather statistics on views or virtual tables */ return; } - if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ + if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){ /* Do not gather statistics on system tables */ return; } @@ -92000,30 +83669,30 @@ static void analyzeOneTable( iIdxCur = iTab++; pParse->nTab = MAX(pParse->nTab, iTab); sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeLoadString(v, regTabname, pTab->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int nCol; /* Number of columns in pIdx. "N" */ + int nCol; /* Number of columns indexed by pIdx */ + int *aGotoChng; /* Array of jump instruction addresses */ int addrRewind; /* Address of "OP_Rewind iIdxCur" */ + int addrGotoChng0; /* Address of "Goto addr_chng_0" */ int addrNextRow; /* Address of "next_row:" */ const char *zIdxName; /* Name of the index */ - int nColTest; /* Number of columns to test for changes */ if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0; - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){ - nCol = pIdx->nKeyCol; - zIdxName = pTab->zName; - nColTest = nCol - 1; - }else{ - nCol = pIdx->nColumn; - zIdxName = pIdx->zName; - nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1; - } + VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName)); + nCol = pIdx->nKeyCol; + aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1)); + if( aGotoChng==0 ) continue; /* Populate the register containing the index name. */ - sqlite3VdbeLoadString(v, regIdxname, zIdxName); - VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName)); + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ + zIdxName = pTab->zName; + }else{ + zIdxName = pIdx->zName; + } + sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0); /* ** Pseudo-code for loop that calls stat_push(): @@ -92048,7 +83717,7 @@ static void analyzeOneTable( ** regPrev(1) = idx(1) ** ... ** - ** endDistinctTest: + ** chng_addr_N: ** regRowid = idx(rowid) ** stat_push(P, regChng, regRowid) ** Next csr @@ -92061,7 +83730,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); + pParse->nMem = MAX(pParse->nMem, regPrev+nCol); /* Open a read-only cursor on the index being analyzed. */ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); @@ -92071,22 +83740,18 @@ static void analyzeOneTable( /* Invoke the stat_init() function. The arguments are: ** - ** (1) the number of columns in the index including the rowid - ** (or for a WITHOUT ROWID table, the number of PK columns), - ** (2) the number of columns in the key without the rowid/pk - ** (3) the number of rows in the index, + ** (1) the number of columns in the index including the rowid, + ** (2) the number of rows in the index, ** - ** - ** The third argument is only used for STAT3 and STAT4 + ** The second argument is only used for STAT3 and STAT4 */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3); + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+2); #endif - sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1); - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2); - sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4+1, regStat4); + sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+1); + sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4); sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 2+IsStat34); + sqlite3VdbeChangeP5(v, 1+IsStat34); /* Implementation of the following: ** @@ -92099,62 +83764,44 @@ static void analyzeOneTable( addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); + addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto); + + /* + ** next_row: + ** regChng = 0 + ** if( idx(0) != regPrev(0) ) goto chng_addr_0 + ** regChng = 1 + ** if( idx(1) != regPrev(1) ) goto chng_addr_1 + ** ... + ** regChng = N + ** goto chng_addr_N + */ addrNextRow = sqlite3VdbeCurrentAddr(v); - - if( nColTest>0 ){ - int endDistinctTest = sqlite3VdbeMakeLabel(v); - int *aGotoChng; /* Array of jump instruction addresses */ - aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); - if( aGotoChng==0 ) continue; - - /* - ** next_row: - ** regChng = 0 - ** if( idx(0) != regPrev(0) ) goto chng_addr_0 - ** regChng = 1 - ** if( idx(1) != regPrev(1) ) goto chng_addr_1 - ** ... - ** regChng = N - ** goto endDistinctTest - */ - sqlite3VdbeAddOp0(v, OP_Goto); - addrNextRow = sqlite3VdbeCurrentAddr(v); - if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){ - /* For a single-column UNIQUE index, once we have found a non-NULL - ** row, we know that all the rest will be distinct, so skip - ** subsequent distinctness tests. */ - sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest); - VdbeCoverage(v); - } - for(i=0; iazColl[i]); - sqlite3VdbeAddOp2(v, OP_Integer, i, regChng); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp); - aGotoChng[i] = - sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - VdbeCoverage(v); - } - sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng); - sqlite3VdbeGoto(v, endDistinctTest); - - - /* - ** chng_addr_0: - ** regPrev(0) = idx(0) - ** chng_addr_1: - ** regPrev(1) = idx(1) - ** ... - */ - sqlite3VdbeJumpHere(v, addrNextRow-1); - for(i=0; iazColl[i]); + sqlite3VdbeAddOp2(v, OP_Integer, i, regChng); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp); + aGotoChng[i] = + sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); } - + sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng); + aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto); + + /* + ** chng_addr_0: + ** regPrev(0) = idx(0) + ** chng_addr_1: + ** regPrev(1) = idx(1) + ** ... + */ + sqlite3VdbeJumpHere(v, addrGotoChng0); + for(i=0; inKeyCol); for(j=0; jnKeyCol; j++){ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); - assert( k>=0 && knCol ); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName)); } @@ -92181,15 +83828,14 @@ static void analyzeOneTable( } #endif assert( regChng==(regStat4+1) ); - sqlite3VdbeAddOp3(v, OP_Function0, 1, regStat4, regTemp); + sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp); sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 2+IsStat34); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); - assert( "BBB"[0]==SQLITE_AFF_TEXT ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); @@ -92207,7 +83853,7 @@ static void analyzeOneTable( int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - pParse->nMem = MAX(pParse->nMem, regCol+nCol); + pParse->nMem = MAX(pParse->nMem, regCol+nCol+1); addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); @@ -92222,12 +83868,14 @@ static void analyzeOneTable( ** be taken */ VdbeCoverageNeverTaken(v); #ifdef SQLITE_ENABLE_STAT3 - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, + pIdx->aiColumn[0], regSample); #else for(i=0; iaiColumn[i]; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); #endif sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); @@ -92239,6 +83887,7 @@ static void analyzeOneTable( /* End of analysis */ sqlite3VdbeJumpHere(v, addrRewind); + sqlite3DbFree(db, aGotoChng); } @@ -92250,8 +83899,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); - assert( "BBB"[0]==SQLITE_AFF_TEXT ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); @@ -92340,7 +83988,6 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ Table *pTab; Index *pIdx; Token *pTableName; - Vdbe *v; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ @@ -92388,8 +84035,6 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ } } } - v = sqlite3GetVdbe(pParse); - if( v ) sqlite3VdbeAddOp0(v, OP_Expire); } /* @@ -92422,7 +84067,7 @@ static void decodeIntArray( #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else - assert( z!=0 ); + if( NEVER(z==0) ) z = ""; #endif for(i=0; *z && ibUnordered = 0; - pIndex->noSkipScan = 0; - while( z[0] ){ - if( sqlite3_strglob("unordered*", z)==0 ){ - pIndex->bUnordered = 1; - }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ - pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3)); - }else if( sqlite3_strglob("noskipscan*", z)==0 ){ - pIndex->noSkipScan = 1; - } -#ifdef SQLITE_ENABLE_COSTMULT - else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){ - pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9)); - } -#endif - while( z[0]!=0 && z[0]!=' ' ) z++; - while( z[0]==' ' ) z++; + { + if( strcmp(z, "unordered")==0 ){ + pIndex->bUnordered = 1; + }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ + int v32 = 0; + sqlite3GetInt32(z+3, &v32); + pIndex->szIdxRow = sqlite3LogEst(v32); } } } @@ -92504,27 +84141,11 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ z = argv[2]; if( pIndex ){ - tRowcnt *aiRowEst = 0; - int nCol = pIndex->nKeyCol+1; -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - /* Index.aiRowEst may already be set here if there are duplicate - ** sqlite_stat1 entries for this index. In that case just clobber - ** the old data with the new instead of allocating a new array. */ - if( pIndex->aiRowEst==0 ){ - pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); - if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; - } - aiRowEst = pIndex->aiRowEst; -#endif - pIndex->bUnordered = 0; - decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); + decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex); if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; }else{ Index fakeIdx; fakeIdx.szIdxRow = pTable->szTabRow; -#ifdef SQLITE_ENABLE_COSTMULT - fakeIdx.pTable = pTable; -#endif decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); pTable->szTabRow = fakeIdx.szIdxRow; } @@ -92566,52 +84187,30 @@ static void initAvgEq(Index *pIdx){ IndexSample *aSample = pIdx->aSample; IndexSample *pFinal = &aSample[pIdx->nSample-1]; int iCol; - int nCol = 1; - if( pIdx->nSampleCol>1 ){ - /* If this is stat4 data, then calculate aAvgEq[] values for all - ** sample columns except the last. The last is always set to 1, as - ** once the trailing PK fields are considered all index keys are - ** unique. */ - nCol = pIdx->nSampleCol-1; - pIdx->aAvgEq[nCol] = 1; - } - for(iCol=0; iColnSample; + for(iCol=0; iColnKeyCol; iCol++){ int i; /* Used to iterate through samples */ tRowcnt sumEq = 0; /* Sum of the nEq values */ + tRowcnt nSum = 0; /* Number of terms contributing to sumEq */ tRowcnt avgEq = 0; - tRowcnt nRow; /* Number of rows in index */ - i64 nSum100 = 0; /* Number of terms contributing to sumEq */ - i64 nDist100; /* Number of distinct values in index */ - - if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ - nRow = pFinal->anLt[iCol]; - nDist100 = (i64)100 * pFinal->anDLt[iCol]; - nSample--; - }else{ - nRow = pIdx->aiRowEst[0]; - nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1]; - } - pIdx->nRowEst0 = nRow; + tRowcnt nDLt = pFinal->anDLt[iCol]; /* Set nSum to the number of distinct (iCol+1) field prefixes that - ** occur in the stat4 table for this index. Set sumEq to the sum of - ** the nEq values for column iCol for the same set (adding the value - ** only once where there exist duplicate prefixes). */ - for(i=0; inSample-1) - || aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] - ){ + ** occur in the stat4 table for this index before pFinal. Set + ** sumEq to the sum of the nEq values for column iCol for the same + ** set (adding the value only once where there exist dupicate + ** prefixes). */ + for(i=0; i<(pIdx->nSample-1); i++){ + if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){ sumEq += aSample[i].anEq[iCol]; - nSum100 += 100; + nSum++; } } - - if( nDist100>nSum100 ){ - avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100); + if( nDLt>nSum ){ + avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum); } if( avgEq==0 ) avgEq = 1; pIdx->aAvgEq[iCol] = avgEq; + if( pIdx->nSampleCol==1 ) break; } } } @@ -92670,6 +84269,7 @@ static int loadStatTbl( while( sqlite3_step(pStmt)==SQLITE_ROW ){ int nIdxCol = 1; /* Number of columns in stat4 records */ + int nAvgCol = 1; /* Number of entries in Index.aAvgEq */ char *zIndex; /* Index name */ Index *pIdx; /* Pointer to the index object */ @@ -92687,17 +84287,13 @@ static int loadStatTbl( ** loaded from the stat4 table. In this case ignore stat3 data. */ if( pIdx==0 || pIdx->nSample ) continue; if( bStat3==0 ){ - assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); - if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ - nIdxCol = pIdx->nKeyCol; - }else{ - nIdxCol = pIdx->nColumn; - } + nIdxCol = pIdx->nKeyCol+1; + nAvgCol = pIdx->nKeyCol; } pIdx->nSampleCol = nIdxCol; nByte = sizeof(IndexSample) * nSample; nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; - nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ + nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ @@ -92705,7 +84301,7 @@ static int loadStatTbl( return SQLITE_NOMEM; } pSpace = (tRowcnt*)&pIdx->aSample[nSample]; - pIdx->aAvgEq = pSpace; pSpace += nIdxCol; + pIdx->aAvgEq = pSpace; pSpace += nAvgCol; for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; @@ -92854,17 +84450,12 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ + if( rc==SQLITE_OK ){ int lookasideEnabled = db->lookaside.bEnabled; db->lookaside.bEnabled = 0; rc = loadStat4(db, sInfo.zDatabase); db->lookaside.bEnabled = lookasideEnabled; } - for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ - Index *pIdx = sqliteHashData(i); - sqlite3_free(pIdx->aiRowEst); - pIdx->aiRowEst = 0; - } #endif if( rc==SQLITE_NOMEM ){ @@ -92891,7 +84482,6 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_ATTACH /* @@ -93030,7 +84620,6 @@ static void attachFunc( "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } - sqlite3BtreeEnter(aNew->pBt); pPager = sqlite3BtreePager(aNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); sqlite3BtreeSecureDelete(aNew->pBt, @@ -93038,7 +84627,6 @@ static void attachFunc( #ifndef SQLITE_OMIT_PAGER_PRAGMAS sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); #endif - sqlite3BtreeLeave(aNew->pBt); } aNew->safety_level = 3; aNew->zName = sqlite3DbStrDup(db, zName); @@ -93071,7 +84659,7 @@ static void attachFunc( case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ + if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; @@ -93089,15 +84677,6 @@ static void attachFunc( rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); } -#ifdef SQLITE_USER_AUTHENTICATION - if( rc==SQLITE_OK ){ - u8 newAuth = 0; - rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); - if( newAuthauth.authLevel ){ - rc = SQLITE_AUTH_USER; - } - } -#endif if( rc ){ int iDb = db->nDb - 1; assert( iDb>=2 ); @@ -93178,7 +84757,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3CollapseDatabaseArray(db); + sqlite3ResetAllSchemasOfConnection(db); return; detach_error: @@ -93212,6 +84791,7 @@ static void codeAttach( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ + pParse->nErr++; goto attach_end; } @@ -93239,7 +84819,7 @@ static void codeAttach( assert( v || db->mallocFailed ); if( v ){ - sqlite3VdbeAddOp3(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3); + sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3); assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg ); sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg)); sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); @@ -93481,7 +85061,6 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 */ -/* #include "sqliteInt.h" */ /* ** All of the code in this file may be omitted by defining a single @@ -93534,16 +85113,13 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( ** Setting the auth function to NULL disables this hook. The default ** setting of the auth function is NULL. */ -SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer( +SQLITE_API int sqlite3_set_authorizer( sqlite3 *db, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pArg ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); - db->xAuth = (sqlite3_xauth)xAuth; + db->xAuth = xAuth; db->pAuthArg = pArg; sqlite3ExpirePreparedStatements(db); sqlite3_mutex_leave(db->mutex); @@ -93578,11 +85154,7 @@ SQLITE_PRIVATE int sqlite3AuthReadCol( char *zDb = db->aDb[iDb].zName; /* Name of attached database */ int rc; /* Auth callback return code */ - 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 ){ if( db->nDb>2 || iDb!=0 ){ sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol); @@ -93682,11 +85254,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck( if( db->xAuth==0 ){ return SQLITE_OK; } - 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; @@ -93752,7 +85320,6 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ ** COMMIT ** ROLLBACK */ -/* #include "sqliteInt.h" */ /* ** This routine is called when a new SQL statement is beginning to @@ -93843,19 +85410,6 @@ static void codeTableLocks(Parse *pParse){ #define codeTableLocks(x) #endif -/* -** Return TRUE if the given yDbMask object is empty - if it contains no -** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero() -** macros when SQLITE_MAX_ATTACHED is greater than 30. -*/ -#if SQLITE_MAX_ATTACHED>30 -SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){ - int i; - for(i=0; ipToplevel==0 ); db = pParse->db; + if( db->mallocFailed ) return; if( pParse->nested ) return; - if( db->mallocFailed || pParse->nErr ){ - if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; - return; - } + if( pParse->nErr ) return; /* Begin by generating some termination code at the end of the ** vdbe program @@ -93888,42 +85440,28 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} 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; - sqlite3ErrorMsg(pParse, "user not authenticated"); - return; - } - } -#endif - /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ - if( db->mallocFailed==0 - && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) - ){ + if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){ + yDbMask mask; int iDb, i; assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); sqlite3VdbeJumpHere(v, 0); - for(iDb=0; iDbnDb; iDb++){ - if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; + for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ + if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp4Int(v, OP_Transaction, /* Opcode */ iDb, /* P1 */ - DbMaskTest(pParse->writeMask,iDb), /* P2 */ + (mask & pParse->writeMask)!=0, /* P2 */ pParse->cookieValue[iDb], /* P3 */ db->aDb[iDb].pSchema->iGeneration /* P4 */ ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); - VdbeComment((v, - "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); } #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; inVtabLock; i++){ @@ -93953,14 +85491,14 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ } /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeGoto(v, 1); + sqlite3VdbeAddOp2(v, OP_Goto, 0, 1); } } /* Get the VDBE program ready for execution */ - if( v && pParse->nErr==0 && !db->mallocFailed ){ + if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ @@ -93975,7 +85513,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ pParse->nMem = 0; pParse->nSet = 0; pParse->nVar = 0; - DbMaskZero(pParse->cookieMask); + pParse->cookieMask = 0; } /* @@ -94016,16 +85554,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 @@ -94041,21 +85569,16 @@ SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; - + int nName; + assert( zName!=0 ); + nName = sqlite3Strlen30(zName); /* 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++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); if( p ) break; } return p; @@ -94088,17 +85611,6 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( p = sqlite3FindTable(pParse->db, zName, zDbase); if( p==0 ){ const char *zMsg = isView ? "no such view" : "no such table"; -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ - /* If zName is the not the name of a table in the schema created using - ** CREATE, then check to see if it is the name of an virtual table that - ** can be an eponymous virtual table. */ - Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); - if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ - return pMod->pEpoTab; - } - } -#endif if( zDbase ){ sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); }else{ @@ -94106,7 +85618,6 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( } pParse->checkSchema = 1; } - return p; } @@ -94150,6 +85661,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem( SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; + int nName = sqlite3Strlen30(zName); /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ @@ -94158,7 +85670,7 @@ SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const cha assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&pSchema->idxHash, zName); + p = sqlite3HashFind(&pSchema->idxHash, zName, nName); if( p ) break; } return p; @@ -94171,13 +85683,10 @@ static void freeIndex(sqlite3 *db, Index *p){ #ifndef SQLITE_OMIT_ANALYZE sqlite3DeleteIndexSamples(db, p); #endif + if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); sqlite3ExprDelete(db, p->pPartIdxWhere); - sqlite3ExprListDelete(db, p->aColExpr); sqlite3DbFree(db, p->zColAff); - if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl); -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - sqlite3_free(p->aiRowEst); -#endif + if( p->isResized ) sqlite3DbFree(db, p->azColl); sqlite3DbFree(db, p); } @@ -94189,11 +85698,13 @@ static void freeIndex(sqlite3 *db, Index *p){ */ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; + int len; Hash *pHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &db->aDb[iDb].pSchema->idxHash; - pIndex = sqlite3HashInsert(pHash, zIdxName, 0); + len = sqlite3Strlen30(zIdxName); + pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); if( ALWAYS(pIndex) ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; @@ -94299,7 +85810,7 @@ SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ ** Delete memory allocated for the column names of a table or view (the ** Table.aCol[] array). */ -SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ +static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); @@ -94353,7 +85864,7 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( !db || db->pnBytesFreed==0 ){ char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, 0 + &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); @@ -94366,11 +85877,13 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Delete the Table structure itself. */ - sqlite3DeleteColumnNames(db, pTable); + sqliteDeleteColumnNames(db, pTable); sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zColAff); sqlite3SelectDelete(db, pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK sqlite3ExprListDelete(db, pTable->pCheck); +#endif #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3VtabClear(db, pTable); #endif @@ -94394,7 +85907,8 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, + sqlite3Strlen30(zTabName),0); sqlite3DeleteTable(db, p); db->flags |= SQLITE_InternChanges; } @@ -94500,12 +86014,14 @@ SQLITE_PRIVATE int sqlite3TwoPartName( if( ALWAYS(pName2!=0) && pName2->n>0 ){ if( db->init.busy ) { sqlite3ErrorMsg(pParse, "corrupt database"); + pParse->nErr++; return -1; } *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + pParse->nErr++; return -1; } }else{ @@ -94664,7 +86180,7 @@ SQLITE_PRIVATE void sqlite3StartTable( if( !noErr ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); }else{ - assert( !db->init.busy || CORRUPT_DB ); + assert( !db->init.busy ); sqlite3CodeVerifySchema(pParse, iDb); } goto begin_table_error; @@ -94710,12 +86226,10 @@ SQLITE_PRIVATE void sqlite3StartTable( ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ - int addr1; + int j1; int fileFormat; int reg1, reg2, reg3; - /* nullRow[] is an OP_Record encoding of a row containing 5 NULLs */ - static const char nullRow[] = { 6, 0, 0, 0, 0, 0 }; - sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3BeginWriteOperation(pParse, 0, iDb); #ifndef SQLITE_OMIT_VIRTUALTABLE if( isVirtual ){ @@ -94731,14 +86245,14 @@ SQLITE_PRIVATE void sqlite3StartTable( reg3 = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); - addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); /* This just creates a place-holder record in the sqlite_master table. ** The record created does not contain anything yet. It will be replaced @@ -94759,7 +86273,7 @@ SQLITE_PRIVATE void sqlite3StartTable( } sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); - sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); + sqlite3VdbeAddOp2(v, OP_Null, 0, reg3); sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); @@ -94774,19 +86288,18 @@ begin_table_error: return; } -/* Set properties of a table column based on the (magical) -** name of the column. +/* +** This macro is used to compare two strings in a case-insensitive manner. +** It is slightly faster than calling sqlite3StrICmp() directly, but +** produces larger code. +** +** WARNING: This macro is not compatible with the strcmp() family. It +** returns true if the two strings are equal, otherwise false. */ -#if SQLITE_ENABLE_HIDDEN_COLUMNS -SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ - if( sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){ - pCol->colFlags |= COLFLAG_HIDDEN; - }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ - pTab->tabFlags |= TF_OOOHidden; - } -} -#endif - +#define STRICMP(x, y) (\ +sqlite3UpperToLower[*(unsigned char *)(x)]== \ +sqlite3UpperToLower[*(unsigned char *)(y)] \ +&& sqlite3StrICmp((x)+1,(y)+1)==0 ) /* ** Add a new column to the table currently being constructed. @@ -94812,7 +86325,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){ z = sqlite3NameFromToken(db, pName); if( z==0 ) return; for(i=0; inCol; i++){ - if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ + if( STRICMP(z, p->aCol[i].zName) ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); sqlite3DbFree(db, z); return; @@ -94830,13 +86343,12 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){ pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; - sqlite3ColumnPropertiesFromName(p, pCol); /* If there is no type specified, columns have the default affinity - ** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will + ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will ** be called next to set pCol->affinity correctly. */ - pCol->affinity = SQLITE_AFF_BLOB; + pCol->affinity = SQLITE_AFF_NONE; pCol->szEst = 1; p->nCol++; } @@ -94871,7 +86383,7 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ ** 'CHAR' | SQLITE_AFF_TEXT ** 'CLOB' | SQLITE_AFF_TEXT ** 'TEXT' | SQLITE_AFF_TEXT -** 'BLOB' | SQLITE_AFF_BLOB +** 'BLOB' | SQLITE_AFF_NONE ** 'REAL' | SQLITE_AFF_REAL ** 'FLOA' | SQLITE_AFF_REAL ** 'DOUB' | SQLITE_AFF_REAL @@ -94897,7 +86409,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ aff = SQLITE_AFF_TEXT; }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ - aff = SQLITE_AFF_BLOB; + aff = SQLITE_AFF_NONE; if( zIn[0]=='(' ) zChar = zIn; #ifndef SQLITE_OMIT_FLOATING_POINT }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ @@ -94920,7 +86432,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ ** estimate is scaled so that the size of an integer is 1. */ if( pszEst ){ *pszEst = 1; /* default size is approx 4 bytes */ - if( affpNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; - assert( pCol->zType==0 || CORRUPT_DB ); - sqlite3DbFree(pParse->db, pCol->zType); + assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } @@ -94980,7 +86491,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ p = pParse->pNewTable; if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){ + if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ @@ -94998,30 +86509,6 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ sqlite3ExprDelete(db, pSpan->pExpr); } -/* -** Backwards Compatibility Hack: -** -** Historical versions of SQLite accepted strings as column names in -** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example: -** -** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim) -** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC); -** -** This is goofy. But to preserve backwards compatibility we continue to -** accept it. This routine does the necessary conversion. It converts -** the expression given in its argument from a TK_STRING into a TK_ID -** if the expression is just a TK_STRING with an optional COLLATE clause. -** If the epxression is anything other than TK_STRING, the expression is -** unchanged. -*/ -static void sqlite3StringToId(Expr *p){ - if( p->op==TK_STRING ){ - p->op = TK_ID; - }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){ - p->pLeft->op = TK_ID; - } -} - /* ** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the @@ -95066,24 +86553,18 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( }else{ nTerm = pList->nExpr; for(i=0; ia[i].pExpr); - assert( pCExpr!=0 ); - sqlite3StringToId(pCExpr); - if( pCExpr->op==TK_ID ){ - const char *zCName = pCExpr->u.zToken; - for(iCol=0; iColnCol; iCol++){ - if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zType = pTab->aCol[iCol].zType; - break; - } + for(iCol=0; iColnCol; iCol++){ + if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ + pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; + zType = pTab->aCol[iCol].zType; + break; } } } } if( nTerm==1 && zType && sqlite3StrICmp(zType, "INTEGER")==0 - && sortOrder!=SQLITE_SO_DESC + && sortOrder==SQLITE_SO_ASC ){ pTab->iPKey = iCol; pTab->keyConf = (u8)onError; @@ -95096,11 +86577,14 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( "INTEGER PRIMARY KEY"); #endif }else{ + Vdbe *v = pParse->pVdbe; Index *p; + if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop); p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); if( p ){ p->idxType = SQLITE_IDXTYPE_PRIMARYKEY; + if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK); } pList = 0; } @@ -95319,8 +86803,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){ zStmt[k++] = '('; for(pCol=p->aCol, i=0; inCol; i++, pCol++){ static const char * const azType[] = { - /* SQLITE_AFF_BLOB */ "", /* SQLITE_AFF_TEXT */ " TEXT", + /* SQLITE_AFF_NONE */ "", /* SQLITE_AFF_NUMERIC */ " NUM", /* SQLITE_AFF_INTEGER */ " INT", /* SQLITE_AFF_REAL */ " REAL" @@ -95332,17 +86816,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){ k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; identPut(zStmt, &k, pCol->zName); - assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 ); - assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) ); - testcase( pCol->affinity==SQLITE_AFF_BLOB ); + assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 ); + assert( pCol->affinity-SQLITE_AFF_TEXT < ArraySize(azType) ); testcase( pCol->affinity==SQLITE_AFF_TEXT ); + testcase( pCol->affinity==SQLITE_AFF_NONE ); testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); testcase( pCol->affinity==SQLITE_AFF_INTEGER ); testcase( pCol->affinity==SQLITE_AFF_REAL ); - zType = azType[pCol->affinity - SQLITE_AFF_BLOB]; + zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; len = sqlite3Strlen30(zType); - assert( pCol->affinity==SQLITE_AFF_BLOB + assert( pCol->affinity==SQLITE_AFF_NONE || pCol->affinity==sqlite3AffinityType(zType, 0) ); memcpy(&zStmt[k], zType, len); k += len; @@ -95365,7 +86849,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){ zExtra = sqlite3DbMallocZero(db, nByte); if( zExtra==0 ) return SQLITE_NOMEM; memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn); - pIdx->azColl = (const char**)zExtra; + pIdx->azColl = (char**)zExtra; zExtra += sizeof(char*)*N; memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn); pIdx->aiColumn = (i16*)zExtra; @@ -95424,7 +86908,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){ ** no rowid btree for a WITHOUT ROWID. Instead, the canonical ** data storage is a covering index btree. ** (2) Bypass the creation of the sqlite_master table entry -** for the PRIMARY KEY as the primary key index is now +** for the PRIMARY KEY as the the primary key index is now ** identified by the sqlite_master table entry of the table itself. ** (3) Set the Index.tnum of the PRIMARY KEY Index object in the ** schema to the rootpage from the main table. @@ -95445,12 +86929,20 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ Vdbe *v = pParse->pVdbe; /* Convert the OP_CreateTable opcode that would normally create the - ** root-page for the table into an OP_CreateIndex opcode. The index + ** root-page for the table into a OP_CreateIndex opcode. The index ** created will become the PRIMARY KEY index. */ if( pParse->addrCrTab ){ assert( v ); - sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex); + sqlite3VdbeGetOp(v, pParse->addrCrTab)->opcode = OP_CreateIndex; + } + + /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master + ** table entry. + */ + if( pParse->addrSkipPK ){ + assert( v ); + sqlite3VdbeGetOp(v, pParse->addrSkipPK)->opcode = OP_Goto; } /* Locate the PRIMARY KEY index. Or, if this table was originally @@ -95458,12 +86950,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ */ if( pTab->iPKey>=0 ){ ExprList *pList; - Token ipkToken; - ipkToken.z = pTab->aCol[pTab->iPKey].zName; - ipkToken.n = sqlite3Strlen30(ipkToken.z); - pList = sqlite3ExprListAppend(pParse, 0, - sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); + pList = sqlite3ExprListAppend(pParse, 0, 0); if( pList==0 ) return; + pList->a[0].zName = sqlite3DbStrDup(pParse->db, + pTab->aCol[pTab->iPKey].zName); pList->a[0].sortOrder = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); @@ -95472,42 +86962,16 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pTab->iPKey = -1; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); - - /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master - ** table entry. This is only required if currently generating VDBE - ** code for a CREATE TABLE (not when parsing one as part of reading - ** a database schema). */ - if( v ){ - assert( db->init.busy==0 ); - sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto); - } - - /* - ** Remove all redundant columns from the PRIMARY KEY. For example, change - ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later - ** code assumes the PRIMARY KEY contains no repeated columns. - */ - for(i=j=1; inKeyCol; i++){ - if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ - pPk->nColumn--; - }else{ - pPk->aiColumn[j++] = pPk->aiColumn[i]; - } - } - pPk->nKeyCol = j; } pPk->isCovering = 1; assert( pPk!=0 ); nPk = pPk->nKeyCol; - /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except, - ** do not enforce this for imposter tables.) */ - if( !db->init.imposterTable ){ - for(i=0; iaCol[pPk->aiColumn[i]].notNull = OE_Abort; - } - pPk->uniqNotNull = 1; + /* Make sure every column of the PRIMARY KEY is NOT NULL */ + for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1; } + pPk->uniqNotNull = 1; /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; @@ -95546,7 +87010,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( !hasColumn(pPk->aiColumn, j, i) ){ assert( jnColumn ); pPk->aiColumn[j] = i; - pPk->azColl[j] = sqlite3StrBINARY; + pPk->azColl[j] = "BINARY"; j++; } } @@ -95589,10 +87053,9 @@ SQLITE_PRIVATE void sqlite3EndTable( int iDb; /* Database in which the table lives */ Index *pIdx; /* An implied index of the table */ - if( pEnd==0 && pSelect==0 ){ + if( (pEnd==0 && pSelect==0) || db->mallocFailed ){ return; } - assert( !db->mallocFailed ); p = pParse->pNewTable; if( p==0 ) return; @@ -95618,7 +87081,7 @@ SQLITE_PRIVATE void sqlite3EndTable( if( (p->tabFlags & TF_HasPrimaryKey)==0 ){ sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); }else{ - p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; + p->tabFlags |= TF_WithoutRowid; convertToWithoutRowidTable(pParse, p); } } @@ -95686,46 +87149,26 @@ SQLITE_PRIVATE void sqlite3EndTable( ** be redundant. */ if( pSelect ){ - SelectDest dest; /* Where the SELECT should store results */ - int regYield; /* Register holding co-routine entry-point */ - int addrTop; /* Top of the co-routine */ - int regRec; /* A record to be insert into the new table */ - int regRowid; /* Rowid of the next row to insert */ - int addrInsLoop; /* Top of the loop for inserting rows */ - Table *pSelTab; /* A table that describes the SELECT results */ + SelectDest dest; + Table *pSelTab; - regYield = ++pParse->nMem; - regRec = ++pParse->nMem; - regRowid = ++pParse->nMem; assert(pParse->nTab==1); - sqlite3MayAbort(pParse); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); pParse->nTab = 2; - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + sqlite3SelectDestInit(&dest, SRT_Table, 1); sqlite3Select(pParse, pSelect, &dest); - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); - if( pParse->nErr ) return; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); - if( pSelTab==0 ) return; - assert( p->aCol==0 ); - p->nCol = pSelTab->nCol; - p->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); - sqlite3TableAffinity(v, p, 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid); - sqlite3VdbeGoto(v, addrInsLoop); - sqlite3VdbeJumpHere(v, addrInsLoop); sqlite3VdbeAddOp1(v, OP_Close, 1); + if( pParse->nErr==0 ){ + pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); + if( pSelTab==0 ) return; + assert( p->aCol==0 ); + p->nCol = pSelTab->nCol; + p->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(db, pSelTab); + } } /* Compute the complete text of the CREATE statement */ @@ -95787,7 +87230,8 @@ SQLITE_PRIVATE void sqlite3EndTable( Table *pOld; Schema *pSchema = p->pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, + sqlite3Strlen30(p->zName),p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ db->mallocFailed = 1; @@ -95820,7 +87264,6 @@ SQLITE_PRIVATE void sqlite3CreateView( Token *pBegin, /* The CREATE token that begins the statement */ Token *pName1, /* The token that holds the name of the view */ Token *pName2, /* The token that holds the name of the view */ - ExprList *pCNames, /* Optional list of view column names */ Select *pSelect, /* A SELECT statement that will become the new view */ int isTemp, /* TRUE for a TEMPORARY view */ int noErr /* Suppress error messages if VIEW already exists */ @@ -95836,15 +87279,22 @@ SQLITE_PRIVATE void sqlite3CreateView( if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); - goto create_view_fail; + sqlite3SelectDelete(db, pSelect); + return; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; - if( p==0 || pParse->nErr ) goto create_view_fail; + if( p==0 || pParse->nErr ){ + sqlite3SelectDelete(db, pSelect); + return; + } sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); - if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; + if( sqlite3FixSelect(&sFix, pSelect) ){ + sqlite3SelectDelete(db, pSelect); + return; + } /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically @@ -95852,31 +87302,30 @@ SQLITE_PRIVATE void sqlite3CreateView( ** they will persist after the current sqlite3_exec() call returns. */ p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); - if( db->mallocFailed ) goto create_view_fail; + sqlite3SelectDelete(db, pSelect); + if( db->mallocFailed ){ + return; + } + if( !db->init.busy ){ + sqlite3ViewGetColumnNames(pParse, p); + } /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; - assert( sEnd.z[0]!=0 ); - if( sEnd.z[0]!=';' ){ + if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = (int)(sEnd.z - pBegin->z); - assert( n>0 ); z = pBegin->z; - while( sqlite3Isspace(z[n-1]) ){ n--; } + while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ sqlite3EndTable(pParse, 0, &sEnd, 0, 0); - -create_view_fail: - sqlite3SelectDelete(db, pSelect); - sqlite3ExprListDelete(db, pCNames); return; } #endif /* SQLITE_OMIT_VIEW */ @@ -95893,8 +87342,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ - sqlite3_xauth xAuth; /* Saved xAuth pointer */ - u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */ + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); assert( pTable ); @@ -95940,46 +87388,40 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ ** statement that defines the view. */ assert( pTable->pSelect ); - bEnabledLA = db->lookaside.bEnabled; - if( pTable->pCheck ){ + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); + if( pSel ){ + u8 enableLookaside = db->lookaside.bEnabled; + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; db->lookaside.bEnabled = 0; - sqlite3ColumnsFromExprList(pParse, pTable->pCheck, - &pTable->nCol, &pTable->aCol); - }else{ - pSel = sqlite3SelectDup(db, pTable->pSelect, 0); - if( pSel ){ - n = pParse->nTab; - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); - pTable->nCol = -1; - db->lookaside.bEnabled = 0; #ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; - db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); - db->xAuth = xAuth; + xAuth = db->xAuth; + db->xAuth = 0; + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + db->xAuth = xAuth; #else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); #endif - pParse->nTab = n; - if( pSelTab ){ - assert( pTable->aCol==0 ); - pTable->nCol = pSelTab->nCol; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); - }else{ - pTable->nCol = 0; - nErr++; - } - sqlite3SelectDelete(db, pSel); - } else { + db->lookaside.bEnabled = enableLookaside; + pParse->nTab = n; + if( pSelTab ){ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(db, pSelTab); + assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; nErr++; } + sqlite3SelectDelete(db, pSel); + } else { + nErr++; } - db->lookaside.bEnabled = bEnabledLA; - pTable->pSchema->schemaFlags |= DB_UnresetViews; #endif /* SQLITE_OMIT_VIEW */ return nErr; } @@ -95996,7 +87438,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ - sqlite3DeleteColumnNames(db, pTab); + sqliteDeleteColumnNames(db, pTab); pTab->aCol = 0; pTab->nCol = 0; } @@ -96246,7 +87688,6 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, } assert( pParse->nErr==0 ); assert( pName->nSrc==1 ); - if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; if( noErr ) db->suppressErr++; pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; @@ -96440,7 +87881,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey( assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, - pFKey->zTo, (void *)pFKey + pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey ); if( pNextTo==pFKey ){ db->mallocFailed = 1; @@ -96503,7 +87944,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ KeyInfo *pKey; /* KeyInfo for index */ - int regRecord; /* Register holding assembled index record */ + int regRecord; /* Register holding assemblied index record */ sqlite3 *db = pParse->db; /* The database connection */ int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); @@ -96528,7 +87969,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; - sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*) + sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*) sqlite3KeyInfoRef(pKey), P4_KEYINFO); /* Open the table. Loop through all rows of the table, inserting index @@ -96549,19 +87990,18 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); assert( pKey!=0 || db->mallocFailed || pParse->nErr ); - if( IsUniqueIndex(pIndex) && pKey!=0 ){ + if( pIndex->onError!=OE_None && pKey!=0 ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; - sqlite3VdbeGoto(v, j2); + sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); addr2 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, - pIndex->nKeyCol); VdbeCoverage(v); + pKey->nField - pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); }else{ addr2 = sqlite3VdbeCurrentAddr(v); } - sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); + sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); @@ -96596,7 +88036,7 @@ SQLITE_PRIVATE Index *sqlite3AllocateIndexObject( p = sqlite3DbMallocZero(db, nByte + nExtra); if( p ){ char *pExtra = ((char*)p)+ROUND8(sizeof(Index)); - p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); + p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1); p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol; p->aSortOrder = (u8*)pExtra; @@ -96648,12 +88088,14 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ + const Column *pTabCol; /* A column in the table */ int nExtra = 0; /* Space allocated for zExtra[] */ int nExtraCol; /* Number of extra columns needed */ char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){ + assert( pParse->nErr==0 ); /* Never called with prior errors */ + if( db->mallocFailed || IN_DECLARE_VTAB ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ @@ -96715,10 +88157,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 - && db->init.busy==0 -#if SQLITE_USER_AUTHENTICATION - && sqlite3UserAuthTable(pTab->zName)==0 -#endif && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; @@ -96802,16 +88240,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( ** So create a fake list to simulate this. */ if( pList==0 ){ - Token prevCol; - prevCol.z = pTab->aCol[pTab->nCol-1].zName; - prevCol.n = sqlite3Strlen30(prevCol.z); - pList = sqlite3ExprListAppend(pParse, 0, - sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); + pList = sqlite3ExprListAppend(pParse, 0, 0); if( pList==0 ) goto exit_create_index; - assert( pList->nExpr==1 ); - sqlite3ExprListSetSortOrder(pList, sortOrder); - }else{ - sqlite3ExprListCheckLength(pParse, pList, "index"); + pList->a[0].zName = sqlite3DbStrDup(pParse->db, + pTab->aCol[pTab->nCol-1].zName); + pList->a[0].sortOrder = (u8)sortOrder; } /* Figure out how many bytes of space are required to store explicitly @@ -96819,8 +88252,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( */ for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; - assert( pExpr!=0 ); - if( pExpr->op==TK_COLLATE ){ + if( pExpr ){ + assert( pExpr->op==TK_COLLATE ); nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); } } @@ -96861,54 +88294,35 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( sortOrderMask = 0; /* Ignore DESC */ } - /* Analyze the list of expressions that form the terms of the index and - ** report any errors. In the common case where the expression is exactly - ** a table column, store that column in aiColumn[]. For general expressions, - ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. + /* Scan the names of the columns of the table to be indexed and + ** load the column indices into the Index structure. Report an error + ** if any column is not found. ** - ** TODO: Issue a warning if two or more columns of the index are identical. - ** TODO: Issue a warning if the table primary key is used as part of the - ** index key. + ** TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ - Expr *pCExpr; /* The i-th index expression */ - int requestedSortOrder; /* ASC or DESC on the i-th expression */ - const char *zColl; /* Collation sequence name */ + const char *zColName = pListItem->zName; + int requestedSortOrder; + char *zColl; /* Collation sequence name */ - sqlite3StringToId(pListItem->pExpr); - sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0); - if( pParse->nErr ) goto exit_create_index; - pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr); - if( pCExpr->op!=TK_COLUMN ){ - if( pTab==pParse->pNewTable ){ - sqlite3ErrorMsg(pParse, "expressions prohibited in PRIMARY KEY and " - "UNIQUE constraints"); - goto exit_create_index; - } - if( pIndex->aColExpr==0 ){ - ExprList *pCopy = sqlite3ExprListDup(db, pList, 0); - pIndex->aColExpr = pCopy; - if( !db->mallocFailed ){ - assert( pCopy!=0 ); - pListItem = &pCopy->a[i]; - } - } - j = XN_EXPR; - pIndex->aiColumn[i] = XN_EXPR; - pIndex->uniqNotNull = 0; - }else{ - j = pCExpr->iColumn; - assert( j<=0x7fff ); - if( j<0 ){ - j = pTab->iPKey; - }else if( pTab->aCol[j].notNull==0 ){ - pIndex->uniqNotNull = 0; - } - pIndex->aiColumn[i] = (i16)j; + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } - zColl = 0; - if( pListItem->pExpr->op==TK_COLLATE ){ + if( j>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "table %s has no column named %s", + pTab->zName, zColName); + pParse->checkSchema = 1; + goto exit_create_index; + } + assert( pTab->nCol<=0x7fff && j<=0x7fff ); + pIndex->aiColumn[i] = (i16)j; + if( pListItem->pExpr ){ int nColl; + assert( pListItem->pExpr->op==TK_COLLATE ); zColl = pListItem->pExpr->u.zToken; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); @@ -96916,26 +88330,21 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( zColl = zExtra; zExtra += nColl; nExtra -= nColl; - }else if( j>=0 ){ + }else{ zColl = pTab->aCol[j].zColl; + if( !zColl ) zColl = "BINARY"; } - if( !zColl ) zColl = sqlite3StrBINARY; if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ goto exit_create_index; } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; + if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0; } - - /* Append the table key to the end of the index. For WITHOUT ROWID - ** tables (when pPk!=0) this will be the declared PRIMARY KEY. For - ** normal tables (when pPk==0) this will be the rowid. - */ if( pPk ){ for(j=0; jnKeyCol; j++){ int x = pPk->aiColumn[j]; - assert( x>=0 ); if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){ pIndex->nColumn--; }else{ @@ -96947,8 +88356,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( } assert( i==pIndex->nColumn ); }else{ - pIndex->aiColumn[i] = XN_ROWID; - pIndex->azColl[i] = sqlite3StrBINARY; + pIndex->aiColumn[i] = -1; + pIndex->azColl[i] = "BINARY"; } sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); @@ -96978,15 +88387,14 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( Index *pIdx; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int k; - assert( IsUniqueIndex(pIdx) ); + assert( pIdx->onError!=OE_None ); assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF ); - assert( IsUniqueIndex(pIndex) ); + assert( pIndex->onError!=OE_None ); if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue; for(k=0; knKeyCol; k++){ const char *z1; const char *z2; - assert( pIdx->aiColumn[k]>=0 ); if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; z1 = pIdx->azColl[k]; z2 = pIndex->azColl[k]; @@ -97009,7 +88417,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( pIdx->onError = pIndex->onError; } } - pRet = pIdx; goto exit_create_index; } } @@ -97018,12 +88425,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( /* Link the new Index structure to its table and to the other ** in-memory database structures. */ - assert( pParse->nErr==0 ); if( db->init.busy ){ Index *p; assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, pIndex); + pIndex->zName, sqlite3Strlen30(pIndex->zName), + pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ db->mallocFailed = 1; @@ -97048,7 +88455,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( ** has just been created, it contains no data and the index initialization ** step can be skipped. */ - else if( HasRowid(pTab) || pTblName!=0 ){ + else if( pParse->nErr==0 && (HasRowid(pTab) || pTblName!=0) ){ Vdbe *v; char *zStmt; int iMem = ++pParse->nMem; @@ -97056,15 +88463,10 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; - sqlite3BeginWriteOperation(pParse, 1, iDb); - /* Create the rootpage for the index using CreateIndex. But before - ** doing so, code a Noop instruction and store its address in - ** Index.tnum. This is required in case this index is actually a - ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In - ** that case the convertToWithoutRowidTable() routine will replace - ** the Noop with a Goto to jump over the VDBE code generated below. */ - pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); + /* Create the rootpage for the index + */ + sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); /* Gather the complete text of the CREATE INDEX statement into @@ -97104,8 +88506,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); sqlite3VdbeAddOp1(v, OP_Expire, 0); } - - sqlite3VdbeJumpHere(v, pIndex->tnum); } /* When adding an index to the list of indices for a table, make @@ -97145,7 +88545,7 @@ exit_create_index: ** Fill the Index.aiRowEst[] array with default information - information ** to be used when we have not run the ANALYZE command. ** -** aiRowEst[0] is supposed to contain the number of elements in the index. +** aiRowEst[0] is suppose to contain the number of elements in the index. ** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the ** number of rows in the table that match any particular value of the ** first column of the index. aiRowEst[2] is an estimate of the number @@ -97180,7 +88580,7 @@ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ } assert( 0==sqlite3LogEst(1) ); - if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0; + if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0; } /* @@ -97508,8 +88908,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ sqlite3DbFree(db, pItem->zDatabase); sqlite3DbFree(db, pItem->zName); sqlite3DbFree(db, pItem->zAlias); - if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy); - if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); + sqlite3DbFree(db, pItem->zIndex); sqlite3DeleteTable(db, pItem->pTab); sqlite3SelectDelete(db, pItem->pSelect); sqlite3ExprDelete(db, pItem->pOn); @@ -97525,7 +88924,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ ** if this is the first term of the FROM clause. pTable and pDatabase ** are the name of the table and database named in the FROM clause term. ** pDatabase is NULL if the database name qualifier is missing - the -** usual case. If the term has an alias, then pAlias points to the +** usual case. If the term has a alias, then pAlias points to the ** alias token. If the term is a subquery, then pSubquery is the ** SELECT statement that the subquery encodes. The pTable and ** pDatabase parameters are NULL for subqueries. The pOn and pUsing @@ -97582,37 +88981,17 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI assert( pIndexedBy!=0 ); if( p && ALWAYS(p->nSrc>0) ){ struct SrcList_item *pItem = &p->a[p->nSrc-1]; - assert( pItem->fg.notIndexed==0 ); - assert( pItem->fg.isIndexedBy==0 ); - assert( pItem->fg.isTabFunc==0 ); + assert( pItem->notIndexed==0 && pItem->zIndex==0 ); if( pIndexedBy->n==1 && !pIndexedBy->z ){ /* A "NOT INDEXED" clause was supplied. See parse.y ** construct "indexed_opt" for details. */ - pItem->fg.notIndexed = 1; + pItem->notIndexed = 1; }else{ - pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); - pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0); + pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy); } } } -/* -** Add the list of function arguments to the SrcList entry for a -** table-valued-function. -*/ -SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){ - if( p ){ - struct SrcList_item *pItem = &p->a[p->nSrc-1]; - assert( pItem->fg.notIndexed==0 ); - assert( pItem->fg.isIndexedBy==0 ); - assert( pItem->fg.isTabFunc==0 ); - pItem->u1.pFuncArg = pList; - pItem->fg.isTabFunc = 1; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } -} - /* ** When building up a FROM clause in the parser, the join operator ** is initially attached to the left operand. But the code generator @@ -97631,10 +89010,11 @@ SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList * SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){ if( p ){ int i; + assert( p->a || p->nSrc==0 ); for(i=p->nSrc-1; i>0; i--){ - p->a[i].fg.jointype = p->a[i-1].fg.jointype; + p->a[i].jointype = p->a[i-1].jointype; } - p->a[0].fg.jointype = 0; + p->a[0].jointype = 0; } } @@ -97760,13 +89140,15 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); sqlite3 *db = pToplevel->db; + yDbMask mask; assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDbcookieMask, iDb)==0 ){ - DbMaskSet(pToplevel->cookieMask, iDb); + mask = ((yDbMask)1)<cookieMask & mask)==0 ){ + pToplevel->cookieMask |= mask; pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pToplevel); @@ -97805,7 +89187,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb) SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); sqlite3CodeVerifySchema(pParse, iDb); - DbMaskSet(pToplevel->writeMask, iDb); + pToplevel->writeMask |= ((yDbMask)1)<isMultiWrite |= setStatement; } @@ -97877,17 +89259,14 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( StrAccum errMsg; Table *pTab = pIdx->pTable; - sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); - if( pIdx->aColExpr ){ - sqlite3XPrintf(&errMsg, 0, "index '%q'", pIdx->zName); - }else{ - for(j=0; jnKeyCol; j++){ - char *zCol; - assert( pIdx->aiColumn[j]>=0 ); - zCol = pTab->aCol[pIdx->aiColumn[j]].zName; - if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3XPrintf(&errMsg, 0, "%s.%s", pTab->zName, zCol); - } + sqlite3StrAccumInit(&errMsg, 0, 0, 200); + errMsg.db = pParse->db; + for(j=0; jnKeyCol; j++){ + char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; + if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); + sqlite3StrAccumAppend(&errMsg, ".", 1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } zErr = sqlite3StrAccumFinish(&errMsg); sqlite3HaltConstraint(pParse, @@ -98059,30 +89438,40 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ ** when it has finished using it. */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ - int i; - int nCol = pIdx->nColumn; - int nKey = pIdx->nKeyCol; - KeyInfo *pKey; if( pParse->nErr ) return 0; - if( pIdx->uniqNotNull ){ - pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); - }else{ - pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ + sqlite3KeyInfoUnref(pIdx->pKeyInfo); + pIdx->pKeyInfo = 0; } - if( pKey ){ - assert( sqlite3KeyInfoIsWriteable(pKey) ); - for(i=0; iazColl[i]; - pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 : - sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; +#endif + if( pIdx->pKeyInfo==0 ){ + int i; + int nCol = pIdx->nColumn; + int nKey = pIdx->nKeyCol; + KeyInfo *pKey; + if( pIdx->uniqNotNull ){ + pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); + }else{ + pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); } - if( pParse->nErr ){ - sqlite3KeyInfoUnref(pKey); - pKey = 0; + if( pKey ){ + assert( sqlite3KeyInfoIsWriteable(pKey) ); + for(i=0; iazColl[i]; + assert( zColl!=0 ); + pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : + sqlite3LocateCollSeq(pParse, zColl); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + if( pParse->nErr ){ + sqlite3KeyInfoUnref(pKey); + }else{ + pIdx->pKeyInfo = pKey; + } } } - return pKey; + return sqlite3KeyInfoRef(pIdx->pKeyInfo); } #ifndef SQLITE_OMIT_CTE @@ -98131,7 +89520,7 @@ SQLITE_PRIVATE With *sqlite3WithAdd( pNew->a[pNew->nCte].pSelect = pQuery; pNew->a[pNew->nCte].pCols = pArglist; pNew->a[pNew->nCte].zName = zName; - pNew->a[pNew->nCte].zCteErr = 0; + pNew->a[pNew->nCte].zErr = 0; pNew->nCte++; } @@ -98173,7 +89562,6 @@ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ ** of user defined functions and collation sequences. */ -/* #include "sqliteInt.h" */ /* ** Invoke the 'collation needed' callback to request a collation sequence @@ -98301,7 +89689,7 @@ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ ** ** Each pointer stored in the sqlite3.aCollSeq hash table contains an ** array of three CollSeq structures. The first is the collation sequence -** preferred for UTF-8, the second UTF-16le, and the third UTF-16be. +** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. ** ** Stored immediately after the three collation sequences is a copy of ** the collation sequence name. A pointer to this string is stored in @@ -98313,11 +89701,11 @@ static CollSeq *findCollSeqEntry( int create /* Create a new entry if true */ ){ CollSeq *pColl; - pColl = sqlite3HashFind(&db->aCollSeq, zName); + int nName = sqlite3Strlen30(zName); + pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); if( 0==pColl && create ){ - int nName = sqlite3Strlen30(zName); - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1); + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); if( pColl ){ CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; @@ -98328,7 +89716,7 @@ static CollSeq *findCollSeqEntry( pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; - pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); + pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); /* If a malloc() failure occurred in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added @@ -98606,9 +89994,9 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ sqlite3HashClear(&temp1); sqlite3HashClear(&pSchema->fkeyHash); pSchema->pSeqTab = 0; - if( pSchema->schemaFlags & DB_SchemaLoaded ){ + if( pSchema->flags & DB_SchemaLoaded ){ pSchema->iGeneration++; - pSchema->schemaFlags &= ~DB_SchemaLoaded; + pSchema->flags &= ~DB_SchemaLoaded; } } @@ -98651,7 +90039,6 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. */ -/* #include "sqliteInt.h" */ /* ** While a SrcList can in general represent multiple tables and subqueries @@ -98729,7 +90116,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ Table *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ - int iCur /* Cursor number for ephemeral table */ + int iCur /* Cursor number for ephemerial table */ ){ SelectDest dest; Select *pSel; @@ -98745,8 +90132,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView( assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, - SF_IncludeHidden, 0, 0); + pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); @@ -98829,7 +90215,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( pInClause->x.pSelect = pSelect; pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeightAndFlags(pParse, pInClause); + sqlite3ExprSetHeight(pParse, pInClause); return pInClause; /* something went wrong. clean up anything allocated. */ @@ -98866,8 +90252,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iTabCur; /* Cursor number for the table */ - int iDataCur = 0; /* VDBE cursor for the canonical data source */ - int iIdxCur = 0; /* Cursor number of the first index */ + int iDataCur; /* VDBE cursor for the canonical data source */ + int iIdxCur; /* Cursor number of the first index */ int nIdx; /* Number of indices */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ @@ -98875,7 +90261,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( int iDb; /* Database number */ int memCnt = -1; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ - int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ + int okOnePass; /* True for one-pass algorithm without the FIFO */ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ Index *pPk; /* The PRIMARY KEY index on the table */ @@ -98887,12 +90273,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( int iRowSet = 0; /* Register for rowset of rows to delete */ int addrBypass = 0; /* Address of jump over the delete logic */ int addrLoop = 0; /* Top of the delete loop */ - int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ + int addrDelete = 0; /* Jump directly to the delete logic */ + int addrEphOpen = 0; /* Instruction to open the Ephermeral table */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ - int bComplex; /* True if there are either triggers or FKs */ #endif memset(&sContext, 0, sizeof(sContext)); @@ -98916,11 +90302,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); isView = pTab->pSelect!=0; - bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #else # define pTrigger 0 # define isView 0 -# define bComplex 0 #endif #ifdef SQLITE_OMIT_VIEW # undef isView @@ -98970,7 +90354,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( sqlite3BeginWriteOperation(pParse, 1, iDb); /* If we are trying to delete from a view, realize that view into - ** an ephemeral table. + ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ @@ -99001,10 +90385,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** It is easier just to erase the whole table. Prior to version 3.6.5, ** this optimization caused the row change count (the value returned by ** API function sqlite3_count_changes) to be set incorrectly. */ - if( rcauth==SQLITE_OK - && pWhere==0 - && !bComplex - && !IsVirtual(pTab) + if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) + && 0==sqlite3FkRequired(pParse, pTab, 0, 0) ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); @@ -99019,8 +90401,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { - u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; - wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; @@ -99028,7 +90408,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); }else{ - /* For a WITHOUT ROWID table, create an ephemeral table used to + /* For a WITHOUT ROWID table, create an ephermeral table used to ** hold all primary keys for rows to be deleted. */ pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); @@ -99041,18 +90421,13 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } /* Construct a query to find the rowid or primary key for every row - ** to be deleted, based on the WHERE clause. Set variable eOnePass - ** to indicate the strategy used to implement this delete: - ** - ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. - ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. - ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. + ** to be deleted, based on the WHERE clause. */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, + WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK, + iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); - assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); + okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); /* Keep track of the number of rows to be deleted */ if( db->flags & SQLITE_CountRows ){ @@ -99062,7 +90437,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( /* Extract the rowid or primary key for the current row */ if( pPk ){ for(i=0; iaiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i], iPk+i); } @@ -99073,10 +90447,11 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( iKey>pParse->nMem ) pParse->nMem = iKey; } - if( eOnePass!=ONEPASS_OFF ){ - /* For ONEPASS, no need to store the rowid/primary-key. There is only + if( okOnePass ){ + /* For ONEPASS, no need to store the rowid/primary-key. There is only ** one, so just keep it in its register(s) and fall through to the - ** delete code. */ + ** delete code. + */ nKey = nPk; /* OP_Found will use an unpacked key */ aToOpen = sqlite3DbMallocRaw(db, nIdx+2); if( aToOpen==0 ){ @@ -99088,27 +90463,27 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); + addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */ + }else if( pPk ){ + /* Construct a composite key for the row to be deleted and remember it */ + iKey = ++pParse->nMem; + nKey = 0; /* Zero tells OP_Found to use a composite key */ + sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, + sqlite3IndexAffinityStr(v, pPk), nPk); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); }else{ - if( pPk ){ - /* Add the PK key for this row to the temporary table */ - iKey = ++pParse->nMem; - nKey = 0; /* Zero tells OP_Found to use a composite key */ - sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, - sqlite3IndexAffinityStr(pParse->db, pPk), nPk); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); - }else{ - /* Add the rowid of the row to be deleted to the RowSet */ - nKey = 1; /* OP_Seek always uses a single rowid */ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); - } + /* Get the rowid of the row to be deleted and remember it in the RowSet */ + nKey = 1; /* OP_Seek always uses a single rowid */ + sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } - /* If this DELETE cannot use the ONEPASS strategy, this is the - ** end of the WHERE loop */ - if( eOnePass!=ONEPASS_OFF ){ + /* End of the WHERE loop */ + sqlite3WhereEnd(pWInfo); + if( okOnePass ){ + /* Bypass the delete logic below if the WHERE loop found zero rows */ addrBypass = sqlite3VdbeMakeLabel(v); - }else{ - sqlite3WhereEnd(pWInfo); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass); + sqlite3VdbeJumpHere(v, addrDelete); } /* Unless this is a view, open cursors for the table we are @@ -99117,26 +90492,20 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** triggers. */ if( !isView ){ - int iAddrOnce = 0; - u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); - if( eOnePass==ONEPASS_MULTI ){ - iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); - } - testcase( IsVirtual(pTab) ); - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, - aToOpen, &iDataCur, &iIdxCur); - assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); - assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); - if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen, + &iDataCur, &iIdxCur); + assert( pPk || iDataCur==iTabCur ); + assert( pPk || iIdxCur==iDataCur+1 ); } /* Set up a loop over the rowids/primary-keys that were found in the ** where-clause loop above. */ - if( eOnePass!=ONEPASS_OFF ){ - assert( nKey==nPk ); /* OP_Found will use an unpacked key */ - if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ - assert( pPk!=0 || pTab->pSelect!=0 ); + if( okOnePass ){ + /* Just one row. Hence the top-of-loop is a no-op */ + assert( nKey==nPk ); /* OP_Found will use an unpacked key */ + if( aToOpen[iDataCur-iTabCur] ){ + assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } @@ -99157,32 +90526,23 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, OE_Abort); - assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; - } }else #endif { int count = (pParse->nested==0); /* True to count changes */ - int iIdxNoSeek = -1; - if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){ - iIdxNoSeek = aiCurOnePass[1]; - } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek); + iKey, nKey, count, OE_Default, okOnePass); } /* End of the loop over all rowids/primary-keys. */ - if( eOnePass!=ONEPASS_OFF ){ + if( okOnePass ){ sqlite3VdbeResolveLabel(v, addrBypass); - sqlite3WhereEnd(pWInfo); }else if( pPk ){ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ - sqlite3VdbeGoto(v, addrLoop); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); } @@ -99221,7 +90581,7 @@ delete_from_cleanup: return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file +** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView @@ -99249,25 +90609,6 @@ delete_from_cleanup: ** sequence of nPk memory cells starting at iPk. If nPk==0 that means ** that a search record formed from OP_MakeRecord is contained in the ** single memory location iPk. -** -** eMode: -** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or -** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor -** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF -** then this function must seek iDataCur to the entry identified by iPk -** and nPk before reading from it. -** -** If eMode is ONEPASS_MULTI, then this call is being made as part -** of a ONEPASS delete that affects multiple rows. In this case, if -** iIdxNoSeek is a valid cursor number (>=0), then its position should -** be preserved following the delete operation. Or, if iIdxNoSeek is not -** a valid cursor number, the position of iDataCur should be preserved -** instead. -** -** iIdxNoSeek: -** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an -** index cursor (from within array of cursors starting at iIdxCur) that -** already points to the index entry to be deleted. */ SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse *pParse, /* Parsing context */ @@ -99279,8 +90620,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( i16 nPk, /* Number of PRIMARY KEY memory cells */ u8 count, /* If non-zero, increment the row change counter */ u8 onconf, /* Default ON CONFLICT policy for triggers */ - u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */ - int iIdxNoSeek /* Cursor number of cursor that does not need seeking */ + u8 bNoSeek /* iDataCur is already pointing to the row to delete */ ){ Vdbe *v = pParse->pVdbe; /* Vdbe */ int iOld = 0; /* First register in OLD.* array */ @@ -99297,7 +90637,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - if( eMode==ONEPASS_OFF ){ + if( !bNoSeek ){ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); VdbeCoverageIf(v, opSeek==OP_NotExists); VdbeCoverageIf(v, opSeek==OP_NotFound); @@ -99357,15 +90697,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). */ if( pTab->pSelect==0 ){ - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); + sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); if( count ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); } - if( iIdxNoSeek>=0 ){ - sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); - } - sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); } /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to @@ -99408,8 +90744,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( Table *pTab, /* Table containing the row to be deleted */ int iDataCur, /* Cursor of table holding data. */ int iIdxCur, /* First index cursor */ - int *aRegIdx, /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ - int iIdxNoSeek /* Do not delete from this cursor */ + int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ ){ int i; /* Index loop counter */ int r1 = -1; /* Register holding an index key */ @@ -99425,12 +90760,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( assert( iIdxCur+i!=iDataCur || pPk==pIdx ); if( aRegIdx!=0 && aRegIdx[i]==0 ) continue; if( pIdx==pPk ) continue; - if( iIdxCur+i==iIdxNoSeek ) continue; VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, - &iPartIdxLabel, pPrior, r1); + &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, - pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); + pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); pPrior = pIdx; } @@ -99479,16 +90813,17 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( ){ Vdbe *v = pParse->pVdbe; int j; + Table *pTab = pIdx->pTable; int regBase; int nCol; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); - pParse->iSelfTab = iDataCur; + pParse->iPartIdxTab = iDataCur; sqlite3ExprCachePush(pParse); - sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, - SQLITE_JUMPIFNULL); + sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, + SQLITE_JUMPIFNULL); }else{ *piPartIdxLabel = 0; } @@ -99497,14 +90832,9 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( regBase = sqlite3GetTempRange(pParse, nCol); if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; for(j=0; jaiColumn[j]==pIdx->aiColumn[j] - && pPrior->aiColumn[j]!=XN_EXPR - ){ - /* This column was already computed by the previous index */ - continue; - } - sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); + if( pPrior && pPrior->aiColumn[j]==pIdx->aiColumn[j] ) continue; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pIdx->aiColumn[j], + regBase+j); /* If the column affinity is REAL but the number is an integer, then it ** might be stored in the table as an integer (using a compact ** representation) then converted to REAL by an OP_RealAffinity opcode. @@ -99545,25 +90875,21 @@ SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** This file contains the C-language implementations for many of the SQL -** functions of SQLite. (Some function, and in particular the date and -** time functions, are implemented separately.) +** This file contains the C functions that implement various SQL +** functions of SQLite. +** +** There is only one exported symbol in this file - the function +** sqliteRegisterBuildinFunctions() found at the bottom of the file. +** All other code has file scope. */ -/* #include "sqliteInt.h" */ /* #include */ /* #include */ -/* #include "vdbeInt.h" */ /* ** Return the collating function associated with a function. */ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ - VdbeOp *pOp; - assert( context->pVdbe!=0 ); - pOp = &context->pVdbe->aOp[context->iOp-1]; - assert( pOp->opcode==OP_CollSeq ); - assert( pOp->p4type==P4_COLLSEQ ); - return pOp->p4.pColl; + return context->pColl; } /* @@ -99695,8 +91021,8 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ default: { /* Because sqlite3_value_double() returns 0.0 if the argument is not ** something that can be converted into a number, we have: - ** IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob - ** that cannot be converted to a numeric value. + ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that + ** cannot be converted to a numeric value. */ double rVal = sqlite3_value_double(argv[0]); if( rVal<0 ) rVal = -rVal; @@ -99768,13 +91094,13 @@ static void printfFunc( StrAccum str; const char *zFormat; int n; - sqlite3 *db = sqlite3_context_db_handle(context); if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ x.nArg = argc-1; x.nUsed = 0; x.apArg = argv+1; - sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH); + str.db = sqlite3_context_db_handle(context); sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, @@ -99829,14 +91155,6 @@ static void substrFunc( } } } -#ifdef SQLITE_SUBSTR_COMPATIBILITY - /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as - ** as substr(X,1,N) - it returns the first N characters of X. This - ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] - ** from 2009-02-02 for compatibility of applications that exploited the - ** old buggy behavior. */ - if( p1==0 ) p1 = 1; /* */ -#endif if( argc==3 ){ p2 = sqlite3_value_int(argv[2]); if( p2<0 ){ @@ -99874,14 +91192,13 @@ static void substrFunc( for(z2=z; *z2 && p2; p2--){ SQLITE_SKIP_UTF8(z2); } - sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT, - SQLITE_UTF8); + sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT); }else{ if( p1+p2>len ){ p2 = len-p1; if( p2<0 ) p2 = 0; } - sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT); + sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT); } } @@ -99924,7 +91241,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ #endif /* -** Allocate nByte bytes of space using sqlite3Malloc(). If the +** Allocate nByte bytes of space using sqlite3_malloc(). If the ** allocation fails, call sqlite3_result_error_nomem() to notify ** the database handle that malloc() has failed and return NULL. ** If nByte is larger than the maximum string or blob length, then @@ -99940,7 +91257,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){ sqlite3_result_error_toobig(context); z = 0; }else{ - z = sqlite3Malloc(nByte); + z = sqlite3Malloc((int)nByte); if( !z ){ sqlite3_result_error_nomem(context); } @@ -100111,15 +91428,15 @@ struct compareInfo { /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every -** character is exactly one byte in size. Also, provde the Utf8Read() -** macro for fast reading of the next character in the common case where -** the next character is ASCII. +** character is exactly one byte in size. Also, all characters are +** able to participate in upper-case-to-lower-case mappings in EBCDIC +** whereas only characters less than 0x80 do in ASCII. */ #if defined(SQLITE_EBCDIC) -# define sqlite3Utf8Read(A) (*((*A)++)) -# define Utf8Read(A) (*(A++)) +# define sqlite3Utf8Read(A) (*((*A)++)) +# define GlobUpperToLower(A) A = sqlite3UpperToLower[A] #else -# define Utf8Read(A) (A[0]<0x80?*(A++):sqlite3Utf8Read(&A)) +# define GlobUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; } #endif static const struct compareInfo globInfo = { '*', '?', '[', 0 }; @@ -100132,7 +91449,7 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; /* ** Compare two UTF-8 strings for equality where the first string can -** potentially be a "glob" or "like" expression. Return true (1) if they +** potentially be a "glob" expression. Return true (1) if they ** are the same and false (0) if they are different. ** ** Globbing rules: @@ -100152,18 +91469,11 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; ** "[a-z]" matches any single lower-case letter. To match a '-', make ** it the last character in the list. ** -** Like matching rules: -** -** '%' Matches any sequence of zero or more characters -** -*** '_' Matches any one character -** -** Ec Where E is the "esc" character and c is any other -** character, including '%', '_', and esc, match exactly c. -** -** The comments within this routine usually assume glob matching. -** ** This routine is usually quick, but can be N**2 in the worst case. +** +** Hints: to match '*' or '?', put them in "[]". Like this: +** +** abc[*]xyz Matches "abc*xyz" only */ static int patternCompare( const u8 *zPattern, /* The glob pattern */ @@ -100171,123 +91481,104 @@ static int patternCompare( const struct compareInfo *pInfo, /* Information about how to do the compare */ u32 esc /* The escape character */ ){ - u32 c, c2; /* Next pattern and input string chars */ - u32 matchOne = pInfo->matchOne; /* "?" or "_" */ - u32 matchAll = pInfo->matchAll; /* "*" or "%" */ - u32 matchOther; /* "[" or the escape character */ - u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ - const u8 *zEscaped = 0; /* One past the last escaped input char */ - - /* The GLOB operator does not have an ESCAPE clause. And LIKE does not - ** have the matchSet operator. So we either have to look for one or - ** the other, never both. Hence the single variable matchOther is used - ** to store the one we have to look for. - */ - matchOther = esc ? esc : pInfo->matchSet; + u32 c, c2; + int invert; + int seen; + u8 matchOne = pInfo->matchOne; + u8 matchAll = pInfo->matchAll; + u8 matchSet = pInfo->matchSet; + u8 noCase = pInfo->noCase; + int prevEscape = 0; /* True if the previous character was 'escape' */ - while( (c = Utf8Read(zPattern))!=0 ){ - if( c==matchAll ){ /* Match "*" */ - /* Skip over multiple "*" characters in the pattern. If there - ** are also "?" characters, skip those as well, but consume a - ** single character of the input string for each "?" skipped */ - while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ + while( (c = sqlite3Utf8Read(&zPattern))!=0 ){ + if( c==matchAll && !prevEscape ){ + while( (c=sqlite3Utf8Read(&zPattern)) == matchAll + || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ return 0; } } if( c==0 ){ - return 1; /* "*" at the end of the pattern matches */ - }else if( c==matchOther ){ - if( esc ){ - c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; - }else{ - /* "[...]" immediately follows the "*". We have to do a slow - ** recursive search in this case, but it is an unusual case. */ - assert( matchOther<0x80 ); /* '[' is a single-byte character */ - while( *zString - && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ - SQLITE_SKIP_UTF8(zString); - } - return *zString!=0; - } - } - - /* At this point variable c contains the first character of the - ** pattern string past the "*". Search in the input string for the - ** first matching character and recursively contine the match from - ** that point. - ** - ** For a case-insensitive search, set variable cx to be the same as - ** c but in the other case and search the input string for either - ** c or cx. - */ - if( c<=0x80 ){ - u32 cx; - if( noCase ){ - cx = sqlite3Toupper(c); - c = sqlite3Tolower(c); - }else{ - cx = c; - } - while( (c2 = *(zString++))!=0 ){ - if( c2!=c && c2!=cx ) continue; - if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; - } - }else{ - while( (c2 = Utf8Read(zString))!=0 ){ - if( c2!=c ) continue; - if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; - } - } - return 0; - } - if( c==matchOther ){ - if( esc ){ + return 1; + }else if( c==esc ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; - zEscaped = zPattern; - }else{ - u32 prior_c = 0; - int seen = 0; - int invert = 0; - c = sqlite3Utf8Read(&zString); - if( c==0 ) return 0; - c2 = sqlite3Utf8Read(&zPattern); - if( c2=='^' ){ - invert = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - while( c2 && c2!=']' ){ - if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ - c2 = sqlite3Utf8Read(&zPattern); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else{ - if( c==c2 ){ - seen = 1; - } - prior_c = c2; - } - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==0 || (seen ^ invert)==0 ){ + if( c==0 ){ return 0; } - continue; + }else if( c==matchSet ){ + assert( esc==0 ); /* This is GLOB, not LIKE */ + assert( matchSet<0x80 ); /* '[' is a single-byte character */ + while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ + SQLITE_SKIP_UTF8(zString); + } + return *zString!=0; } + while( (c2 = sqlite3Utf8Read(&zString))!=0 ){ + if( noCase ){ + GlobUpperToLower(c2); + GlobUpperToLower(c); + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(&zString); + GlobUpperToLower(c2); + } + }else{ + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(&zString); + } + } + if( c2==0 ) return 0; + if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; + } + return 0; + }else if( c==matchOne && !prevEscape ){ + if( sqlite3Utf8Read(&zString)==0 ){ + return 0; + } + }else if( c==matchSet ){ + u32 prior_c = 0; + assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ + seen = 0; + invert = 0; + c = sqlite3Utf8Read(&zString); + if( c==0 ) return 0; + c2 = sqlite3Utf8Read(&zPattern); + if( c2=='^' ){ + invert = 1; + c2 = sqlite3Utf8Read(&zPattern); + } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = sqlite3Utf8Read(&zPattern); + } + while( c2 && c2!=']' ){ + if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ + c2 = sqlite3Utf8Read(&zPattern); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else{ + if( c==c2 ){ + seen = 1; + } + prior_c = c2; + } + c2 = sqlite3Utf8Read(&zPattern); + } + if( c2==0 || (seen ^ invert)==0 ){ + return 0; + } + }else if( esc==c && !prevEscape ){ + prevEscape = 1; + }else{ + c2 = sqlite3Utf8Read(&zString); + if( noCase ){ + GlobUpperToLower(c); + GlobUpperToLower(c2); + } + if( c!=c2 ){ + return 0; + } + prevEscape = 0; } - c2 = Utf8Read(zString); - if( c==c2 ) continue; - if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){ - continue; - } - if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; - return 0; } return *zString==0; } @@ -100295,17 +91586,10 @@ static int patternCompare( /* ** The sqlite3_strglob() interface. */ -SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){ +SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0; } -/* -** The sqlite3_strlike() interface. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0; -} - /* ** Count the number of times that the LIKE operator (or GLOB which is ** just a variation of LIKE) gets called. This is used for testing @@ -100338,17 +91622,6 @@ static void likeFunc( int nPat; sqlite3 *db = sqlite3_context_db_handle(context); -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( sqlite3_value_type(argv[0])==SQLITE_BLOB - || sqlite3_value_type(argv[1])==SQLITE_BLOB - ){ -#ifdef SQLITE_TEST - sqlite3_like_count++; -#endif - sqlite3_result_int(context, 0); - return; - } -#endif zB = sqlite3_value_text(argv[0]); zA = sqlite3_value_text(argv[1]); @@ -100608,7 +91881,7 @@ static void charFunc( ){ unsigned char *z, *zOut; int i; - zOut = z = sqlite3_malloc64( argc*4+1 ); + zOut = z = sqlite3_malloc( argc*4+1 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; @@ -100635,7 +91908,7 @@ static void charFunc( *zOut++ = 0x80 + (u8)(c & 0x3F); } \ } - sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); + sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free); } /* @@ -100676,14 +91949,16 @@ static void zeroblobFunc( sqlite3_value **argv ){ i64 n; - int rc; + sqlite3 *db = sqlite3_context_db_handle(context); assert( argc==1 ); UNUSED_PARAMETER(argc); n = sqlite3_value_int64(argv[0]); - if( n<0 ) n = 0; - rc = sqlite3_result_zeroblob64(context, n); /* IMP: R-00293-64994 */ - if( rc ){ - sqlite3_result_error_code(context, rc); + testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); + testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); + if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + }else{ + sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ } } @@ -100754,7 +92029,7 @@ static void replaceFunc( return; } zOld = zOut; - zOut = sqlite3_realloc64(zOut, (int)nOut); + zOut = sqlite3_realloc(zOut, (int)nOut); if( zOut==0 ){ sqlite3_result_error_nomem(context); sqlite3_free(zOld); @@ -101083,7 +92358,6 @@ static void minmaxStep( sqlite3SkipAccumulatorLoad(context); } }else{ - pBest->db = sqlite3_context_db_handle(context); sqlite3VdbeMemCopy(pBest, pArg); } } @@ -101116,7 +92390,8 @@ static void groupConcatStep( if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pAccum->mxAlloc==0; + int firstTerm = pAccum->useMalloc==0; + pAccum->useMalloc = 2; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( !firstTerm ){ if( argc==2 ){ @@ -101200,11 +92475,6 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) ** then set aWc[0] through aWc[2] to the wildcard characters and ** return TRUE. If the function is not a LIKE-style function then ** return FALSE. -** -** *pIsNocase is set to true if uppercase and lowercase are equivalent for -** the function (default for LIKE). If the function makes the distinction -** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to -** false. */ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; @@ -101235,7 +92505,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas } /* -** All of the FuncDef structures in the aBuiltinFunc[] array above +** All all of the FuncDef structures in the aBuiltinFunc[] array above ** to the global function hash table. This occurs at start-time (as ** a consequence of calling sqlite3_initialize()). ** @@ -101259,12 +92529,10 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), - AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize, - SQLITE_FUNC_MINMAX ), + AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), - AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, - SQLITE_FUNC_MINMAX ), + AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), @@ -101287,19 +92555,15 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), - DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), - DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), + FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), + FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), -#if SQLITE_USER_AUTHENTICATION - FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ), -#endif #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), - DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), + FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), + FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ FUNCTION(quote, 1, 0, 0, quoteFunc ), VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), @@ -101311,14 +92575,14 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ FUNCTION(soundex, 1, 0, 0, soundexFunc ), #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION - VFUNCTION(load_extension, 1, 0, 0, loadExt ), - VFUNCTION(load_extension, 2, 0, 0, loadExt ), + FUNCTION(load_extension, 1, 0, 0, loadExt ), + FUNCTION(load_extension, 2, 0, 0, loadExt ), #endif AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), - AGGREGATE2(count, 0, 0, 0, countStep, countFinalize, - SQLITE_FUNC_COUNT ), + /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ + {0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), @@ -101364,7 +92628,6 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ ** This file contains code used by the compiler to add foreign key ** support to compiled SQL statements. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER @@ -101526,7 +92789,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ ** ** 4) No parent key columns were provided explicitly as part of the ** foreign key definition, and the PRIMARY KEY of the parent table -** consists of a different number of columns to the child key in +** consists of a a different number of columns to the child key in ** the child table. ** ** then non-zero is returned, and a "foreign key mismatch" error loaded @@ -101578,7 +92841,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex( } for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ + if( pIdx->nKeyCol==nCol && pIdx->onError!=OE_None ){ /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number ** of columns. If each indexed column corresponds to a foreign key ** column of pFKey, then this index is a winner. */ @@ -101602,16 +92865,16 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex( int i, j; for(i=0; iaiColumn[i]; /* Index of column in parent tbl */ - const char *zDfltColl; /* Def. collation for column */ + char *zDfltColl; /* Def. collation for column */ char *zIdxCol; /* Name of indexed column */ - if( iCol<0 ) break; /* No foreign keys against expression indexes */ - /* If the index uses a collation sequence that is different from ** the default collation sequence for the column, this index is ** unusable. Bail out early in this case. */ zDfltColl = pParent->aCol[iCol].zColl; - if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; + if( !zDfltColl ){ + zDfltColl = "BINARY"; + } if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; zIdxCol = pParent->aCol[iCol].zName; @@ -101727,7 +92990,7 @@ static void fkLookupParent( sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); - sqlite3VdbeGoto(v, iOk); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, iMustBeInt); sqlite3ReleaseTempReg(pParse, regTemp); @@ -101757,7 +93020,6 @@ static void fkLookupParent( for(i=0; iaiColumn[i]+1+regData; - assert( pIdx->aiColumn[i]>=0 ); assert( aiCol[i]!=pTab->iPKey ); if( pIdx->aiColumn[i]==pTab->iPKey ){ /* The parent key is a composite key that includes the IPK column */ @@ -101766,11 +93028,11 @@ static void fkLookupParent( sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } - sqlite3VdbeGoto(v, iOk); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); } sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, - sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); + sqlite3IndexAffinityStr(v,pIdx), nCol); sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, regRec); @@ -101791,7 +93053,7 @@ static void fkLookupParent( OE_Abort, 0, P4_STATIC, P5_ConstraintFK); }else{ if( nIncr>0 && pFKey->isDeferred==0 ){ - sqlite3MayAbort(pParse); + sqlite3ParseToplevel(pParse)->mayAbort = 1; } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); } @@ -101863,10 +93125,6 @@ static Expr *exprTableColumn( ** code for an SQL UPDATE operation, this function may be called twice - ** once to "delete" the old row and once to "insert" the new row. ** -** Parameter nIncr is passed -1 when inserting a row (as this may decrease -** the number of FK violations in the db) or +1 when deleting one (as this -** may increase the number of FK constraint problems). -** ** The code generated by this function scans through the rows in the child ** table that correspond to the parent table row being deleted or inserted. ** For each child row found, one of the following actions is taken: @@ -101966,7 +93224,6 @@ static void fkScanChildren( assert( pIdx!=0 ); for(i=0; inKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; - assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); @@ -101984,9 +93241,13 @@ static void fkScanChildren( sqlite3ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE - ** clause. For each row found, increment either the deferred or immediate - ** foreign key constraint counter. */ + ** clause. If the constraint is not deferred, throw an exception for + ** each row found. Otherwise, for deferred constraints, increment the + ** deferred constraint counter by nIncr for each row selected. */ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); + if( nIncr>0 && pFKey->isDeferred==0 ){ + sqlite3ParseToplevel(pParse)->mayAbort = 1; + } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); if( pWInfo ){ sqlite3WhereEnd(pWInfo); @@ -102014,7 +93275,8 @@ static void fkScanChildren( ** table). */ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ - return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); + int nName = sqlite3Strlen30(pTab->zName); + return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); } /* @@ -102165,24 +93427,6 @@ static int fkParentIsModified( return 0; } -/* -** Return true if the parser passed as the first argument is being -** used to code a trigger that is really a "SET NULL" action belonging -** to trigger pFKey. -*/ -static int isSetNullAction(Parse *pParse, FKey *pFKey){ - Parse *pTop = sqlite3ParseToplevel(pParse); - if( pTop->pTriggerPrg ){ - Trigger *p = pTop->pTriggerPrg->pTrigger; - if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) - || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) - ){ - return 1; - } - } - return 0; -} - /* ** This function is called when inserting, deleting or updating a row of ** table pTab to generate VDBE code to perform foreign key constraint @@ -102235,7 +93479,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( int *aiCol; int iCol; int i; - int bIgnore = 0; + int isIgnore = 0; if( aChange && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 @@ -102286,7 +93530,6 @@ SQLITE_PRIVATE void sqlite3FkCheck( if( aiCol[i]==pTab->iPKey ){ aiCol[i] = -1; } - assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Request permission to read the parent key columns. If the ** authorization callback returns SQLITE_IGNORE, behave as if any @@ -102295,7 +93538,7 @@ SQLITE_PRIVATE void sqlite3FkCheck( int rcauth; char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); - bIgnore = (rcauth==SQLITE_IGNORE); + isIgnore = (rcauth==SQLITE_IGNORE); } #endif } @@ -102310,18 +93553,12 @@ SQLITE_PRIVATE void sqlite3FkCheck( /* A row is being removed from the child table. Search for the parent. ** If the parent does not exist, removing the child row resolves an ** outstanding foreign key constraint violation. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); } - if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ + if( regNew!=0 ){ /* A row is being added to the child table. If a parent row cannot - ** be found, adding the child row has violated the FK constraint. - ** - ** If this operation is being performed as part of a trigger program - ** that is actually a "SET NULL" action belonging to this very - ** foreign key, then omit this scan altogether. As all child key - ** values are guaranteed to be NULL, it is not possible for adding - ** this row to cause an FK violation. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); + ** be found, adding the child row has violated the FK constraint. */ + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); } sqlite3DbFree(db, aiFree); @@ -102342,8 +93579,8 @@ SQLITE_PRIVATE void sqlite3FkCheck( && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); - /* Inserting a single row into a parent table cannot cause (or fix) - ** an immediate foreign key violation. So do nothing in this case. */ + /* Inserting a single row into a parent table cannot cause an immediate + ** foreign key violation. So do nothing in this case. */ continue; } @@ -102367,28 +93604,13 @@ SQLITE_PRIVATE void sqlite3FkCheck( fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); } if( regOld!=0 ){ - int eAction = pFKey->aAction[aChange!=0]; + /* If there is a RESTRICT action configured for the current operation + ** on the parent table of this FK, then throw an exception + ** immediately if the FK constraint is violated, even if this is a + ** deferred trigger. That's what RESTRICT means. To defer checking + ** the constraint, the FK should specify NO ACTION (represented + ** using OE_None). NO ACTION is the default. */ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); - /* If this is a deferred FK constraint, or a CASCADE or SET NULL - ** action applies, then any foreign key violations caused by - ** removing the parent key will be rectified by the action trigger. - ** So do not set the "may-abort" flag in this case. - ** - ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the - ** may-abort flag will eventually be set on this statement anyway - ** (when this function is called as part of processing the UPDATE - ** within the action trigger). - ** - ** Note 2: At first glance it may seem like SQLite could simply omit - ** all OP_FkCounter related scans when either CASCADE or SET NULL - ** applies. The trouble starts if the CASCADE or SET NULL action - ** trigger causes other triggers or action rules attached to the - ** child table to fire. In these cases the fk constraint counters - ** might be set incorrectly if any OP_FkCounter related scans are - ** omitted. */ - if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ - sqlite3MayAbort(pParse); - } } pItem->zName = 0; sqlite3SrcListDelete(db, pSrc); @@ -102418,10 +93640,7 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask( Index *pIdx = 0; sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); if( pIdx ){ - for(i=0; inKeyCol; i++){ - assert( pIdx->aiColumn[i]>=0 ); - mask |= COLUMN_MASK(pIdx->aiColumn[i]); - } + for(i=0; inKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); } } } @@ -102543,9 +93762,7 @@ static Trigger *fkActionTrigger( iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); - assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); - assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); - tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; + tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; tToCol.n = sqlite3Strlen30(tToCol.z); @@ -102557,10 +93774,10 @@ static Trigger *fkActionTrigger( ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) + sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) , 0), - sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) + sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) , 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); @@ -102572,12 +93789,12 @@ static Trigger *fkActionTrigger( if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), 0), sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), 0), 0); pWhen = sqlite3ExprAnd(db, pWhen, pEq); @@ -102587,8 +93804,8 @@ static Trigger *fkActionTrigger( Expr *pNew; if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) + sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), + sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) , 0); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; @@ -102635,12 +93852,13 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->zTarget */ + nFrom + 1 /* Space for pStep->target.z */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->zTarget = (char *)&pStep[1]; - memcpy((char *)pStep->zTarget, zFrom, nFrom); + pStep->target.z = (char *)&pStep[1]; + pStep->target.n = nFrom; + memcpy((char *)pStep->target.z, zFrom, nFrom); pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); @@ -102736,7 +93954,7 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ }else{ void *p = (void *)pFKey->pNextTo; const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; @@ -102776,7 +93994,6 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. */ -/* #include "sqliteInt.h" */ /* ** Generate code that will @@ -102806,7 +94023,7 @@ SQLITE_PRIVATE void sqlite3OpenTable( }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); - assert( pPk->tnum==pTab->tnum ); + assert( pPk->tnum=pTab->tnum ); sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pPk); VdbeComment((v, "%s", pTab->zName)); @@ -102820,20 +94037,20 @@ SQLITE_PRIVATE void sqlite3OpenTable( ** ** Character Column affinity ** ------------------------------ -** 'A' BLOB -** 'B' TEXT -** 'C' NUMERIC -** 'D' INTEGER -** 'F' REAL +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL ** -** An extra 'D' is appended to the end of the string to cover the +** An extra 'd' is appended to the end of the string to cover the ** rowid that appears as the last column in every index. ** ** Memory for the buffer containing the column index affinity string ** is managed along with the rest of the Index structure. It will be ** released when sqlite3DeleteIndex() is called. */ -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ +SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ /* The first time a column affinity string for a particular index is ** required, it is allocated and populated here. It is then stored as @@ -102845,6 +94062,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ */ int n; Table *pTab = pIdx->pTable; + sqlite3 *db = sqlite3VdbeDb(v); pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); if( !pIdx->zColAff ){ db->mallocFailed = 1; @@ -102852,18 +94070,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ } for(n=0; nnColumn; n++){ i16 x = pIdx->aiColumn[n]; - if( x>=0 ){ - pIdx->zColAff[n] = pTab->aCol[x].affinity; - }else if( x==XN_ROWID ){ - pIdx->zColAff[n] = SQLITE_AFF_INTEGER; - }else{ - char aff; - assert( x==XN_EXPR ); - assert( pIdx->aColExpr!=0 ); - aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); - if( aff==0 ) aff = SQLITE_AFF_BLOB; - pIdx->zColAff[n] = aff; - } + pIdx->zColAff[n] = x<0 ? SQLITE_AFF_INTEGER : pTab->aCol[x].affinity; } pIdx->zColAff[n] = 0; } @@ -102873,9 +94080,9 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ /* ** Compute the affinity string for table pTab, if it has not already been -** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. +** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. ** -** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and +** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and ** if iReg>0 then code an OP_Affinity opcode that will set the affinities ** for register iReg and following. Or if affinities exists and iReg==0, ** then just set the P4 operand of the previous opcode (which should be @@ -102885,11 +94092,11 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ ** ** Character Column affinity ** ------------------------------ -** 'A' BLOB -** 'B' TEXT -** 'C' NUMERIC -** 'D' INTEGER -** 'E' REAL +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL */ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ int i; @@ -102907,7 +94114,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ } do{ zColAff[i--] = 0; - }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); + }while( i>=0 && zColAff[i]==SQLITE_AFF_NONE ); pTab->zColAff = zColAff; } i = sqlite3Strlen30(zColAff); @@ -103024,7 +94231,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ /* This routine is never called during trigger-generation. It is ** only called from the top-level */ assert( pParse->pTriggerTab==0 ); - assert( sqlite3IsToplevel(pParse) ); + assert( pParse==sqlite3ParseToplevel(pParse) ); assert( v ); /* We failed long ago if this is not so */ for(p = pParse->pAinc; p; p = p->pNext){ @@ -103034,14 +94241,14 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); - sqlite3VdbeGoto(v, addr+9); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); sqlite3VdbeAddOp0(v, OP_Close); @@ -103077,16 +94284,16 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ assert( v ); for(p = pParse->pAinc; p; p = p->pNext){ Db *pDb = &db->aDb[p->iDb]; - int addr1; + int j1; int iRec; int memId = p->regCtr; iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); @@ -103116,23 +94323,20 @@ static int xferOptimization( /* ** This routine is called to handle SQL of the following forms: ** -** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... +** insert into TABLE (IDLIST) values(EXPRLIST) ** insert into TABLE (IDLIST) select -** insert into TABLE (IDLIST) default values ** ** The IDLIST following the table name is always optional. If omitted, -** then a list of all (non-hidden) columns for the table is substituted. -** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST -** is omitted. +** then a list of all columns for the table is substituted. The IDLIST +** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. ** -** For the pSelect parameter holds the values to be inserted for the -** first two forms shown above. A VALUES clause is really just short-hand -** for a SELECT statement that omits the FROM clause and everything else -** that follows. If the pSelect parameter is NULL, that means that the -** DEFAULT VALUES form of the INSERT statement is intended. +** The pList parameter holds EXPRLIST in the first form of the INSERT +** statement above, and pSelect is NULL. For the second form, pList is +** NULL and pSelect is a pointer to the select statement used to generate +** data for the insert. ** ** The code generated follows one of four templates. For a simple -** insert with data coming from a single-row VALUES clause, the code executes +** insert with data coming from a VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** @@ -103187,7 +94391,7 @@ static int xferOptimization( ** The 4th template is used if the insert statement takes its ** values from a SELECT but the data is being inserted into a table ** that is also read as part of the SELECT. In the third form, -** we have to use an intermediate table to store the results of +** we have to use a intermediate table to store the results of ** the select. The template is like this: ** ** X <- A @@ -103239,7 +94443,7 @@ SQLITE_PRIVATE void sqlite3Insert( u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ - u8 bIdListInOrder; /* True if IDLIST is in table order */ + u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ @@ -103264,8 +94468,8 @@ SQLITE_PRIVATE void sqlite3Insert( } /* If the Select object is really just a simple VALUES() list with a - ** single row (the common case) then keep that one row of values - ** and discard the other (unused) parts of the pSelect object + ** single row values (the common case) then keep that one row of values + ** and go ahead and discard the Select object */ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ pList = pSelect->pEList; @@ -103352,7 +94556,7 @@ SQLITE_PRIVATE void sqlite3Insert( regAutoinc = autoIncBegin(pParse, iDb, pTab); /* Allocate registers for holding the rowid of the new row, - ** the content of the new row, and the assembled row record. + ** the content of the new row, and the assemblied row record. */ regRowid = regIns = pParse->nMem+1; pParse->nMem += pTab->nCol + 1; @@ -103373,7 +94577,6 @@ SQLITE_PRIVATE void sqlite3Insert( ** is appears in the original table. (The index of the INTEGER ** PRIMARY KEY in the original table is pTab->iPKey.) */ - bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; if( pColumn ){ for(i=0; inId; i++){ pColumn->a[i].idx = -1; @@ -103409,8 +94612,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ - /* Data is coming from a SELECT or from a multi-row VALUES clause. - ** Generate a co-routine to run the SELECT. */ + /* Data is coming from a SELECT. 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 */ @@ -103423,7 +94625,8 @@ SQLITE_PRIVATE void sqlite3Insert( dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; - if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; + assert( pParse->nErr==0 || rc ); + if( rc || db->mallocFailed ) goto insert_cleanup; sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); @@ -103465,27 +94668,25 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeGoto(v, addrL); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL); sqlite3VdbeJumpHere(v, addrL); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ - /* This is the case if the data for the INSERT is coming from a - ** single-row VALUES clause + /* This is the case if the data for the INSERT is coming from a VALUES + ** clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; srcTab = -1; assert( useTempTable==0 ); - if( pList ){ - nColumn = pList->nExpr; - if( sqlite3ResolveExprListNames(&sNC, pList) ){ + nColumn = pList ? pList->nExpr : 0; + for(i=0; ia[i].pExpr) ){ goto insert_cleanup; } - }else{ - nColumn = 0; } } @@ -103500,8 +94701,10 @@ SQLITE_PRIVATE void sqlite3Insert( /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ - for(i=0; inCol; i++){ - nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + if( IsVirtual(pTab) ){ + for(i=0; inCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + } } if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ sqlite3ErrorMsg(pParse, @@ -103524,7 +94727,7 @@ SQLITE_PRIVATE void sqlite3Insert( /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; - nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, + nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0, &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ @@ -103576,7 +94779,7 @@ SQLITE_PRIVATE void sqlite3Insert( if( ipkColumn<0 ){ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); }else{ - int addr1; + int j1; assert( !withoutRowid ); if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols); @@ -103584,9 +94787,9 @@ SQLITE_PRIVATE void sqlite3Insert( assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); } - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } @@ -103597,14 +94800,15 @@ SQLITE_PRIVATE void sqlite3Insert( /* Create the new column data */ - for(i=j=0; inCol; i++){ - if( pColumn ){ + for(i=0; inCol; i++){ + if( pColumn==0 ){ + j = i; + }else{ for(j=0; jnId; j++){ if( pColumn->a[j].idx==i ) break; } } - if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) - || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){ + if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); @@ -103612,7 +94816,6 @@ SQLITE_PRIVATE void sqlite3Insert( assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); } - if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++; } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, @@ -103660,14 +94863,14 @@ SQLITE_PRIVATE void sqlite3Insert( ** to generate a unique primary key value. */ if( !appendFlag ){ - int addr1; + int j1; if( !IsVirtual(pTab) ){ - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); }else{ - addr1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v); + j1 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v); } sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v); } @@ -103696,6 +94899,7 @@ SQLITE_PRIVATE void sqlite3Insert( } if( pColumn==0 ){ if( IsHiddenColumn(&pTab->aCol[i]) ){ + assert( IsVirtual(pTab) ); j = -1; nHidden++; }else{ @@ -103763,7 +94967,7 @@ SQLITE_PRIVATE void sqlite3Insert( sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ - sqlite3VdbeGoto(v, addrCont); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } @@ -103804,7 +95008,7 @@ insert_cleanup: } /* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file +** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView @@ -103920,7 +95124,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int ix; /* Index loop counter */ int nCol; /* Number of columns */ int onError; /* Conflict resolution strategy */ - int addr1; /* Address of jump instruction */ + int j1; /* Addresss of jump instruction */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ int ipkTop = 0; /* Top of the rowid change constraint check */ @@ -103991,10 +95195,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } default: { assert( onError==OE_Replace ); - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); - VdbeCoverage(v); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v); sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); break; } } @@ -104011,7 +95214,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int allOk = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ - sqlite3VdbeGoto(v, ignoreDest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); }else{ char *zName = pCheck->a[i].zName; if( zName==0 ) zName = pTab->zName; @@ -104109,20 +95312,17 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regNewData, 1, 0, OE_Replace, - ONEPASS_SINGLE, -1); - }else{ - if( pTab->pIndex ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); - } + regNewData, 1, 0, OE_Replace, 1); + }else if( pTab->pIndex ){ + sqlite3MultiWrite(pParse); + sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0); } seenReplace = 1; break; } case OE_Ignore: { /*assert( seenReplace==0 );*/ - sqlite3VdbeGoto(v, ignoreDest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; } } @@ -104158,8 +95358,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); pParse->ckBase = regNewData+1; - sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, - SQLITE_JUMPIFNULL); + sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk, + SQLITE_JUMPIFNULL); pParse->ckBase = 0; } @@ -104170,22 +95370,15 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( for(i=0; inColumn; i++){ int iField = pIdx->aiColumn[i]; int x; - if( iField==XN_EXPR ){ - pParse->ckBase = regNewData+1; - sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); - pParse->ckBase = 0; - VdbeComment((v, "%s column %d", pIdx->zName, i)); + if( iField<0 || iField==pTab->iPKey ){ + if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ + x = regNewData; + regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; }else{ - if( iField==XN_ROWID || iField==pTab->iPKey ){ - if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ - x = regNewData; - regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; - }else{ - x = iField + regNewData + 1; - } - sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i); - VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); + x = iField + regNewData + 1; } + sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i); + VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); @@ -104235,7 +95428,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( ** store it in registers regR..regR+nPk-1 */ if( pIdx!=pPk ){ for(i=0; inKeyCol; i++){ - assert( pPk->aiColumn[i]>=0 ); x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); VdbeComment((v, "%s.%s", pTab->zName, @@ -104257,7 +95449,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( for(i=0; inKeyCol; i++){ char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); x = pPk->aiColumn[i]; - assert( x>=0 ); if( i==(pPk->nKeyCol-1) ){ addrJump = addrUniqueOk; op = OP_Eq; @@ -104284,7 +95475,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( break; } case OE_Ignore: { - sqlite3VdbeGoto(v, ignoreDest); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; } default: { @@ -104295,8 +95486,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - regR, nPkField, 0, OE_Replace, - (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1); + regR, nPkField, 0, OE_Replace, pIdx==pPk); seenReplace = 1; break; } @@ -104306,7 +95496,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ - sqlite3VdbeGoto(v, ipkTop+1); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ipkTop+1); sqlite3VdbeJumpHere(v, ipkBottom); } @@ -104338,7 +95528,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( Index *pIdx; /* An index being inserted or updated */ u8 pik_flags; /* flag values passed to the btree insert */ int regData; /* Content registers (after the rowid) */ - int regRec; /* Register holding assembled record for the table */ + int regRec; /* Register holding assemblied record for the table */ int i; /* Loop counter */ u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ @@ -104403,15 +95593,11 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( ** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range ** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the ** pTab->pIndex list. -** -** If pTab is a virtual table, then this routine is a no-op and the -** *piDataCur and *piIdxCur values are left uninitialized. */ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int op, /* OP_OpenRead or OP_OpenWrite */ - u8 p5, /* P5 value for OP_Open* instructions */ int iBase, /* Use this for the table cursor, if there is one */ u8 *aToOpen, /* If not NULL: boolean for each table and index */ int *piDataCur, /* Write the database source cursor number here */ @@ -104424,11 +95610,10 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( Vdbe *v; assert( op==OP_OpenRead || op==OP_OpenWrite ); - assert( op==OP_OpenWrite || p5==0 ); if( IsVirtual(pTab) ){ - /* This routine is a no-op for virtual tables. Leave the output - ** variables *piDataCur and *piIdxCur uninitialized so that valgrind - ** can detect if they are used by mistake in the caller. */ + assert( aToOpen==0 ); + *piDataCur = 0; + *piIdxCur = 1; return 0; } iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); @@ -104452,7 +95637,6 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( if( aToOpen==0 || aToOpen[i+1] ){ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - sqlite3VdbeChangeP5(v, p5); VdbeComment((v, "%s", pIdx->zName)); } } @@ -104466,13 +95650,27 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( ** The following global variable is incremented whenever the ** transfer optimization is used. This is used for testing ** purposes only - to make sure the transfer optimization really -** is happening when it is supposed to. +** is happening when it is suppose to. */ SQLITE_API int sqlite3_xferopt_count; #endif /* SQLITE_TEST */ #ifndef SQLITE_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite3StrICmp(z1, z2)==0; +} + + /* ** Check to see if index pSrc is compatible as a source of data ** for index pDest in an insert transfer optimization. The rules @@ -104498,17 +95696,10 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ return 0; /* Different columns indexed */ } - if( pSrc->aiColumn[i]==XN_EXPR ){ - assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); - if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, - pDest->aColExpr->a[i].pExpr, -1)!=0 ){ - return 0; /* Different expressions in the index */ - } - } if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ return 0; /* Different sort orders */ } - if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){ + if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){ return 0; /* Different collating sequences */ } } @@ -104526,7 +95717,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ ** INSERT INTO tab1 SELECT * FROM tab2; ** ** The xfer optimization transfers raw records from tab2 over to tab1. -** Columns are not decoded and reassembled, which greatly improves +** Columns are not decoded and reassemblied, which greatly improves ** performance. Raw index records are transferred in the same way. ** ** The xfer optimization is only attempted if tab1 and tab2 are compatible. @@ -104552,7 +95743,6 @@ static int xferOptimization( int onError, /* How to handle constraint errors */ int iDbDest /* The database of pDest */ ){ - sqlite3 *db = pParse->db; ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ @@ -104623,7 +95813,7 @@ static int xferOptimization( return 0; /* The result set must have exactly one column */ } assert( pEList->a[0].pExpr ); - if( pEList->a[0].pExpr->op!=TK_ASTERISK ){ + if( pEList->a[0].pExpr->op!=TK_ALL ){ return 0; /* The result set must be the special operator "*" */ } @@ -104659,17 +95849,10 @@ static int xferOptimization( for(i=0; inCol; i++){ Column *pDestCol = &pDest->aCol[i]; Column *pSrcCol = &pSrc->aCol[i]; -#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS - if( (db->flags & SQLITE_Vacuum)==0 - && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN - ){ - return 0; /* Neither table may have __hidden__ columns */ - } -#endif if( pDestCol->affinity!=pSrcCol->affinity ){ return 0; /* Affinity must be the same on all columns */ } - if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){ + if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDestCol->notNull && !pSrcCol->notNull ){ @@ -104684,7 +95867,7 @@ static int xferOptimization( } } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - if( IsUniqueIndex(pDestIdx) ){ + if( pDestIdx->onError!=OE_None ){ destHasUniqueIdx = 1; } for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ @@ -104707,11 +95890,11 @@ static int xferOptimization( ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ + if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ return 0; } #endif - if( (db->flags & SQLITE_CountRows)!=0 ){ + if( (pParse->db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ } @@ -104722,7 +95905,7 @@ static int xferOptimization( #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif - iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); + iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; @@ -104732,18 +95915,14 @@ static int xferOptimization( regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (db->flags & SQLITE_Vacuum)==0 && ( - (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ || destHasUniqueIdx /* (2) */ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - )){ + ){ /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. Unless the - ** SQLITE_Vacuum flag is set, this block generates code to make - ** that determination. If SQLITE_Vacuum is set, then the destination - ** table is always empty. - ** - ** Conditions under which the destination must be empty: + ** only if the destination table is initially empty. This code makes + ** that determination. Conditions under which the destination must + ** be empty: ** ** (1) There is no INTEGER PRIMARY KEY but there are indices. ** (If the destination is not initially empty, the rowid fields @@ -104755,7 +95934,7 @@ static int xferOptimization( ** (3) onError is something other than OE_Abort and OE_Rollback. */ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); - emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); + emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ @@ -104786,7 +95965,6 @@ static int xferOptimization( sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - u8 idxInsFlags = 0; for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } @@ -104800,37 +95978,7 @@ static int xferOptimization( VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); - if( db->flags & SQLITE_Vacuum ){ - /* This INSERT command is part of a VACUUM operation, which guarantees - ** that the destination table is empty. If all indexed columns use - ** collation sequence BINARY, then it can also be assumed that the - ** index will be populated by inserting keys in strictly sorted - ** order. In this case, instead of seeking within the b-tree as part - ** of every OP_IdxInsert opcode, an OP_Last is added before the - ** OP_IdxInsert to seek to the point within the b-tree where each key - ** should be inserted. This is faster. - ** - ** If any of the indexed columns use a collation sequence other than - ** BINARY, this optimization is disabled. This is because the user - ** might change the definition of a collation sequence and then run - ** a VACUUM command. In that case keys may not be written in strictly - ** sorted order. */ - for(i=0; inColumn; i++){ - const char *zColl = pSrcIdx->azColl[i]; - assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0 - || sqlite3StrBINARY==zColl ); - if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break; - } - if( i==pSrcIdx->nColumn ){ - idxInsFlags = OPFLAG_USESEEKRESULT; - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); - } - } - if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ - idxInsFlags |= OPFLAG_NCHANGE; - } sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); - sqlite3VdbeChangeP5(v, idxInsFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); @@ -104869,7 +96017,6 @@ static int xferOptimization( ** accessed by users of the library. */ -/* #include "sqliteInt.h" */ /* ** Execute SQL code. Return one of the SQLITE_ success/failure @@ -104881,7 +96028,7 @@ static int xferOptimization( ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ -SQLITE_API int SQLITE_STDCALL sqlite3_exec( +SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ @@ -104898,7 +96045,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); - sqlite3Error(db, SQLITE_OK); + sqlite3Error(db, SQLITE_OK, 0); while( rc==SQLITE_OK && zSql[0] ){ int nCol; char **azVals = 0; @@ -104950,13 +96097,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec( } } if( xCallback(pArg, nCol, azVals, azCols) ){ - /* EVIDENCE-OF: R-38229-40159 If the callback function to - ** sqlite3_exec() returns non-zero, then sqlite3_exec() will - ** return SQLITE_ABORT. */ rc = SQLITE_ABORT; sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; - sqlite3Error(db, SQLITE_ABORT); + sqlite3Error(db, SQLITE_ABORT, 0); goto exec_out; } } @@ -104979,14 +96123,14 @@ exec_out: sqlite3DbFree(db, azCols); rc = sqlite3ApiExit(db, rc); - if( rc!=SQLITE_OK && pzErrMsg ){ + if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); *pzErrMsg = sqlite3Malloc(nErrMsg); if( *pzErrMsg ){ memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); }else{ rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM); + sqlite3Error(db, SQLITE_NOMEM, 0); } }else if( pzErrMsg ){ *pzErrMsg = 0; @@ -105038,7 +96182,6 @@ exec_out: */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ -/* #include "sqlite3.h" */ typedef struct sqlite3_api_routines sqlite3_api_routines; @@ -105049,7 +96192,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines; ** WARNING: In order to maintain backwards compatibility, add new ** interfaces to the end of this structure only. If you insert new ** interfaces in the middle of this structure, then older different -** versions of SQLite will not be able to load each other's shared +** versions of SQLite will not be able to load each others' shared ** libraries! */ struct sqlite3_api_routines { @@ -105271,40 +96414,11 @@ struct sqlite3_api_routines { const char *(*uri_parameter)(const char*,const char*); char *(*vsnprintf)(int,char*,const char*,va_list); int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); - /* Version 3.8.7 and later */ - int (*auto_extension)(void(*)(void)); - int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, - void(*)(void*)); - int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, - void(*)(void*),unsigned char); - int (*cancel_auto_extension)(void(*)(void)); - int (*load_extension)(sqlite3*,const char*,const char*,char**); - void *(*malloc64)(sqlite3_uint64); - sqlite3_uint64 (*msize)(void*); - void *(*realloc64)(void*,sqlite3_uint64); - void (*reset_auto_extension)(void); - void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, - void(*)(void*)); - void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, - void(*)(void*), unsigned char); - int (*strglob)(const char*,const char*); - /* Version 3.8.11 and later */ - sqlite3_value *(*value_dup)(const sqlite3_value*); - void (*value_free)(sqlite3_value*); - int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); - int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); - /* Version 3.9.0 and later */ - unsigned int (*value_subtype)(sqlite3_value*); - void (*result_subtype)(sqlite3_context*,unsigned int); - /* Version 3.10.0 and later */ - int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); - int (*strlike)(const char*,const char*,unsigned int); - int (*db_cacheflush)(sqlite3*); }; /* ** The following macros redefine the API routines so that they are -** redirected through the global sqlite3_api structure. +** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file ** (part of the main SQLite library - not an extension) so that @@ -105313,7 +96427,7 @@ struct sqlite3_api_routines { ** the API. So the redefinition macros are only valid if the ** SQLITE_CORE macros is undefined. */ -#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +#ifndef SQLITE_CORE #define sqlite3_aggregate_context sqlite3_api->aggregate_context #ifndef SQLITE_OMIT_DEPRECATED #define sqlite3_aggregate_count sqlite3_api->aggregate_count @@ -105440,7 +96554,6 @@ struct sqlite3_api_routines { #define sqlite3_value_text16le sqlite3_api->value_text16le #define sqlite3_value_type sqlite3_api->value_type #define sqlite3_vmprintf sqlite3_api->vmprintf -#define sqlite3_vsnprintf sqlite3_api->vsnprintf #define sqlite3_overload_function sqlite3_api->overload_function #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 @@ -105518,34 +96631,9 @@ struct sqlite3_api_routines { #define sqlite3_uri_parameter sqlite3_api->uri_parameter #define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 -/* Version 3.8.7 and later */ -#define sqlite3_auto_extension sqlite3_api->auto_extension -#define sqlite3_bind_blob64 sqlite3_api->bind_blob64 -#define sqlite3_bind_text64 sqlite3_api->bind_text64 -#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension -#define sqlite3_load_extension sqlite3_api->load_extension -#define sqlite3_malloc64 sqlite3_api->malloc64 -#define sqlite3_msize sqlite3_api->msize -#define sqlite3_realloc64 sqlite3_api->realloc64 -#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension -#define sqlite3_result_blob64 sqlite3_api->result_blob64 -#define sqlite3_result_text64 sqlite3_api->result_text64 -#define sqlite3_strglob sqlite3_api->strglob -/* Version 3.8.11 and later */ -#define sqlite3_value_dup sqlite3_api->value_dup -#define sqlite3_value_free sqlite3_api->value_free -#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 -#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 -/* Version 3.9.0 and later */ -#define sqlite3_value_subtype sqlite3_api->value_subtype -#define sqlite3_result_subtype sqlite3_api->result_subtype -/* Version 3.10.0 and later */ -#define sqlite3_status64 sqlite3_api->status64 -#define sqlite3_strlike sqlite3_api->strlike -#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush -#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ +#endif /* SQLITE_CORE */ -#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +#ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; @@ -105564,7 +96652,6 @@ struct sqlite3_api_routines { /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ -/* #include "sqliteInt.h" */ /* #include */ #ifndef SQLITE_OMIT_LOAD_EXTENSION @@ -105581,6 +96668,7 @@ struct sqlite3_api_routines { # define sqlite3_column_table_name16 0 # define sqlite3_column_origin_name 0 # define sqlite3_column_origin_name16 0 +# define sqlite3_table_column_metadata 0 #endif #ifdef SQLITE_OMIT_AUTHORIZATION @@ -105936,32 +97024,7 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_uri_int64, sqlite3_uri_parameter, sqlite3_vsnprintf, - sqlite3_wal_checkpoint_v2, - /* Version 3.8.7 and later */ - sqlite3_auto_extension, - sqlite3_bind_blob64, - sqlite3_bind_text64, - sqlite3_cancel_auto_extension, - sqlite3_load_extension, - sqlite3_malloc64, - sqlite3_msize, - sqlite3_realloc64, - sqlite3_reset_auto_extension, - sqlite3_result_blob64, - sqlite3_result_text64, - sqlite3_strglob, - /* Version 3.8.11 and later */ - (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, - sqlite3_value_free, - sqlite3_result_zeroblob64, - sqlite3_bind_zeroblob64, - /* Version 3.9.0 and later */ - sqlite3_value_subtype, - sqlite3_result_subtype, - /* Version 3.10.0 and later */ - sqlite3_status64, - sqlite3_strlike, - sqlite3_db_cacheflush + sqlite3_wal_checkpoint_v2 }; /* @@ -105989,7 +97052,7 @@ static int sqlite3LoadExtension( const char *zEntry; char *zAltEntry = 0; void **aHandle; - u64 nMsg = 300 + sqlite3Strlen30(zFile); + int nMsg = 300 + sqlite3Strlen30(zFile); int ii; /* Shared library endings to try if zFile cannot be loaded as written */ @@ -106032,7 +97095,7 @@ static int sqlite3LoadExtension( #endif if( handle==0 ){ if( pzErrMsg ){ - *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "unable to open shared library [%s]", zFile); @@ -106058,7 +97121,7 @@ static int sqlite3LoadExtension( if( xInit==0 && zProc==0 ){ int iFile, iEntry, c; int ncFile = sqlite3Strlen30(zFile); - zAltEntry = sqlite3_malloc64(ncFile+30); + zAltEntry = sqlite3_malloc(ncFile+30); if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM; @@ -106080,7 +97143,7 @@ static int sqlite3LoadExtension( if( xInit==0 ){ if( pzErrMsg ){ nMsg += sqlite3Strlen30(zEntry); - *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zEntry, zFile); @@ -106115,7 +97178,7 @@ static int sqlite3LoadExtension( db->aExtension[db->nExtension++] = handle; return SQLITE_OK; } -SQLITE_API int SQLITE_STDCALL sqlite3_load_extension( +SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -106146,7 +97209,7 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ ** Enable or disable extension loading. Extension loading is disabled by ** default so as not to open security holes in older applications. */ -SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff){ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension; @@ -106179,7 +97242,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 }; */ typedef struct sqlite3AutoExtList sqlite3AutoExtList; static SQLITE_WSD struct sqlite3AutoExtList { - u32 nExt; /* Number of entries in aExt[] */ + int nExt; /* Number of entries in aExt[] */ void (**aExt)(void); /* Pointers to the extension init functions */ } sqlite3Autoext = { 0, 0 }; @@ -106203,7 +97266,7 @@ static SQLITE_WSD struct sqlite3AutoExtList { ** Register a statically linked extension that is automatically ** loaded by every new database connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ +SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); @@ -106212,7 +97275,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ }else #endif { - u32 i; + int i; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -106222,9 +97285,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ if( wsdAutoext.aExt[i]==xInit ) break; } if( i==wsdAutoext.nExt ){ - u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); + int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); void (**aNew)(void); - aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte); + aNew = sqlite3_realloc(wsdAutoext.aExt, nByte); if( aNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -106248,7 +97311,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){ ** Return 1 if xInit was found on the list and removed. Return 0 if xInit ** was not on the list. */ -SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)){ +SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -106256,7 +97319,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)) int n = 0; wsdAutoextInit; sqlite3_mutex_enter(mutex); - for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ + for(i=wsdAutoext.nExt-1; i>=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ wsdAutoext.nExt--; wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; @@ -106271,7 +97334,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)) /* ** Reset the automatic extension loading mechanism. */ -SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){ +SQLITE_API void sqlite3_reset_auto_extension(void){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize()==SQLITE_OK ) #endif @@ -106294,7 +97357,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){ ** If anything goes wrong, set an error in the database connection. */ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ - u32 i; + int i; int go = 1; int rc; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); @@ -106320,7 +97383,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ sqlite3_mutex_leave(mutex); zErrmsg = 0; if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ - sqlite3ErrorWithMsg(db, rc, + sqlite3Error(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; } @@ -106343,7 +97406,6 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ ************************************************************************* ** This file contains code used to implement the PRAGMA command. */ -/* #include "sqliteInt.h" */ #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) @@ -106354,64 +97416,54 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ #endif /*************************************************************************** -** The "pragma.h" include file is an automatically generated file that -** that includes the PragType_XXXX macro definitions and the aPragmaName[] -** object. This ensures that the aPragmaName[] table is arranged in -** lexicographical order to facility a binary search of the pragma name. -** Do not edit pragma.h directly. Edit and rerun the script in at -** ../tool/mkpragmatab.tcl. */ -/************** Include pragma.h in the middle of pragma.c *******************/ -/************** Begin file pragma.h ******************************************/ -/* DO NOT EDIT! -** This file is automatically generated by the script at -** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit -** that script and rerun it. +** The next block of code, including the PragTyp_XXXX macro definitions and +** the aPragmaName[] object is composed of generated code. DO NOT EDIT. +** +** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun +** that script. Then copy/paste the output in place of the following: */ #define PragTyp_HEADER_VALUE 0 #define PragTyp_AUTO_VACUUM 1 #define PragTyp_FLAG 2 #define PragTyp_BUSY_TIMEOUT 3 #define PragTyp_CACHE_SIZE 4 -#define PragTyp_CACHE_SPILL 5 -#define PragTyp_CASE_SENSITIVE_LIKE 6 -#define PragTyp_COLLATION_LIST 7 -#define PragTyp_COMPILE_OPTIONS 8 -#define PragTyp_DATA_STORE_DIRECTORY 9 -#define PragTyp_DATABASE_LIST 10 -#define PragTyp_DEFAULT_CACHE_SIZE 11 -#define PragTyp_ENCODING 12 -#define PragTyp_FOREIGN_KEY_CHECK 13 -#define PragTyp_FOREIGN_KEY_LIST 14 -#define PragTyp_INCREMENTAL_VACUUM 15 -#define PragTyp_INDEX_INFO 16 -#define PragTyp_INDEX_LIST 17 -#define PragTyp_INTEGRITY_CHECK 18 -#define PragTyp_JOURNAL_MODE 19 -#define PragTyp_JOURNAL_SIZE_LIMIT 20 -#define PragTyp_LOCK_PROXY_FILE 21 -#define PragTyp_LOCKING_MODE 22 -#define PragTyp_PAGE_COUNT 23 -#define PragTyp_MMAP_SIZE 24 -#define PragTyp_PAGE_SIZE 25 -#define PragTyp_SECURE_DELETE 26 -#define PragTyp_SHRINK_MEMORY 27 -#define PragTyp_SOFT_HEAP_LIMIT 28 -#define PragTyp_STATS 29 -#define PragTyp_SYNCHRONOUS 30 -#define PragTyp_TABLE_INFO 31 -#define PragTyp_TEMP_STORE 32 -#define PragTyp_TEMP_STORE_DIRECTORY 33 -#define PragTyp_THREADS 34 -#define PragTyp_WAL_AUTOCHECKPOINT 35 -#define PragTyp_WAL_CHECKPOINT 36 -#define PragTyp_ACTIVATE_EXTENSIONS 37 -#define PragTyp_HEXKEY 38 -#define PragTyp_KEY 39 -#define PragTyp_REKEY 40 -#define PragTyp_LOCK_STATUS 41 -#define PragTyp_PARSER_TRACE 42 +#define PragTyp_CASE_SENSITIVE_LIKE 5 +#define PragTyp_COLLATION_LIST 6 +#define PragTyp_COMPILE_OPTIONS 7 +#define PragTyp_DATA_STORE_DIRECTORY 8 +#define PragTyp_DATABASE_LIST 9 +#define PragTyp_DEFAULT_CACHE_SIZE 10 +#define PragTyp_ENCODING 11 +#define PragTyp_FOREIGN_KEY_CHECK 12 +#define PragTyp_FOREIGN_KEY_LIST 13 +#define PragTyp_INCREMENTAL_VACUUM 14 +#define PragTyp_INDEX_INFO 15 +#define PragTyp_INDEX_LIST 16 +#define PragTyp_INTEGRITY_CHECK 17 +#define PragTyp_JOURNAL_MODE 18 +#define PragTyp_JOURNAL_SIZE_LIMIT 19 +#define PragTyp_LOCK_PROXY_FILE 20 +#define PragTyp_LOCKING_MODE 21 +#define PragTyp_PAGE_COUNT 22 +#define PragTyp_MMAP_SIZE 23 +#define PragTyp_PAGE_SIZE 24 +#define PragTyp_SECURE_DELETE 25 +#define PragTyp_SHRINK_MEMORY 26 +#define PragTyp_SOFT_HEAP_LIMIT 27 +#define PragTyp_STATS 28 +#define PragTyp_SYNCHRONOUS 29 +#define PragTyp_TABLE_INFO 30 +#define PragTyp_TEMP_STORE 31 +#define PragTyp_TEMP_STORE_DIRECTORY 32 +#define PragTyp_WAL_AUTOCHECKPOINT 33 +#define PragTyp_WAL_CHECKPOINT 34 +#define PragTyp_ACTIVATE_EXTENSIONS 35 +#define PragTyp_HEXKEY 36 +#define PragTyp_KEY 37 +#define PragTyp_REKEY 38 +#define PragTyp_LOCK_STATUS 39 +#define PragTyp_PARSER_TRACE 40 #define PragFlag_NeedSchema 0x01 -#define PragFlag_ReadOnly 0x02 static const struct sPragmaNames { const char *const zName; /* Name of pragma */ u8 ePragTyp; /* PragTyp_XXX value */ @@ -106428,7 +97480,7 @@ static const struct sPragmaNames { { /* zName: */ "application_id", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, - /* iArg: */ BTREE_APPLICATION_ID }, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) { /* zName: */ "auto_vacuum", @@ -106456,18 +97508,14 @@ static const struct sPragmaNames { #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_CACHE_SPILL, + /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, - /* iArg: */ 0 }, + /* iArg: */ SQLITE_CacheSpill }, #endif { /* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, /* ePragFlag: */ 0, /* iArg: */ 0 }, - { /* zName: */ "cell_size_check", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CellSizeCk }, #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "checkpoint_fullfsync", /* ePragTyp: */ PragTyp_FLAG, @@ -106498,12 +97546,6 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "data_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_DATA_VERSION }, -#endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, @@ -106559,8 +97601,8 @@ static const struct sPragmaNames { #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "freelist_count", /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_FREE_PAGE_COUNT }, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "full_column_names", @@ -106605,10 +97647,6 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, - { /* zName: */ "index_xinfo", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) { /* zName: */ "integrity_check", @@ -106672,7 +97710,7 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) +#if defined(SQLITE_DEBUG) { /* zName: */ "parser_trace", /* ePragTyp: */ PragTyp_PARSER_TRACE, /* ePragFlag: */ 0, @@ -106716,7 +97754,7 @@ static const struct sPragmaNames { { /* zName: */ "schema_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, - /* iArg: */ BTREE_SCHEMA_VERSION }, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "secure_delete", @@ -106774,15 +97812,11 @@ static const struct sPragmaNames { /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif - { /* zName: */ "threads", - /* ePragTyp: */ PragTyp_THREADS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "user_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, - /* iArg: */ BTREE_USER_VERSION }, + /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if defined(SQLITE_DEBUG) @@ -106825,10 +97859,9 @@ static const struct sPragmaNames { /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; -/* Number of pragmas: 60 on by default, 73 total. */ - -/************** End of pragma.h **********************************************/ -/************** Continuing where we left off in pragma.c *********************/ +/* Number of pragmas: 56 on by default, 69 total. */ +/* End of the automatically generated pragma table. +***************************************************************************/ /* ** Interpret the given string as a safety level. Return 0 for OFF, @@ -106841,7 +97874,7 @@ static const struct sPragmaNames { ** to support legacy SQL code. The safety level used to be boolean ** and older scripts may have used numbers 0 for OFF and 1 for ON. */ -static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ +static u8 getSafetyLevel(const char *z, int omitFull, int dflt){ /* 123456789 123456789 */ static const char zText[] = "onoffalseyestruefull"; static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; @@ -106863,7 +97896,7 @@ static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ /* ** Interpret the given string as a boolean value. */ -SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, u8 dflt){ +SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){ return getSafetyLevel(z,1,dflt)!=0; } @@ -106959,46 +97992,20 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ } #endif /* SQLITE_PAGER_PRAGMAS */ -/* -** Set the names of the first N columns to the values in azCol[] -*/ -static void setAllColumnNames( - Vdbe *v, /* The query under construction */ - int N, /* Number of columns */ - const char **azCol /* Names of columns */ -){ - int i; - sqlite3VdbeSetNumCols(v, N); - for(i=0; inMem; + i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value)); + if( pI64 ){ + memcpy(pI64, &value, sizeof(value)); } + sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); } @@ -107079,7 +98086,7 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){ ** ** Pragmas are of this form: ** -** PRAGMA [schema.]id [= value] +** PRAGMA [database.]id [= value] ** ** The identifier might also be a string. The value is a string, and ** identifier, or a number. If minusFlag is true, then the value is @@ -107091,8 +98098,8 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){ */ SQLITE_PRIVATE void sqlite3Pragma( Parse *pParse, - Token *pId1, /* First part of [schema.]id field */ - Token *pId2, /* Second part of [schema.]id field, or NULL */ + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ Token *pValue, /* Token for , or NULL */ int minusFlag /* True if a '-' sign preceded */ ){ @@ -107102,18 +98109,17 @@ SQLITE_PRIVATE void sqlite3Pragma( Token *pId; /* Pointer to token */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ int iDb; /* Database index for */ - int lwr, upr, mid = 0; /* Binary search bounds */ + int lwr, upr, mid; /* Binary search bounds */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ - const struct sPragmaNames *pPragma; if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; - /* Interpret the [schema.] part of the pragma statement. iDb is the + /* Interpret the [database.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; @@ -107143,17 +98149,6 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS ** connection. If it returns SQLITE_OK, then assume that the VFS ** handled the pragma and generate a no-op prepared statement. - ** - ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, - ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file - ** object corresponding to the database file to which the pragma - ** statement refers. - ** - ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA - ** file control is an array of pointers to strings (char**) in which the - ** second element of the array is the name of the pragma and the third - ** element is the argument to the pragma or NULL if the pragma has no - ** argument. */ aFcntl[0] = 0; aFcntl[1] = zLeft; @@ -107162,8 +98157,14 @@ SQLITE_PRIVATE void sqlite3Pragma( db->busyHandler.nBusy = 0; rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); if( rc==SQLITE_OK ){ - returnSingleText(v, "result", aFcntl[0]); - sqlite3_free(aFcntl[0]); + if( aFcntl[0] ){ + int mem = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3_free(aFcntl[0]); + } goto pragma_out; } if( rc!=SQLITE_NOTFOUND ){ @@ -107190,20 +98191,19 @@ SQLITE_PRIVATE void sqlite3Pragma( } } if( lwr>upr ) goto pragma_out; - pPragma = &aPragmaNames[mid]; /* Make sure the database schema is loaded if the pragma requires that */ - if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){ + if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } /* Jump to the appropriate pragma handler */ - switch( pPragma->ePragTyp ){ + switch( aPragmaNames[mid].ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* - ** PRAGMA [schema.]default_cache_size - ** PRAGMA [schema.]default_cache_size=N + ** PRAGMA [database.]default_cache_size + ** PRAGMA [database.]default_cache_size=N ** ** The first form reports the current persistent setting for the ** page cache size. The value returned is the maximum number of @@ -107233,7 +98233,8 @@ SQLITE_PRIVATE void sqlite3Pragma( int addr; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ - setOneColumnName(v, "cache_size"); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn); sqlite3VdbeChangeP1(v, addr, iDb); @@ -107254,8 +98255,8 @@ SQLITE_PRIVATE void sqlite3Pragma( #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) /* - ** PRAGMA [schema.]page_size - ** PRAGMA [schema.]page_size=N + ** PRAGMA [database.]page_size + ** PRAGMA [database.]page_size=N ** ** The first form reports the current setting for the ** database page size in bytes. The second form sets the @@ -107267,7 +98268,7 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( pBt!=0 ); if( !zRight ){ int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; - returnSingleInt(v, "page_size", size); + returnSingleInt(pParse, "page_size", size); }else{ /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). @@ -107281,8 +98282,8 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* - ** PRAGMA [schema.]secure_delete - ** PRAGMA [schema.]secure_delete=ON/OFF + ** PRAGMA [database.]secure_delete + ** PRAGMA [database.]secure_delete=ON/OFF ** ** The first form reports the current setting for the ** secure_delete flag. The second form changes the secure_delete @@ -107302,13 +98303,13 @@ SQLITE_PRIVATE void sqlite3Pragma( } } b = sqlite3BtreeSecureDelete(pBt, b); - returnSingleInt(v, "secure_delete", b); + returnSingleInt(pParse, "secure_delete", b); break; } /* - ** PRAGMA [schema.]max_page_count - ** PRAGMA [schema.]max_page_count=N + ** PRAGMA [database.]max_page_count + ** PRAGMA [database.]max_page_count=N ** ** The first form reports the current setting for the ** maximum number of pages in the database file. The @@ -107319,7 +98320,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** change. The only purpose is to provide an easy way to test ** the sqlite3AbsInt32() function. ** - ** PRAGMA [schema.]page_count + ** PRAGMA [database.]page_count ** ** Return the number of pages in the specified database. */ @@ -107340,8 +98341,8 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* - ** PRAGMA [schema.]locking_mode - ** PRAGMA [schema.]locking_mode = (normal|exclusive) + ** PRAGMA [database.]locking_mode + ** PRAGMA [database.]locking_mode = (normal|exclusive) */ case PragTyp_LOCKING_MODE: { const char *zRet = "normal"; @@ -107381,20 +98382,25 @@ SQLITE_PRIVATE void sqlite3Pragma( if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ zRet = "exclusive"; } - returnSingleText(v, "locking_mode", zRet); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); break; } /* - ** PRAGMA [schema.]journal_mode - ** PRAGMA [schema.]journal_mode = + ** PRAGMA [database.]journal_mode + ** PRAGMA [database.]journal_mode = ** (delete|persist|off|truncate|memory|wal|off) */ case PragTyp_JOURNAL_MODE: { int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ int ii; /* Loop counter */ - setOneColumnName(v, "journal_mode"); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); + if( zRight==0 ){ /* If there is no "=MODE" part of the pragma, do a query for the ** current mode */ @@ -107427,8 +98433,8 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* - ** PRAGMA [schema.]journal_size_limit - ** PRAGMA [schema.]journal_size_limit=N + ** PRAGMA [database.]journal_size_limit + ** PRAGMA [database.]journal_size_limit=N ** ** Get or set the size limit on rollback journal files. */ @@ -107436,19 +98442,19 @@ SQLITE_PRIVATE void sqlite3Pragma( Pager *pPager = sqlite3BtreePager(pDb->pBt); i64 iLimit = -2; if( zRight ){ - sqlite3DecOrHexToI64(zRight, &iLimit); + sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8); if( iLimit<-1 ) iLimit = -1; } iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); - returnSingleInt(v, "journal_size_limit", iLimit); + returnSingleInt(pParse, "journal_size_limit", iLimit); break; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* - ** PRAGMA [schema.]auto_vacuum - ** PRAGMA [schema.]auto_vacuum=N + ** PRAGMA [database.]auto_vacuum + ** PRAGMA [database.]auto_vacuum=N ** ** Get or set the value of the database 'auto-vacuum' parameter. ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL @@ -107458,7 +98464,7 @@ SQLITE_PRIVATE void sqlite3Pragma( Btree *pBt = pDb->pBt; assert( pBt!=0 ); if( !zRight ){ - returnSingleInt(v, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); + returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); }else{ int eAuto = getAutoVacuum(zRight); assert( eAuto>=0 && eAuto<=2 ); @@ -107499,7 +98505,7 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif /* - ** PRAGMA [schema.]incremental_vacuum(N) + ** PRAGMA [database.]incremental_vacuum(N) ** ** Do N steps of incremental vacuuming on a database. */ @@ -107522,8 +98528,8 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* - ** PRAGMA [schema.]cache_size - ** PRAGMA [schema.]cache_size=N + ** PRAGMA [database.]cache_size + ** PRAGMA [database.]cache_size=N ** ** The first form reports the current local setting for the ** page cache size. The second form sets the local @@ -107535,7 +98541,7 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ - returnSingleInt(v, "cache_size", pDb->pSchema->cache_size); + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; @@ -107545,50 +98551,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } /* - ** PRAGMA [schema.]cache_spill - ** PRAGMA cache_spill=BOOLEAN - ** PRAGMA [schema.]cache_spill=N - ** - ** The first form reports the current local setting for the - ** page cache spill size. The second form turns cache spill on - ** or off. When turnning cache spill on, the size is set to the - ** current cache_size. The third form sets a spill size that - ** may be different form the cache size. - ** If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - ** - ** If the number of cache_spill pages is less then the number of - ** cache_size pages, no spilling occurs until the page count exceeds - ** the number of cache_size pages. - ** - ** The cache_spill=BOOLEAN setting applies to all attached schemas, - ** not just the schema specified. - */ - case PragTyp_CACHE_SPILL: { - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !zRight ){ - returnSingleInt(v, "cache_spill", - (db->flags & SQLITE_CacheSpill)==0 ? 0 : - sqlite3BtreeSetSpillSize(pDb->pBt,0)); - }else{ - int size = 1; - if( sqlite3GetInt32(zRight, &size) ){ - sqlite3BtreeSetSpillSize(pDb->pBt, size); - } - if( sqlite3GetBoolean(zRight, size!=0) ){ - db->flags |= SQLITE_CacheSpill; - }else{ - db->flags &= ~SQLITE_CacheSpill; - } - setAllPagerFlags(db); - } - break; - } - - /* - ** PRAGMA [schema.]mmap_size(N) + ** PRAGMA [database.]mmap_size(N) ** ** Used to set mapping size limit. The mapping size limit is ** used to limit the aggregate size of all memory mapped regions of the @@ -107607,7 +98570,7 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( zRight ){ int ii; - sqlite3DecOrHexToI64(zRight, &sz); + sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8); if( sz<0 ) sz = sqlite3GlobalConfig.szMmap; if( pId2->n==0 ) db->szMmap = sz; for(ii=db->nDb-1; ii>=0; ii--){ @@ -107623,7 +98586,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = SQLITE_OK; #endif if( rc==SQLITE_OK ){ - returnSingleInt(v, "mmap_size", sz); + returnSingleInt(pParse, "mmap_size", sz); }else if( rc!=SQLITE_NOTFOUND ){ pParse->nErr++; pParse->rc = rc; @@ -107644,7 +98607,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_TEMP_STORE: { if( !zRight ){ - returnSingleInt(v, "temp_store", db->temp_store); + returnSingleInt(pParse, "temp_store", db->temp_store); }else{ changeTempStorage(pParse, zRight); } @@ -107663,7 +98626,13 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_TEMP_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, "temp_store_directory", sqlite3_temp_directory); + if( sqlite3_temp_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", SQLITE_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ @@ -107707,7 +98676,13 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_DATA_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, "data_store_directory", sqlite3_data_directory); + if( sqlite3_data_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "data_store_directory", SQLITE_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ @@ -107732,8 +98707,8 @@ SQLITE_PRIVATE void sqlite3Pragma( #if SQLITE_ENABLE_LOCKING_STYLE /* - ** PRAGMA [schema.]lock_proxy_file - ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" + ** PRAGMA [database.]lock_proxy_file + ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path" ** ** Return or set the value of the lock_proxy_file flag. Changing ** the value sets a specific file to be used for database access locks. @@ -107746,7 +98721,14 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3_file *pFile = sqlite3PagerFile(pPager); sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, &proxy_file_path); - returnSingleText(v, "lock_proxy_file", proxy_file_path); + + if( proxy_file_path ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "lock_proxy_file", SQLITE_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } }else{ Pager *pPager = sqlite3BtreePager(pDb->pBt); sqlite3_file *pFile = sqlite3PagerFile(pPager); @@ -107768,8 +98750,8 @@ SQLITE_PRIVATE void sqlite3Pragma( #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* - ** PRAGMA [schema.]synchronous - ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL + ** PRAGMA [database.]synchronous + ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the @@ -107778,15 +98760,13 @@ SQLITE_PRIVATE void sqlite3Pragma( */ case PragTyp_SYNCHRONOUS: { if( !zRight ){ - returnSingleInt(v, "synchronous", pDb->safety_level-1); + returnSingleInt(pParse, "synchronous", pDb->safety_level-1); }else{ if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ - int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; - if( iLevel==0 ) iLevel = 1; - pDb->safety_level = iLevel; + pDb->safety_level = getSafetyLevel(zRight,0,1)+1; setAllPagerFlags(db); } } @@ -107797,20 +98777,15 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_FLAG_PRAGMAS case PragTyp_FLAG: { if( zRight==0 ){ - returnSingleInt(v, pPragma->zName, (db->flags & pPragma->iArg)!=0 ); + returnSingleInt(pParse, aPragmaNames[mid].zName, + (db->flags & aPragmaNames[mid].iArg)!=0 ); }else{ - int mask = pPragma->iArg; /* Mask of bits to set or clear. */ + int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ mask &= ~(SQLITE_ForeignKeys); } -#if SQLITE_USER_AUTHENTICATION - if( db->auth.authLevel==UAUTH_User ){ - /* Do not allow non-admin users to modify the schema arbitrarily */ - mask &= ~(SQLITE_WriteSchema); - } -#endif if( sqlite3GetBoolean(zRight, 0) ){ db->flags |= mask; @@ -107847,36 +98822,43 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ - static const char *azCol[] = { - "cid", "name", "type", "notnull", "dflt_value", "pk" - }; int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); + sqlite3VdbeSetNumCols(v, 6); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ if( IsHiddenColumn(pCol) ){ nHidden++; continue; } + sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + pCol->zType ? pCol->zType : "", 0); + sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); + if( pCol->zDflt ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, 5); + } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ - for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} + for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} } - sqlite3VdbeMultiLoad(v, 1, "issisi", - i-nHidden, - pCol->zName, - pCol->zType ? pCol->zType : "", - pCol->notNull ? 1 : 0, - pCol->zDflt, - k); + sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } @@ -107884,26 +98866,31 @@ SQLITE_PRIVATE void sqlite3Pragma( break; case PragTyp_STATS: { - static const char *azCol[] = { "table", "index", "width", "height" }; Index *pIdx; HashElem *i; v = sqlite3GetVdbe(pParse); + sqlite3VdbeSetNumCols(v, 4); pParse->nMem = 4; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC); for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); - sqlite3VdbeMultiLoad(v, 1, "ssii", - pTab->zName, - 0, - (int)sqlite3LogEstToInt(pTab->szTabRow), - (int)sqlite3LogEstToInt(pTab->nRowLogEst)); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_Null, 0, 2); + sqlite3VdbeAddOp2(v, OP_Integer, + (int)sqlite3LogEstToInt(pTab->szTabRow), 3); + sqlite3VdbeAddOp2(v, OP_Integer, + (int)sqlite3LogEstToInt(pTab->nRowLogEst), 4); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeMultiLoad(v, 2, "sii", - pIdx->zName, - (int)sqlite3LogEstToInt(pIdx->szIdxRow), - (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0])); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); + sqlite3VdbeAddOp2(v, OP_Integer, + (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3); + sqlite3VdbeAddOp2(v, OP_Integer, + (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); } } @@ -107915,35 +98902,21 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ - static const char *azCol[] = { - "seqno", "cid", "name", "desc", "coll", "key" - }; int i; - int mx; - if( pPragma->iArg ){ - /* PRAGMA index_xinfo (newer version with more rows and columns) */ - mx = pIdx->nColumn; - pParse->nMem = 6; - }else{ - /* PRAGMA index_info (legacy version) */ - mx = pIdx->nKeyCol; - pParse->nMem = 3; - } pTab = pIdx->pTable; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); - assert( pParse->nMem<=ArraySize(azCol) ); - setAllColumnNames(v, pParse->nMem, azCol); - for(i=0; inKeyCol; i++){ i16 cnum = pIdx->aiColumn[i]; - sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum, - cnum<0 ? 0 : pTab->aCol[cnum].zName); - if( pPragma->iArg ){ - sqlite3VdbeMultiLoad(v, 4, "isi", - pIdx->aSortOrder[i], - pIdx->azColl[i], - inKeyCol); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); + assert( pTab->nCol>cnum ); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } } } @@ -107955,53 +98928,53 @@ SQLITE_PRIVATE void sqlite3Pragma( int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ - static const char *azCol[] = { - "seq", "name", "unique", "origin", "partial" - }; v = sqlite3GetVdbe(pParse); - pParse->nMem = 5; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 5, azCol); assert( 5==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ - const char *azOrigin[] = { "c", "u", "pk" }; - sqlite3VdbeMultiLoad(v, 1, "isisi", - i, - pIdx->zName, - IsUniqueIndex(pIdx), - azOrigin[pIdx->idxType], - pIdx->pPartIdxWhere!=0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } } } break; case PragTyp_DATABASE_LIST: { - static const char *azCol[] = { "seq", "name", "file" }; int i; + sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; - setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); - sqlite3VdbeMultiLoad(v, 1, "iss", - i, - db->aDb[i].zName, - sqlite3BtreeGetFilename(db->aDb[i].pBt)); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } } break; case PragTyp_COLLATION_LIST: { - static const char *azCol[] = { "seq", "name" }; int i = 0; HashElem *p; + sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; - setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); - sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); + sqlite3VdbeAddOp2(v, OP_Integer, i++, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } } @@ -108017,26 +98990,33 @@ SQLITE_PRIVATE void sqlite3Pragma( v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ - static const char *azCol[] = { - "id", "seq", "table", "from", "to", "on_update", "on_delete", - "match" - }; int i = 0; + sqlite3VdbeSetNumCols(v, 8); pParse->nMem = 8; sqlite3CodeVerifySchema(pParse, iDb); - setAllColumnNames(v, 8, azCol); assert( 8==ArraySize(azCol) ); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE_STATIC); while(pFK){ int j; for(j=0; jnCol; j++){ - sqlite3VdbeMultiLoad(v, 1, "iissssss", - i, - j, - pFK->zTo, - pTab->aCol[pFK->aCol[j].iFrom].zName, - pFK->aCol[j].zCol, - actionName(pFK->aAction[1]), /* ON UPDATE */ - actionName(pFK->aAction[0]), /* ON DELETE */ - "NONE"); + char *zCol = pFK->aCol[j].zCol; + char *zOnDelete = (char *)actionName(pFK->aAction[0]); + char *zOnUpdate = (char *)actionName(pFK->aAction[1]); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp2(v, OP_Integer, j, 2); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, + pTab->aCol[pFK->aCol[j].iFrom].zName, 0); + sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8); } ++i; @@ -108065,14 +99045,17 @@ SQLITE_PRIVATE void sqlite3Pragma( int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ - static const char *azCol[] = { "table", "rowid", "parent", "fkid" }; regResult = pParse->nMem+1; pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; v = sqlite3GetVdbe(pParse); - setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); + sqlite3VdbeSetNumCols(v, 4); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ @@ -108087,7 +99070,8 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); - sqlite3VdbeLoadString(v, regResult, pTab->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, + P4_TRANSIENT); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; @@ -108132,7 +99116,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrOk); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ for(j=0; jnCol; j++){ @@ -108142,13 +99126,15 @@ SQLITE_PRIVATE void sqlite3Pragma( } if( pParent ){ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, - sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); + sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); VdbeCoverage(v); } } sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); - sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1); + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, + pFK->zTo, P4_TRANSIENT); + sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); sqlite3VdbeResolveLabel(v, addrOk); sqlite3DbFree(db, aiCols); @@ -108165,7 +99151,7 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_PARSER_TRACE: { if( zRight ){ if( sqlite3GetBoolean(zRight, 0) ){ - sqlite3ParserTrace(stdout, "parser: "); + sqlite3ParserTrace(stderr, "parser: "); }else{ sqlite3ParserTrace(0, 0); } @@ -108203,7 +99189,7 @@ SQLITE_PRIVATE void sqlite3Pragma( static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ - { OP_If, 1, 0, 0}, /* 1 */ + { OP_IfNeg, 1, 0, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, }; @@ -108225,7 +99211,8 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Initialize the VDBE program */ pParse->nMem = 6; - setOneColumnName(v, "integrity_check"); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; @@ -108306,7 +99293,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); sqlite3ExprCacheClear(pParse); - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 1, 0, &iDataCur, &iIdxCur); sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ @@ -108315,79 +99302,35 @@ SQLITE_PRIVATE void sqlite3Pragma( pParse->nMem = MAX(pParse->nMem, 8+j); sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); - /* Verify that all NOT NULL columns really are NOT NULL */ - for(j=0; jnCol; j++){ - char *zErr; - int jmp2, jmp3; - if( j==pTab->iPKey ) continue; - if( pTab->aCol[j].notNull==0 ) continue; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); - sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); - jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ - zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, - pTab->aCol[j].zName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); - jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); - sqlite3VdbeAddOp0(v, OP_Halt); - sqlite3VdbeJumpHere(v, jmp2); - sqlite3VdbeJumpHere(v, jmp3); - } - /* Validate index entries for the current row */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int jmp2, jmp3, jmp4, jmp5; - int ckUniq = sqlite3VdbeMakeLabel(v); + int jmp2, jmp3, jmp4; if( pPk==pIdx ) continue; r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, pPrior, r1); pPrior = pIdx; sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ - /* Verify that an index entry exists for the current table row */ - jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, + jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1, pIdx->nColumn); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ - sqlite3VdbeLoadString(v, 3, "row "); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC); sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " missing from index "); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, " missing from index ", + P4_STATIC); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); sqlite3VdbeAddOp0(v, OP_Halt); - sqlite3VdbeJumpHere(v, jmp2); - /* For UNIQUE indexes, verify that only one entry exists with the - ** current key. The entry is unique if (1) any column is NULL - ** or (2) the next entry has a different key */ - if( IsUniqueIndex(pIdx) ){ - int uniqOk = sqlite3VdbeMakeLabel(v); - int jmp6; - int kk; - for(kk=0; kknKeyCol; kk++){ - int iCol = pIdx->aiColumn[kk]; - assert( iCol!=XN_ROWID && iColnCol ); - if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; - sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); - VdbeCoverage(v); - } - jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); - sqlite3VdbeGoto(v, uniqOk); - sqlite3VdbeJumpHere(v, jmp6); - sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, - pIdx->nKeyCol); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ - sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); - sqlite3VdbeGoto(v, jmp5); - sqlite3VdbeResolveLabel(v, uniqOk); - } sqlite3VdbeJumpHere(v, jmp4); + sqlite3VdbeJumpHere(v, jmp2); sqlite3ResolvePartIdxLabel(pParse, jmp3); } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); #ifndef SQLITE_OMIT_BTREECOUNT - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, + "wrong # of entries in index ", P4_STATIC); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ if( pPk==pIdx ) continue; addr = sqlite3VdbeCurrentAddr(v); @@ -108397,7 +99340,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); - sqlite3VdbeLoadString(v, 3, pIdx->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); } @@ -108453,10 +99396,14 @@ SQLITE_PRIVATE void sqlite3Pragma( const struct EncName *pEnc; if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC); + sqlite3VdbeAddOp2(v, OP_String8, 0, 1); assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); - returnSingleText(v, "encoding", encnames[ENC(pParse->db)].zName); + sqlite3VdbeChangeP4(v, -1, encnames[ENC(pParse->db)].zName, P4_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); }else{ /* "PRAGMA encoding = XXX" */ /* Only change the value of sqlite.enc if the database handle is not ** initialized. If the main database exists, the new sqlite.enc value @@ -108469,8 +99416,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - SCHEMA_ENC(db) = ENC(db) = - pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; break; } } @@ -108485,16 +99431,16 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS /* - ** PRAGMA [schema.]schema_version - ** PRAGMA [schema.]schema_version = + ** PRAGMA [database.]schema_version + ** PRAGMA [database.]schema_version = ** - ** PRAGMA [schema.]user_version - ** PRAGMA [schema.]user_version = + ** PRAGMA [database.]user_version + ** PRAGMA [database.]user_version = ** - ** PRAGMA [schema.]freelist_count = + ** PRAGMA [database.]freelist_count = ** - ** PRAGMA [schema.]application_id - ** PRAGMA [schema.]application_id = + ** PRAGMA [database.]application_id + ** PRAGMA [database.]application_id = ** ** The pragma's schema_version and user_version are used to set or get ** the value of the schema-version and user-version, respectively. Both @@ -108515,9 +99461,24 @@ SQLITE_PRIVATE void sqlite3Pragma( ** applications for any purpose. */ case PragTyp_HEADER_VALUE: { - int iCookie = pPragma->iArg; /* Which cookie to read or write */ + int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ + switch( zLeft[0] ){ + case 'a': case 'A': + iCookie = BTREE_APPLICATION_ID; + break; + case 'f': case 'F': + iCookie = BTREE_FREE_PAGE_COUNT; + break; + case 's': case 'S': + iCookie = BTREE_SCHEMA_VERSION; + break; + default: + iCookie = BTREE_USER_VERSION; + break; + } + + if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ @@ -108557,10 +99518,11 @@ SQLITE_PRIVATE void sqlite3Pragma( case PragTyp_COMPILE_OPTIONS: { int i = 0; const char *zOpt; + sqlite3VdbeSetNumCols(v, 1); pParse->nMem = 1; - setOneColumnName(v, "compile_option"); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC); while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ - sqlite3VdbeLoadString(v, 1, zOpt); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } } @@ -108569,12 +99531,11 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef SQLITE_OMIT_WAL /* - ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate + ** PRAGMA [database.]wal_checkpoint = passive|full|restart ** ** Checkpoint the database. */ case PragTyp_WAL_CHECKPOINT: { - static const char *azCol[] = { "busy", "log", "checkpointed" }; int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); int eMode = SQLITE_CHECKPOINT_PASSIVE; if( zRight ){ @@ -108582,12 +99543,14 @@ SQLITE_PRIVATE void sqlite3Pragma( eMode = SQLITE_CHECKPOINT_FULL; }else if( sqlite3StrICmp(zRight, "restart")==0 ){ eMode = SQLITE_CHECKPOINT_RESTART; - }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ - eMode = SQLITE_CHECKPOINT_TRUNCATE; } } - setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); + sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC); + sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } @@ -108605,7 +99568,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( zRight ){ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, "wal_autocheckpoint", + returnSingleInt(pParse, "wal_autocheckpoint", db->xWalCallback==sqlite3WalDefaultHook ? SQLITE_PTR_TO_INT(db->pWalArg) : 0); } @@ -108615,9 +99578,8 @@ SQLITE_PRIVATE void sqlite3Pragma( /* ** PRAGMA shrink_memory ** - ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database - ** connection on which it is invoked to free up as much memory as it - ** can, by calling sqlite3_db_release_memory(). + ** This pragma attempts to free as much memory as possible from the + ** current database connection. */ case PragTyp_SHRINK_MEMORY: { sqlite3_db_release_memory(db); @@ -108634,11 +99596,11 @@ SQLITE_PRIVATE void sqlite3Pragma( ** disables the timeout. */ /*case PragTyp_BUSY_TIMEOUT*/ default: { - assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT ); + assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT ); if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, "timeout", db->busyTimeout); + returnSingleInt(pParse, "timeout", db->busyTimeout); break; } @@ -108646,39 +99608,15 @@ SQLITE_PRIVATE void sqlite3Pragma( ** PRAGMA soft_heap_limit ** PRAGMA soft_heap_limit = N ** - ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the - ** sqlite3_soft_heap_limit64() interface with the argument N, if N is - ** specified and is a non-negative integer. - ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always - ** returns the same integer that would be returned by the - ** sqlite3_soft_heap_limit64(-1) C-language function. + ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted, + ** use -1. */ case PragTyp_SOFT_HEAP_LIMIT: { sqlite3_int64 N; - if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ + if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){ sqlite3_soft_heap_limit64(N); } - returnSingleInt(v, "soft_heap_limit", sqlite3_soft_heap_limit64(-1)); - break; - } - - /* - ** PRAGMA threads - ** PRAGMA threads = N - ** - ** Configure the maximum number of worker threads. Return the new - ** maximum, which might be less than requested. - */ - case PragTyp_THREADS: { - sqlite3_int64 N; - if( zRight - && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK - && N>=0 - ){ - sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); - } - returnSingleInt(v, "threads", - sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); + returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1)); break; } @@ -108690,15 +99628,17 @@ SQLITE_PRIVATE void sqlite3Pragma( static const char *const azLockName[] = { "unlocked", "shared", "reserved", "pending", "exclusive" }; - static const char *azCol[] = { "database", "status" }; int i; - setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); + sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); for(i=0; inDb; i++){ Btree *pBt; const char *zState = "unknown"; int j; if( db->aDb[i].zName==0 ) continue; + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; @@ -108706,7 +99646,7 @@ SQLITE_PRIVATE void sqlite3Pragma( SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } - sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zName, zState); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } break; @@ -108782,7 +99722,6 @@ pragma_out: ** interface, and routines that contribute to loading the database schema ** from disk. */ -/* #include "sqliteInt.h" */ /* ** Fill the InitData structure with an error message that indicates @@ -108795,13 +99734,13 @@ static void corruptSchema( ){ sqlite3 *db = pData->db; if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ - char *z; if( zObj==0 ) zObj = "?"; - z = sqlite3_mprintf("malformed database schema (%s)", zObj); - if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); - sqlite3DbFree(db, *pData->pzErrMsg); - *pData->pzErrMsg = z; - if( z==0 ) db->mallocFailed = 1; + sqlite3SetString(pData->pzErrMsg, db, + "malformed database schema (%s)", zObj); + if( zExtra ){ + *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg, + "%s - %s", *pData->pzErrMsg, zExtra); + } } pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; } @@ -108836,7 +99775,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ corruptSchema(pData, argv[0], 0); - }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){ + }else if( argv[2] && argv[2][0] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data @@ -108867,8 +99806,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char } } sqlite3_finalize(pStmt); - }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ - corruptSchema(pData, argv[0], 0); + }else if( argv[0]==0 ){ + corruptSchema(pData, 0, 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -108993,7 +99932,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); if( rc!=SQLITE_OK ){ - sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); + sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); goto initone_error_out; } openedTransaction = 1; @@ -109097,7 +100036,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ db->aDb[iDb].zName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { - sqlite3_xauth xAuth; + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); xAuth = db->xAuth; db->xAuth = 0; #endif @@ -109163,11 +100102,8 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int commit_internal = !(db->flags&SQLITE_InternChanges); assert( sqlite3_mutex_held(db->mutex) ); - assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); - assert( db->init.busy==0 ); rc = SQLITE_OK; db->init.busy = 1; - ENC(db) = SCHEMA_ENC(db); for(i=0; rc==SQLITE_OK && inDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); @@ -109181,8 +100117,8 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ ** schema may contain references to objects in other databases. */ #ifndef SQLITE_OMIT_TEMPDB - assert( db->nDb>1 ); - if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ + if( rc==SQLITE_OK && ALWAYS(db->nDb>1) + && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetOneSchema(db, 1); @@ -109365,7 +100301,7 @@ static int sqlite3Prepare( rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ const char *zDb = db->aDb[i].zName; - sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); + sqlite3Error(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; } @@ -109382,7 +100318,7 @@ static int sqlite3Prepare( testcase( nBytes==mxLen ); testcase( nBytes==mxLen+1 ); if( nBytes>mxLen ){ - sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); + sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); rc = sqlite3ApiExit(db, SQLITE_TOOBIG); goto end_prepare; } @@ -109449,10 +100385,10 @@ static int sqlite3Prepare( } if( zErrMsg ){ - sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); + sqlite3Error(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ - sqlite3Error(db, rc); + sqlite3Error(db, rc, 0); } /* Delete any TriggerPrg structures allocated while parsing this statement. */ @@ -109480,12 +100416,9 @@ static int sqlite3LockAndPrepare( const char **pzTail /* OUT: End of parsed string */ ){ int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif + assert( ppStmt!=0 ); *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ + if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(db->mutex); @@ -109546,7 +100479,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare( +SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -109558,7 +100491,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2( +SQLITE_API int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -109592,11 +100525,9 @@ static int sqlite3Prepare16( const char *zTail8 = 0; int rc = SQLITE_OK; -#ifdef SQLITE_ENABLE_API_ARMOR - if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; -#endif + assert( ppStmt ); *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ + if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } if( nBytes>=0 ){ @@ -109634,7 +100565,7 @@ static int sqlite3Prepare16( ** and the statement is automatically recompiled if an schema change ** occurs. */ -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( +SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -109646,7 +100577,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16( assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } -SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( +SQLITE_API int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ @@ -109677,22 +100608,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2( ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. */ -/* #include "sqliteInt.h" */ - -/* -** Trace output macros -*/ -#if SELECTTRACE_ENABLED -/***/ int sqlite3SelectTrace = 0; -# define SELECTTRACE(K,P,S,X) \ - if(sqlite3SelectTrace&(K)) \ - sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ - (S)->zSelName,(S)),\ - sqlite3DebugPrintf X -#else -# define SELECTTRACE(K,P,S,X) -#endif - /* ** An instance of the following object is used to record information about @@ -109719,31 +100634,25 @@ struct SortCtx { int regReturn; /* Register holding block-output return address */ int labelBkOut; /* Start label for the block-output subroutine */ int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ - int labelDone; /* Jump here when done, ex: LIMIT reached */ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ /* -** Delete all the content of a Select structure. Deallocate the structure -** itself only if bFree is true. +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. */ -static void clearSelect(sqlite3 *db, Select *p, int bFree){ - while( p ){ - Select *pPrior = p->pPrior; - sqlite3ExprListDelete(db, p->pEList); - sqlite3SrcListDelete(db, p->pSrc); - sqlite3ExprDelete(db, p->pWhere); - sqlite3ExprListDelete(db, p->pGroupBy); - sqlite3ExprDelete(db, p->pHaving); - sqlite3ExprListDelete(db, p->pOrderBy); - sqlite3ExprDelete(db, p->pLimit); - sqlite3ExprDelete(db, p->pOffset); - sqlite3WithDelete(db, p->pWith); - if( bFree ) sqlite3DbFree(db, p); - p = pPrior; - bFree = 1; - } +static void clearSelect(sqlite3 *db, Select *p){ + sqlite3ExprListDelete(db, p->pEList); + sqlite3SrcListDelete(db, p->pSrc); + sqlite3ExprDelete(db, p->pWhere); + sqlite3ExprListDelete(db, p->pGroupBy); + sqlite3ExprDelete(db, p->pHaving); + sqlite3ExprListDelete(db, p->pOrderBy); + sqlite3SelectDelete(db, p->pPrior); + sqlite3ExprDelete(db, p->pLimit); + sqlite3ExprDelete(db, p->pOffset); + sqlite3WithDelete(db, p->pWith); } /* @@ -109778,13 +100687,14 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); + assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ if( pNew==0 ){ assert( db->mallocFailed ); pNew = &standin; memset(pNew, 0, sizeof(*pNew)); } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0)); + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); } pNew->pEList = pEList; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); @@ -109797,11 +100707,12 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; - assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 ); + assert( pOffset==0 || pLimit!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; if( db->mallocFailed ) { - clearSelect(db, pNew, pNew!=&standin); + clearSelect(db, pNew); + if( pNew!=&standin ) sqlite3DbFree(db, pNew); pNew = 0; }else{ assert( pNew->pSrc!=0 || pParse->nErr>0 ); @@ -109810,23 +100721,14 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( return pNew; } -#if SELECTTRACE_ENABLED -/* -** Set the name of a Select object -*/ -SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ - if( p && zName ){ - sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName); - } -} -#endif - - /* ** Delete the given Select structure and all of its substructures. */ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - clearSelect(db, p, 1); + if( p ){ + clearSelect(db, p); + sqlite3DbFree(db, p); + } } /* @@ -110032,12 +100934,6 @@ static void setJoinExpr(Expr *p, int iTable){ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); p->iRightJoinTable = (i16)iTable; - if( p->op==TK_FUNCTION && p->x.pList ){ - int i; - for(i=0; ix.pList->nExpr; i++){ - setJoinExpr(p->x.pList->a[i].pExpr, iTable); - } - } setJoinExpr(p->pLeft, iTable); p = p->pRight; } @@ -110072,12 +100968,12 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ int isOuter; if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; - isOuter = (pRight->fg.jointype & JT_OUTER)!=0; + isOuter = (pRight->jointype & JT_OUTER)!=0; /* When the NATURAL keyword is present, add WHERE clause terms for ** every column that the two tables have in common. */ - if( pRight->fg.jointype & JT_NATURAL ){ + if( pRight->jointype & JT_NATURAL ){ if( pRight->pOn || pRight->pUsing ){ sqlite3ErrorMsg(pParse, "a NATURAL join may not have " "an ON or USING clause", 0); @@ -110154,49 +101050,28 @@ static KeyInfo *keyInfoFromExprList( ); /* -** Generate code that will push the record in registers regData -** through regData+nData-1 onto the sorter. +** Insert code into "v" that will push the record in register regData +** into the sorter. */ static void pushOntoSorter( Parse *pParse, /* Parser context */ SortCtx *pSort, /* Information about the ORDER BY clause */ Select *pSelect, /* The whole SELECT statement */ - int regData, /* First register holding data to be sorted */ - int regOrigData, /* First register holding data before packing */ - int nData, /* Number of elements in the data array */ - int nPrefixReg /* No. of reg prior to regData available for use */ + int regData /* Register holding data to be sorted */ ){ - Vdbe *v = pParse->pVdbe; /* Stmt under construction */ - int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0); - int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ - int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ - int regBase; /* Regs for sorter record */ - int regRecord = ++pParse->nMem; /* Assembled sorter record */ - int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ - int op; /* Opcode to add sorter record to sorter */ - int iLimit; /* LIMIT counter */ + Vdbe *v = pParse->pVdbe; + int nExpr = pSort->pOrderBy->nExpr; + int regRecord = ++pParse->nMem; + int regBase = pParse->nMem+1; + int nOBSat = pSort->nOBSat; + int op; - assert( bSeq==0 || bSeq==1 ); - assert( nData==1 || regData==regOrigData ); - if( nPrefixReg ){ - assert( nPrefixReg==nExpr+bSeq ); - regBase = regData - nExpr - bSeq; - }else{ - regBase = pParse->nMem + 1; - pParse->nMem += nBase; - } - assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); - iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; - pSort->labelDone = sqlite3VdbeMakeLabel(v); - sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, - SQLITE_ECEL_DUP|SQLITE_ECEL_REF); - if( bSeq ){ - sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); - } - if( nPrefixReg==0 ){ - sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); + pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */ + sqlite3ExprCacheClear(pParse); + sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0); + sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); + sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ int addrFirst; /* Address of the OP_IfNot opcode */ @@ -110207,35 +101082,24 @@ static void pushOntoSorter( regPrevKey = pParse->nMem+1; pParse->nMem += pSort->nOBSat; - nKey = nExpr - pSort->nOBSat + bSeq; - if( bSeq ){ - addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); - }else{ - addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor); - } - VdbeCoverage(v); + nKey = nExpr - pSort->nOBSat + 1; + addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat); pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); if( pParse->db->mallocFailed ) return; - pOp->p2 = nKey + nData; + pOp->p2 = nKey + 1; pKI = pOp->p4.pKeyInfo; memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); - testcase( pKI->nXField>2 ); - pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, - pKI->nXField-1); + pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1); addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); pSort->labelBkOut = sqlite3VdbeMakeLabel(v); pSort->regReturn = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); - if( iLimit ){ - sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone); - VdbeCoverage(v); - } sqlite3VdbeJumpHere(v, addrFirst); - sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); + sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat); sqlite3VdbeJumpHere(v, addrJmp); } if( pSort->sortFlags & SORTFLAG_UseSorter ){ @@ -110244,12 +101108,21 @@ static void pushOntoSorter( op = OP_IdxInsert; } sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); - if( iLimit ){ - int addr; - addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v); + if( pSelect->iLimit ){ + int addr1, addr2; + int iLimit; + if( pSelect->iOffset ){ + iLimit = pSelect->iOffset+1; + }else{ + iLimit = pSelect->iLimit; + } + addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); + addr2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); - sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeJumpHere(v, addr2); } } @@ -110262,8 +101135,12 @@ static void codeOffset( int iContinue /* Jump here to skip the current record */ ){ if( iOffset>0 ){ - sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v); - VdbeComment((v, "OFFSET")); + int addr; + sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1); + addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); + VdbeComment((v, "skip OFFSET records")); + sqlite3VdbeJumpHere(v, addr); } } @@ -110345,7 +101222,6 @@ static void selectInnerLoop( int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ - int nPrefixReg = 0; /* Number of extra registers before regResult */ assert( v ); assert( pEList!=0 ); @@ -110361,11 +101237,6 @@ static void selectInnerLoop( nResultCol = pEList->nExpr; if( pDest->iSdst==0 ){ - if( pSort ){ - nPrefixReg = pSort->pOrderBy->nExpr; - if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++; - pParse->nMem += nPrefixReg; - } pDest->iSdst = pParse->nMem+1; pParse->nMem += nResultCol; }else if( pDest->iSdst+nResultCol > pParse->nMem ){ @@ -110387,13 +101258,8 @@ static void selectInnerLoop( /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - u8 ecelFlags; - if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ - ecelFlags = SQLITE_ECEL_DUP; - }else{ - ecelFlags = 0; - } - sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags); + sqlite3ExprCodeExprList(pParse, pEList, regResult, + (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0); } /* If the DISTINCT keyword was present on the SELECT statement @@ -110436,7 +101302,7 @@ static void selectInnerLoop( sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); } - assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed ); + assert( sqlite3VdbeCurrentAddr(v)==iJump ); sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1); break; } @@ -110448,8 +101314,7 @@ static void selectInnerLoop( default: { assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); - codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, - regResult); + codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult); break; } } @@ -110488,12 +101353,10 @@ static void selectInnerLoop( case SRT_DistFifo: case SRT_Table: case SRT_EphemTab: { - int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); + int r1 = sqlite3GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); - testcase( eDest==SRT_Fifo ); - testcase( eDest==SRT_DistFifo ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -110502,14 +101365,13 @@ static void selectInnerLoop( ** current row to the index and proceed with writing it to the ** output table as well. */ int addr = sqlite3VdbeCurrentAddr(v) + 4; - sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); - VdbeCoverage(v); + sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); assert( pSort==0 ); } #endif if( pSort ){ - pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); + pushOntoSorter(pParse, pSort, p, r1); }else{ int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); @@ -110517,7 +101379,7 @@ static void selectInnerLoop( sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); } - sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1); + sqlite3ReleaseTempReg(pParse, r1); break; } @@ -110535,7 +101397,7 @@ static void selectInnerLoop( ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + pushOntoSorter(pParse, pSort, p, regResult); }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); @@ -110561,9 +101423,9 @@ static void selectInnerLoop( case SRT_Mem: { assert( nResultCol==1 ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); + pushOntoSorter(pParse, pSort, p, regResult); }else{ - assert( regResult==iParm ); + sqlite3ExprCodeMove(pParse, regResult, iParm, 1); /* The LIMIT clause will jump out of the loop for us */ } break; @@ -110575,8 +101437,10 @@ static void selectInnerLoop( testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol, - nPrefixReg); + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); + pushOntoSorter(pParse, pSort, p, r1); + sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ @@ -110653,7 +101517,7 @@ static void selectInnerLoop( ** the output for us. */ if( pSort==0 && p->iLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } } @@ -110719,7 +101583,7 @@ SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; } ** then the KeyInfo structure is appropriate for initializing a virtual ** index to implement a DISTINCT test. ** -** Space to hold the KeyInfo structure is obtained from malloc. The calling +** Space to hold the KeyInfo structure is obtain from malloc. The calling ** function is responsible for seeing that this structure is eventually ** freed. */ @@ -110736,7 +101600,7 @@ static KeyInfo *keyInfoFromExprList( int i; nExpr = pList->nExpr; - pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); + pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1); if( pInfo ){ assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; ipVdbe; /* The prepared statement */ - int addrBreak = pSort->labelDone; /* Jump here to exit loop */ + int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; int addrOnce = 0; int iTab; + int pseudoTab = 0; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int nKey; - int iSortTab; /* Sorter cursor to read from */ - int nSortData; /* Trailing values to read from sorter */ - int i; - int bSeq; /* True if sorter record includes seq. no. */ -#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS - struct ExprList_item *aOutEx = p->pEList->a; -#endif - assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); - sqlite3VdbeGoto(v, addrBreak); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak); sqlite3VdbeResolveLabel(v, pSort->labelBkOut); + addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); } iTab = pSort->iECursor; + regRow = sqlite3GetTempReg(pParse); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ + pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn); regRowid = 0; - regRow = pDest->iSdst; - nSortData = nColumn; }else{ regRowid = sqlite3GetTempReg(pParse); - regRow = sqlite3GetTempReg(pParse); - nSortData = 1; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; - iSortTab = pParse->nTab++; - if( pSort->labelBkOut ){ - addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); + int ptab2 = pParse->nTab++; + sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2); if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); - sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); - bSeq = 0; + sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); + sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow); + sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); }else{ + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); - iSortTab = iTab; - bSeq = 1; - } - for(i=0; iiSdst+i ); + sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i); + if( i==0 ){ + sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); + } + } if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); @@ -110944,10 +101808,9 @@ static void generateSortTail( break; } } - if( regRowid ){ - sqlite3ReleaseTempReg(pParse, regRow); - sqlite3ReleaseTempReg(pParse, regRowid); - } + sqlite3ReleaseTempReg(pParse, regRow); + sqlite3ReleaseTempReg(pParse, regRowid); + /* The bottom of the loop */ sqlite3VdbeResolveLabel(v, addrContinue); @@ -110986,30 +101849,30 @@ static void generateSortTail( */ #ifdef SQLITE_ENABLE_COLUMN_METADATA # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) -#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ -# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) -#endif static const char *columnTypeImpl( NameContext *pNC, Expr *pExpr, -#ifdef SQLITE_ENABLE_COLUMN_METADATA const char **pzOrigDb, const char **pzOrigTab, const char **pzOrigCol, -#endif u8 *pEstWidth ){ - char const *zType = 0; - int j; - u8 estWidth = 1; -#ifdef SQLITE_ENABLE_COLUMN_METADATA char const *zOrigDb = 0; char const *zOrigTab = 0; char const *zOrigCol = 0; -#endif +#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ +# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) +static const char *columnTypeImpl( + NameContext *pNC, + Expr *pExpr, + u8 *pEstWidth +){ +#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */ + char const *zType = 0; + int j; + u8 estWidth = 1; - assert( pExpr!=0 ); - assert( pNC->pSrcList!=0 ); + if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0; switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { @@ -111064,9 +101927,6 @@ static const char *columnTypeImpl( /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. - ** - ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been - ** caught already by name resolution. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; @@ -111197,9 +102057,7 @@ static void generateColumnNames( } #endif - if( pParse->colNamesSet || db->mallocFailed ) return; - assert( v!=0 ); - assert( pTabList!=0 ); + if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; @@ -111211,7 +102069,7 @@ static void generateColumnNames( if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){ + }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){ Table *pTab; char *zCol; int iCol = p->iColumn; @@ -111247,7 +102105,7 @@ static void generateColumnNames( } /* -** Given an expression list (which is really the list of expressions +** Given a an expression list (which is really the list of expressions ** that form the result set of a SELECT statement) compute appropriate ** column names for a table that would hold the expression list. ** @@ -111259,7 +102117,7 @@ static void generateColumnNames( ** Return SQLITE_OK on success. If a memory allocation error occurs, ** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. */ -SQLITE_PRIVATE int sqlite3ColumnsFromExprList( +static int selectColumnsFromExprList( Parse *pParse, /* Parsing context */ ExprList *pEList, /* Expr list from which to derive column names */ i16 *pnCol, /* Write the number of columns here */ @@ -111267,15 +102125,13 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( ){ sqlite3 *db = pParse->db; /* Database connection */ int i, j; /* Loop counters */ - u32 cnt; /* Index added to make the name unique */ + int cnt; /* Index added to make the name unique */ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ Expr *p; /* Expression for a single result column */ char *zName; /* Column name */ int nName; /* Size of name in zName[] */ - Hash ht; /* Hash table of column names */ - sqlite3HashInit(&ht); if( pEList ){ nCol = pEList->nExpr; aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); @@ -111284,16 +102140,16 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( nCol = 0; aCol = 0; } - assert( nCol==(i16)nCol ); *pnCol = nCol; *paCol = aCol; - for(i=0, pCol=aCol; imallocFailed; i++, pCol++){ + for(i=0, pCol=aCol; ia[i].pExpr); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS " phrase, use as the name */ + zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ Table *pTab; /* Table associated with this expression */ @@ -111306,37 +102162,41 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( int iCol = pColExpr->iColumn; pTab = pColExpr->pTab; if( iCol<0 ) iCol = pTab->iPKey; - zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; + zName = sqlite3MPrintf(db, "%s", + iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); }else if( pColExpr->op==TK_ID ){ assert( !ExprHasProperty(pColExpr, EP_IntValue) ); - zName = pColExpr->u.zToken; + zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); }else{ /* Use the original text of the column expression as its name */ - zName = pEList->a[i].zSpan; + zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); } } - zName = sqlite3MPrintf(db, "%s", zName); + if( db->mallocFailed ){ + sqlite3DbFree(db, zName); + break; + } /* Make sure the column name is unique. If the name is not unique, - ** append an integer to the name so that it becomes unique. + ** append a integer to the name so that it becomes unique. */ - cnt = 0; - while( zName && sqlite3HashFind(&ht, zName)!=0 ){ - nName = sqlite3Strlen30(zName); - if( nName>0 ){ - for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} - if( zName[j]==':' ) nName = j; + nName = sqlite3Strlen30(zName); + for(j=cnt=0; j1 && sqlite3Isdigit(zName[k]); k--){} + if( k>=0 && zName[k]==':' ) nName = k; + zName[nName] = 0; + zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); + sqlite3DbFree(db, zName); + zName = zNewName; + j = -1; + if( zName==0 ) break; } - zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); - if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); } pCol->zName = zName; - sqlite3ColumnPropertiesFromName(0, pCol); - if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ - db->mallocFailed = 1; - } } - sqlite3HashClear(&ht); if( db->mallocFailed ){ for(j=0; jpEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ p = a[i].pExpr; - if( pCol->zType==0 ){ - pCol->zType = sqlite3DbStrDup(db, - columnType(&sNC, p,0,0,0, &pCol->szEst)); - } + pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); - if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; + if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl && pCol->zColl==0 ){ + if( pColl ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } @@ -111424,7 +102281,7 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ pTab->nRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); - sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); + selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab, pSelect); pTab->iPKey = -1; if( db->mallocFailed ){ @@ -111481,7 +102338,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ Vdbe *v = 0; int iLimit = 0; int iOffset; - int n; + int addr1, n; if( p->iLimit ) return; /* @@ -111500,7 +102357,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); if( n==0 ){ - sqlite3VdbeGoto(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); }else if( n>=0 && p->nSelectRow>(u64)n ){ p->nSelectRow = n; } @@ -111508,7 +102365,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; @@ -111516,10 +102373,14 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pOffset, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); + sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); VdbeComment((v, "LIMIT+OFFSET")); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); + sqlite3VdbeJumpHere(v, addr1); } } } @@ -111541,10 +102402,7 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ pRet = 0; } assert( iCol>=0 ); - /* iCol must be less than p->pEList->nExpr. Otherwise an error would - ** have been thrown during name resolution and we would not have gotten - ** this far */ - if( pRet==0 && ALWAYS(iColpEList->nExpr) ){ + if( pRet==0 && iColpEList->nExpr ){ pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); } return pRet; @@ -111599,7 +102457,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ ** ** ** There is exactly one reference to the recursive-table in the FROM clause -** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag. +** of recursive-query, marked with the SrcList->a[].isRecursive flag. ** ** The setup-query runs once to generate an initial set of rows that go ** into a Queue table. Rows are extracted from the Queue table one by @@ -111664,7 +102522,7 @@ static void generateWithRecursiveQuery( /* Locate the cursor number of the Current table */ for(i=0; ALWAYS(inSrc); i++){ - if( pSrc->a[i].fg.isRecursive ){ + if( pSrc->a[i].isRecursive ){ iCurrent = pSrc->a[i].iCursor; break; } @@ -111726,7 +102584,7 @@ static void generateWithRecursiveQuery( selectInnerLoop(pParse, p, p->pEList, iCurrent, 0, 0, pDest, addrCont, addrBreak); if( regLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); + sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); VdbeCoverage(v); } sqlite3VdbeResolveLabel(v, addrCont); @@ -111734,17 +102592,13 @@ static void generateWithRecursiveQuery( /* Execute the recursive SELECT taking the single row in Current as ** the value for the recursive-table. Store the results in the Queue. */ - if( p->selFlags & SF_Aggregate ){ - sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); - }else{ - p->pPrior = 0; - sqlite3Select(pParse, p, &destQueue); - assert( p->pPrior==0 ); - p->pPrior = pSetup; - } + p->pPrior = 0; + sqlite3Select(pParse, p, &destQueue); + assert( p->pPrior==0 ); + p->pPrior = pSetup; /* Keep running the loop until the Queue is empty */ - sqlite3VdbeGoto(v, addrTop); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); sqlite3VdbeResolveLabel(v, addrBreak); end_of_recursive_query: @@ -111763,48 +102617,6 @@ static int multiSelectOrderBy( SelectDest *pDest /* What to do with query results */ ); -/* -** Handle the special case of a compound-select that originates from a -** VALUES clause. By handling this as a special case, we avoid deep -** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT -** on a VALUES clause. -** -** Because the Select object originates from a VALUES clause: -** (1) It has no LIMIT or OFFSET -** (2) All terms are UNION ALL -** (3) There is no ORDER BY clause -*/ -static int multiSelectValues( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - Select *pPrior; - int nRow = 1; - int rc = 0; - assert( p->selFlags & SF_MultiValue ); - do{ - assert( p->selFlags & SF_Values ); - assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); - assert( p->pLimit==0 ); - assert( p->pOffset==0 ); - assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); - if( p->pPrior==0 ) break; - assert( p->pPrior->pNext==p ); - p = p->pPrior; - nRow++; - }while(1); - while( p ){ - pPrior = p->pPrior; - p->pPrior = 0; - rc = sqlite3Select(pParse, p, pDest); - p->pPrior = pPrior; - if( rc ) break; - p->nSelectRow = nRow; - p = p->pNext; - } - return rc; -} /* ** This routine is called to process a compound query form from @@ -111886,18 +102698,20 @@ static int multiSelect( dest.eDest = SRT_Table; } - /* Special handling for a compound-select that originates as a VALUES clause. - */ - if( p->selFlags & SF_MultiValue ){ - rc = multiSelectValues(pParse, p, &dest); - goto multi_select_end; - } - /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ assert( p->pEList && pPrior->pEList ); - assert( p->pEList->nExpr==pPrior->pEList->nExpr ); + if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ + if( p->selFlags & SF_Values ){ + sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); + }else{ + sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); + } + rc = 1; + goto multi_select_end; + } #ifndef SQLITE_OMIT_CTE if( p->selFlags & SF_Recursive ){ @@ -111933,13 +102747,8 @@ static int multiSelect( p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0); - sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1); - } } explainSetInteger(iSub2, pParse->iNextSelectId); rc = sqlite3Select(pParse, p, &dest); @@ -112040,7 +102849,7 @@ static int multiSelect( if( dest.eDest==SRT_Output ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); @@ -112115,7 +102924,7 @@ static int multiSelect( if( dest.eDest==SRT_Output ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); @@ -112194,19 +103003,6 @@ multi_select_end: } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ -/* -** Error message for when two or more terms of a compound select have different -** size result sets. -*/ -SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ - if( p->selFlags & SF_Values ){ - sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); - }else{ - sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", selectOpName(p->op)); - } -} - /* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. @@ -112247,12 +103043,12 @@ static int generateOutputSubroutine( /* Suppress duplicates for UNION, EXCEPT, and INTERSECT */ if( regPrev ){ - int addr1, addr2; - addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); - addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, + int j1, j2; + j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); } @@ -112262,14 +103058,15 @@ static int generateOutputSubroutine( */ codeOffset(v, p->iOffset, iContinue); - assert( pDest->eDest!=SRT_Exists ); - assert( pDest->eDest!=SRT_Table ); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ + case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); + testcase( pDest->eDest==SRT_Table ); + testcase( pDest->eDest==SRT_EphemTab ); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); @@ -112286,7 +103083,7 @@ static int generateOutputSubroutine( */ case SRT_Set: { int r1; - assert( pIn->nSdst==1 || pParse->nErr>0 ); + assert( pIn->nSdst==1 ); pDest->affSdst = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); r1 = sqlite3GetTempReg(pParse); @@ -112297,12 +103094,22 @@ static int generateOutputSubroutine( break; } +#if 0 /* Never occurs on an ORDER BY query */ + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); + /* The LIMIT clause will terminate the loop for us */ + break; + } +#endif + /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { - assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); + assert( pIn->nSdst==1 ); sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; @@ -112317,7 +103124,7 @@ static int generateOutputSubroutine( pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); pDest->nSdst = pIn->nSdst; } - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); + sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); break; } @@ -112341,7 +103148,7 @@ static int generateOutputSubroutine( /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } /* Generate the subroutine return @@ -112469,7 +103276,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 j1; /* Jump instructions that get retargetted */ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ KeyInfo *pKeyMerge; /* Comparison information for merging rows */ @@ -112533,8 +103340,8 @@ static int multiSelectOrderBy( if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; iu.x.iOrderByCol>0 ); - assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); + assert( pItem->u.x.iOrderByCol>0 + && pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; } pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); @@ -112605,19 +103412,19 @@ static int multiSelectOrderBy( ** left of the compound operator - the "A" select. */ addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; - addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); + j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; explainSetInteger(iSub1, pParse->iNextSelectId); sqlite3Select(pParse, pPrior, &destA); sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); /* Generate a coroutine to evaluate the SELECT statement on ** the right - the "B" select */ addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; - addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); + j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); VdbeComment((v, "right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; @@ -112658,7 +103465,7 @@ static int multiSelectOrderBy( addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrEofA); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); p->nSelectRow += pPrior->nSelectRow; } @@ -112672,7 +103479,7 @@ static int multiSelectOrderBy( VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrEofB); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); } /* Generate code to handle the case of AB @@ -112704,11 +103511,11 @@ static int multiSelectOrderBy( sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); } sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - sqlite3VdbeGoto(v, labelCmpr); + sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* This code runs once to initialize everything. */ - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); @@ -112730,7 +103537,7 @@ static int multiSelectOrderBy( if( pDest->eDest==SRT_Output ){ Select *pFirst = pPrior; while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); + generateColumnNames(pParse, 0, pFirst->pEList); } /* Reassembly the compound query so that it will be freed correctly @@ -112744,14 +103551,14 @@ static int multiSelectOrderBy( /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ explainComposite(pParse, p->op, iSub1, iSub2, 0); - return pParse->nErr!=0; + return SQLITE_OK; } #endif #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Forward Declarations */ static void substExprList(sqlite3*, ExprList*, int, ExprList*); -static void substSelect(sqlite3*, Select *, int, ExprList*, int); +static void substSelect(sqlite3*, Select *, int, ExprList *); /* ** Scan through the expression pExpr. Replace every reference to @@ -112788,7 +103595,7 @@ static Expr *substExpr( pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); + substSelect(db, pExpr->x.pSelect, iTable, pEList); }else{ substExprList(db, pExpr->x.pList, iTable, pEList); } @@ -112811,28 +103618,25 @@ static void substSelect( sqlite3 *db, /* Report malloc errors here */ Select *p, /* SELECT statement in which to make substitutions */ int iTable, /* Table to be replaced */ - ExprList *pEList, /* Substitute values */ - int doPrior /* Do substitutes on p->pPrior too */ + ExprList *pEList /* Substitute values */ ){ SrcList *pSrc; struct SrcList_item *pItem; int i; if( !p ) return; - do{ - substExprList(db, p->pEList, iTable, pEList); - substExprList(db, p->pGroupBy, iTable, pEList); - substExprList(db, p->pOrderBy, iTable, pEList); - p->pHaving = substExpr(db, p->pHaving, iTable, pEList); - p->pWhere = substExpr(db, p->pWhere, iTable, pEList); - pSrc = p->pSrc; - assert( pSrc!=0 ); + substExprList(db, p->pEList, iTable, pEList); + substExprList(db, p->pGroupBy, iTable, pEList); + substExprList(db, p->pOrderBy, iTable, pEList); + p->pHaving = substExpr(db, p->pHaving, iTable, pEList); + p->pWhere = substExpr(db, p->pWhere, iTable, pEList); + substSelect(db, p->pPrior, iTable, pEList); + pSrc = p->pSrc; + assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ + if( ALWAYS(pSrc) ){ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - substSelect(db, pItem->pSelect, iTable, pEList, 1); - if( pItem->fg.isTabFunc ){ - substExprList(db, pItem->u1.pFuncArg, iTable, pEList); - } + substSelect(db, pItem->pSelect, iTable, pEList); } - }while( doPrior && (p = p->pPrior)!=0 ); + } } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ @@ -112858,7 +103662,7 @@ static void substSelect( ** ** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 ** -** The code generated for this simplification gives the same result +** The code generated for this simpification gives the same result ** but only has to scan the data once. And because indices might ** exist on the table t1, a complete scan of the data might be ** avoided. @@ -112867,10 +103671,7 @@ static void substSelect( ** ** (1) The subquery and the outer query do not both use aggregates. ** -** (2) The subquery is not an aggregate or (2a) the outer query is not a join -** and (2b) the outer query does not use subqueries other than the one -** FROM-clause subquery that is a candidate for flattening. (2b is -** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) +** (2) The subquery is not an aggregate or the outer query is not a join. ** ** (3) The subquery is not the right operand of a left outer join ** (Originally ticket #306. Strengthened by ticket #3300) @@ -112894,10 +103695,8 @@ static void substSelect( ** (9) The subquery does not use LIMIT or the outer query does not use ** aggregates. ** -** (**) Restriction (10) was removed from the code on 2005-02-05 but we -** accidently carried the comment forward until 2014-09-15. Original -** text: "The subquery does not use aggregates or the outer query -** does not use LIMIT." +** (10) The subquery does not use aggregates or the outer query does not +** use LIMIT. ** ** (11) The subquery and the outer query do not both have ORDER BY clauses. ** @@ -112960,11 +103759,6 @@ static void substSelect( ** parent to a compound query confuses the code that handles ** recursive queries in multiSelect(). ** -** (24) The subquery is not an aggregate that uses the built-in min() or -** or max() functions. (Without this restriction, a query like: -** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily -** return the value X for which Y was maximal.) -** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query @@ -112984,7 +103778,7 @@ static int flattenSubquery( int subqueryIsAgg /* True if the subquery uses aggregate functions */ ){ const char *zSavedAuthContext = pParse->zAuthContext; - Select *pParent; /* Current UNION ALL term of the other query */ + Select *pParent; Select *pSub; /* The inner query or "subquery" */ Select *pSub1; /* Pointer to the rightmost select in sub-query */ SrcList *pSrc; /* The FROM clause of the outer query */ @@ -113007,21 +103801,12 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( subqueryIsAgg ){ - if( isAgg ) return 0; /* Restriction (1) */ - if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ - if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) - || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 - || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 - ){ - return 0; /* Restriction (2b) */ - } - } - + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, - ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET + ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** became arbitrary expressions, we were forced to add restrictions (13) ** and (14). */ @@ -113046,14 +103831,8 @@ static int flattenSubquery( if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ return 0; /* Restriction (21) */ } - testcase( pSub->selFlags & SF_Recursive ); - testcase( pSub->selFlags & SF_MinMaxAgg ); - if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){ - return 0; /* Restrictions (22) and (24) */ - } - if( (p->selFlags & SF_Recursive) && pSub->pPrior ){ - return 0; /* Restriction (23) */ - } + if( pSub->selFlags & SF_Recursive ) return 0; /* Restriction (22) */ + if( (p->selFlags & SF_Recursive) && pSub->pPrior ) return 0; /* (23) */ /* OBSOLETE COMMENT 1: ** Restriction 3: If the subquery is a join, make sure the subquery is @@ -113087,7 +103866,7 @@ static int flattenSubquery( ** is fraught with danger. Best to avoid the whole thing. If the ** subquery is the right term of a LEFT JOIN, then do not flatten. */ - if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ + if( (pSubitem->jointype & JT_OUTER)!=0 ){ return 0; } @@ -113107,10 +103886,10 @@ static int flattenSubquery( testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); assert( pSub->pSrc!=0 ); - assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 || (pSub1->pPrior && pSub1->op!=TK_ALL) || pSub1->pSrc->nSrc<1 + || pSub->pEList->nExpr!=pSub1->pEList->nExpr ){ return 0; } @@ -113127,8 +103906,6 @@ static int flattenSubquery( } /***** If we reach this point, flattening is permitted. *****/ - SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", - pSub->zSelName, pSub, iFrom)); /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; @@ -113181,7 +103958,6 @@ static int flattenSubquery( p->pLimit = 0; p->pOffset = 0; pNew = sqlite3SelectDup(db, p, 0); - sqlite3SelectSetName(pNew, pSub->zSelName); p->pOffset = pOffset; p->pLimit = pLimit; p->pOrderBy = pOrderBy; @@ -113194,9 +103970,6 @@ static int flattenSubquery( if( pPrior ) pPrior->pNext = pNew; pNew->pNext = p; p->pPrior = pNew; - SELECTTRACE(2,pParse,p, - ("compound-subquery flattener creates %s.%p as peer\n", - pNew->zSelName, pNew)); } if( db->mallocFailed ) return 1; } @@ -113258,7 +104031,7 @@ static int flattenSubquery( if( pSrc ){ assert( pParent==p ); /* First time through the loop */ - jointype = pSubitem->fg.jointype; + jointype = pSubitem->jointype; }else{ assert( pParent!=p ); /* 2nd and subsequent times through the loop */ pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); @@ -113279,9 +104052,9 @@ static int flattenSubquery( ** ** The outer query has 3 slots in its FROM clause. One slot of the ** outer query (the middle slot) is used by the subquery. The next - ** block of code will expand the outer query FROM clause to 4 slots. - ** The middle slot is expanded to two slots in order to make space - ** for the two elements in the FROM clause of the subquery. + ** block of code will expand the out query to 4 slots. The middle + ** slot is expanded to two slots in order to make space for the + ** two elements in the FROM clause of the subquery. */ if( nSubSrc>1 ){ pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); @@ -113295,11 +104068,10 @@ static int flattenSubquery( */ for(i=0; ia[i+iFrom].pUsing); - assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); pSrc->a[i+iFrom] = pSubSrc->a[i]; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } - pSrc->a[iFrom].fg.jointype = jointype; + pSrc->a[iFrom].jointype = jointype; /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. @@ -113321,39 +104093,36 @@ static int flattenSubquery( pList->a[i].zName = zName; } } - if( pSub->pOrderBy ){ - /* At this point, any non-zero iOrderByCol values indicate that the - ** ORDER BY column expression is identical to the iOrderByCol'th - ** expression returned by SELECT statement pSub. Since these values - ** do not necessarily correspond to columns in SELECT statement pParent, - ** zero them before transfering the ORDER BY clause. - ** - ** Not doing this may cause an error if a subsequent call to this - ** function attempts to flatten a compound sub-query into pParent - ** (the only way this can happen is if the compound sub-query is - ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ - ExprList *pOrderBy = pSub->pOrderBy; - for(i=0; inExpr; i++){ - pOrderBy->a[i].u.x.iOrderByCol = 0; - } - assert( pParent->pOrderBy==0 ); - assert( pSub->pPrior==0 ); - pParent->pOrderBy = pOrderBy; - pSub->pOrderBy = 0; + substExprList(db, pParent->pEList, iParent, pSub->pEList); + if( isAgg ){ + substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); + } + if( pSub->pOrderBy ){ + assert( pParent->pOrderBy==0 ); + pParent->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + }else if( pParent->pOrderBy ){ + substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); + } + if( pSub->pWhere ){ + pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); + }else{ + pWhere = 0; } - pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); if( subqueryIsAgg ){ assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; pParent->pWhere = pWhere; + pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, sqlite3ExprDup(db, pSub->pHaving, 0)); assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ + pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); } - substSelect(db, pParent, iParent, pSub->pEList, 0); /* The flattened query is distinct if either the inner or the ** outer query is distinct. @@ -113377,88 +104146,10 @@ static int flattenSubquery( */ sqlite3SelectDelete(db, pSub1); -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ - SELECTTRACE(0x100,pParse,p,("After flattening:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* -** Make copies of relevant WHERE clause terms of the outer query into -** the WHERE clause of subquery. Example: -** -** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10; -** -** Transformed into: -** -** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) -** WHERE x=5 AND y=10; -** -** The hope is that the terms added to the inner query will make it more -** efficient. -** -** Do not attempt this optimization if: -** -** (1) The inner query is an aggregate. (In that case, we'd really want -** to copy the outer WHERE-clause terms onto the HAVING clause of the -** inner query. But they probably won't help there so do not bother.) -** -** (2) The inner query is the recursive part of a common table expression. -** -** (3) The inner query has a LIMIT clause (since the changes to the WHERE -** close would change the meaning of the LIMIT). -** -** (4) The inner query is the right operand of a LEFT JOIN. (The caller -** enforces this restriction since this routine does not have enough -** information to know.) -** -** (5) The WHERE clause expression originates in the ON or USING clause -** of a LEFT JOIN. -** -** Return 0 if no changes are made and non-zero if one or more WHERE clause -** terms are duplicated into the subquery. -*/ -static int pushDownWhereTerms( - sqlite3 *db, /* The database connection (for malloc()) */ - Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ - Expr *pWhere, /* The WHERE clause of the outer query */ - int iCursor /* Cursor number of the subquery */ -){ - Expr *pNew; - int nChng = 0; - if( pWhere==0 ) return 0; - if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ - return 0; /* restrictions (1) and (2) */ - } - if( pSubq->pLimit!=0 ){ - return 0; /* restriction (3) */ - } - while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); - pWhere = pWhere->pLeft; - } - if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ - if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ - nChng++; - while( pSubq ){ - pNew = sqlite3ExprDup(db, pWhere, 0); - pNew = substExpr(db, pNew, iCursor, pSubq->pEList); - pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew); - pSubq = pSubq->pPrior; - } - } - return nChng; -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - /* ** Based on the contents of the AggInfo structure indicated by the first ** argument, this function checks if the following are true: @@ -113501,7 +104192,7 @@ static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ /* ** The select statement passed as the first argument is an aggregate query. -** The second argument is the associated aggregate-info object. This +** The second argment is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** ** SELECT count(*) FROM @@ -113542,20 +104233,20 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ ** pFrom->pIndex and return SQLITE_OK. */ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ - if( pFrom->pTab && pFrom->fg.isIndexedBy ){ + if( pFrom->pTab && pFrom->zIndex ){ Table *pTab = pFrom->pTab; - char *zIndexedBy = pFrom->u1.zIndexedBy; + char *zIndex = pFrom->zIndex; Index *pIdx; for(pIdx=pTab->pIndex; - pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); + pIdx && sqlite3StrICmp(pIdx->zName, zIndex); pIdx=pIdx->pNext ); if( !pIdx ){ - sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); + sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0); pParse->checkSchema = 1; return SQLITE_ERROR; } - pFrom->pIBIndex = pIdx; + pFrom->pIndex = pIdx; } return SQLITE_OK; } @@ -113611,7 +104302,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ if( pNewSrc==0 ) return WRC_Abort; *pNew = *p; p->pSrc = pNewSrc; - p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); + p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0)); p->op = TK_SELECT; p->pWhere = 0; pNew->pGroupBy = 0; @@ -113619,10 +104310,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ pNew->pOrderBy = 0; p->pPrior = 0; p->pNext = 0; - p->pWith = 0; p->selFlags &= ~SF_Compound; - assert( (p->selFlags & SF_Converted)==0 ); - p->selFlags |= SF_Converted; assert( pNew->pPrior!=0 ); pNew->pPrior->pNext = pNew; pNew->pLimit = 0; @@ -113630,19 +104318,6 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ return WRC_Continue; } -/* -** Check to see if the FROM clause term pFrom has table-valued function -** arguments. If it does, leave an error message in pParse and return -** non-zero, since pFrom is not allowed to be a table-valued function. -*/ -static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){ - if( pFrom->fg.isTabFunc ){ - sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName); - return 1; - } - return 0; -} - #ifndef SQLITE_OMIT_CTE /* ** Argument pWith (which may be NULL) points to a linked list of nested @@ -113655,7 +104330,7 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){ ** object that the returned CTE belongs to. */ static struct Cte *searchWith( - With *pWith, /* Current innermost WITH clause */ + With *pWith, /* Current outermost WITH clause */ struct SrcList_item *pItem, /* FROM clause element to resolve */ With **ppContext /* OUT: WITH clause return value belongs to */ ){ @@ -113686,12 +104361,11 @@ static struct Cte *searchWith( ** statement with which it is associated. */ SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ - assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) ); + assert( bFree==0 || pParse->pWith==0 ); if( pWith ){ - assert( pParse->pWith!=pWith ); pWith->pOuter = pParse->pWith; pParse->pWith = pWith; - if( bFree ) pParse->pWithToFree = pWith; + pParse->bFreeWith = bFree; } } @@ -113730,15 +104404,14 @@ static int withExpand( int bMayRecursive; /* True if compound joined by UNION [ALL] */ With *pSavedWith; /* Initial value of pParse->pWith */ - /* If pCte->zCteErr is non-NULL at this point, then this is an illegal + /* If pCte->zErr is non-NULL at this point, then this is an illegal ** recursive reference to CTE pCte. Leave an error in pParse and return - ** early. If pCte->zCteErr is NULL, then this is not a recursive reference. + ** early. If pCte->zErr is NULL, then this is not a recursive reference. ** In this case, proceed. */ - if( pCte->zCteErr ){ - sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName); + if( pCte->zErr ){ + sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); return SQLITE_ERROR; } - if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR; assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); @@ -113747,7 +104420,7 @@ static int withExpand( pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); - pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; + pTab->tabFlags |= TF_Ephemeral; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( db->mallocFailed ) return SQLITE_NOMEM; assert( pFrom->pSelect ); @@ -113765,7 +104438,7 @@ static int withExpand( && 0==sqlite3StrICmp(pItem->zName, pCte->zName) ){ pItem->pTab = pTab; - pItem->fg.isRecursive = 1; + pItem->isRecursive = 1; pTab->nRef++; pSel->selFlags |= SF_Recursive; } @@ -113781,16 +104454,15 @@ static int withExpand( } assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); - pCte->zCteErr = "circular reference: %s"; + pCte->zErr = "circular reference: %s"; pSavedWith = pParse->pWith; pParse->pWith = pWith; sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); - pParse->pWith = pWith; for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; if( pCte->pCols ){ - if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ + if( pEList->nExpr!=pCte->pCols->nExpr ){ sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", pCte->zName, pEList->nExpr, pCte->pCols->nExpr ); @@ -113800,16 +104472,16 @@ static int withExpand( pEList = pCte->pCols; } - sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); + selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); if( bMayRecursive ){ if( pSel->selFlags & SF_Recursive ){ - pCte->zCteErr = "multiple recursive references: %s"; + pCte->zErr = "multiple recursive references: %s"; }else{ - pCte->zCteErr = "recursive reference in a subquery: %s"; + pCte->zErr = "recursive reference in a subquery: %s"; } sqlite3WalkSelect(pWalker, pSel); } - pCte->zCteErr = 0; + pCte->zErr = 0; pParse->pWith = pSavedWith; } @@ -113850,10 +104522,10 @@ static void selectPopWith(Walker *pWalker, Select *p){ ** fill pTabList->a[].pSelect with a copy of the SELECT statement ** that implements the view. A copy is made of the view's SELECT ** statement so that we can freely modify or delete that statement -** without worrying about messing up the persistent representation +** without worrying about messing up the presistent representation ** of the view. ** -** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword +** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword ** on joins and the ON and USING clause of joins. ** ** (4) Scan the list of columns in the result set (pEList) looking @@ -113881,9 +104553,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } pTabList = p->pSrc; pEList = p->pEList; - if( pWalker->xSelectCallback2==selectPopWith ){ - sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); - } + sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. @@ -113896,9 +104566,17 @@ 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->fg.isRecursive ) continue; - assert( pFrom->pTab==0 ); + assert( pFrom->isRecursive==0 || pFrom->pTab ); + if( pFrom->isRecursive ) continue; + if( pFrom->pTab!=0 ){ + /* This statement has already been prepared. There is no need + ** to go further. */ + assert( i==0 ); +#ifndef SQLITE_OMIT_CTE + selectPopWith(pWalker, p); +#endif + return WRC_Prune; + } #ifndef SQLITE_OMIT_CTE if( withExpand(pWalker, pFrom) ) return WRC_Abort; if( pFrom->pTab ) {} else @@ -113909,13 +104587,13 @@ static int selectExpander(Walker *pWalker, Select *p){ /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); - if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; + sqlite3WalkSelect(pWalker, pSel); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } - sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); + selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral; @@ -113932,20 +104610,13 @@ static int selectExpander(Walker *pWalker, Select *p){ return WRC_Abort; } pTab->nRef++; - if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ - return WRC_Abort; - } #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) - if( IsVirtual(pTab) || pTab->pSelect ){ - i16 nCol; + if( pTab->pSelect || IsVirtual(pTab) ){ + /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); - sqlite3SelectSetName(pFrom->pSelect, pTab->zName); - nCol = pTab->nCol; - pTab->nCol = -1; sqlite3WalkSelect(pWalker, pFrom->pSelect); - pTab->nCol = nCol; } #endif } @@ -113965,20 +104636,19 @@ static int selectExpander(Walker *pWalker, Select *p){ /* For every "*" that occurs in the column list, insert the names of ** all columns in all tables. And for every TABLE.* insert the names ** of all columns in TABLE. The parser inserted a special expression - ** with the TK_ASTERISK operator for each "*" that it found in the column - ** list. The following code just has to locate the TK_ASTERISK - ** expressions and expand each one to the list of all columns in - ** all tables. + ** with the TK_ALL operator for each "*" that it found in the column list. + ** The following code just has to locate the TK_ALL expressions and expand + ** each one to the list of all columns in all tables. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for(k=0; knExpr; k++){ pE = pEList->a[k].pExpr; - if( pE->op==TK_ASTERISK ) break; + if( pE->op==TK_ALL ) break; assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); - if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; + if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; } if( knExpr ){ /* @@ -113992,13 +104662,18 @@ static int selectExpander(Walker *pWalker, Select *p){ int longNames = (flags & SQLITE_FullColNames)!=0 && (flags & SQLITE_ShortColNames)==0; + /* When processing FROM-clause subqueries, it is always the case + ** that full_column_names=OFF and short_column_names=ON. The + ** sqlite3ResultSetOfSelect() routine makes it so. */ + assert( (p->selFlags & SF_NestedFrom)==0 + || ((flags & SQLITE_FullColNames)==0 && + (flags & SQLITE_ShortColNames)!=0) ); + for(k=0; knExpr; k++){ pE = a[k].pExpr; pRight = pE->pRight; assert( pE->op!=TK_DOT || pRight!=0 ); - if( pE->op!=TK_ASTERISK - && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) - ){ + if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); @@ -114050,19 +104725,18 @@ static int selectExpander(Walker *pWalker, Select *p){ 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 a column is marked as 'hidden' (currently only possible + ** for virtual tables), do not include it in the expanded + ** result-set list. */ - if( (p->selFlags & SF_IncludeHidden)==0 - && IsHiddenColumn(&pTab->aCol[j]) - ){ + if( IsHiddenColumn(&pTab->aCol[j]) ){ + assert(IsVirtual(pTab)); continue; } tableSeen = 1; if( i>0 && zTName==0 ){ - if( (pFrom->fg.jointype & JT_NATURAL)!=0 + if( (pFrom->jointype & JT_NATURAL)!=0 && tableAndColumnIndex(pTabList, i, zName, 0, 0) ){ /* In a NATURAL join, omit the join columns from the @@ -114127,7 +104801,6 @@ static int selectExpander(Walker *pWalker, Select *p){ #if SQLITE_MAX_COLUMN if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); - return WRC_Abort; } #endif return WRC_Continue; @@ -114142,7 +104815,7 @@ static int selectExpander(Walker *pWalker, Select *p){ ** Walker.xSelectCallback is set to do something useful for every ** subquery in the parser tree. */ -SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ +static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ UNUSED_PARAMETER2(NotUsed, NotUsed2); return WRC_Continue; } @@ -114163,16 +104836,14 @@ SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; memset(&w, 0, sizeof(w)); - w.xExprCallback = sqlite3ExprWalkNoop; + w.xExprCallback = exprWalkNoop; w.pParse = pParse; if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; - if( (pSelect->selFlags & SF_MultiValue)==0 ){ - w.xSelectCallback2 = selectPopWith; - } + w.xSelectCallback2 = selectPopWith; sqlite3WalkSelect(&w, pSelect); } @@ -114198,19 +104869,19 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ struct SrcList_item *pFrom; assert( p->selFlags & SF_Resolved ); - assert( (p->selFlags & SF_HasTypeInfo)==0 ); - p->selFlags |= SF_HasTypeInfo; - pParse = pWalker->pParse; - pTabList = p->pSrc; - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - assert( pTab!=0 ); - if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ - /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->pSelect; - if( pSel ){ - while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab, pSel); + if( (p->selFlags & SF_HasTypeInfo)==0 ){ + p->selFlags |= SF_HasTypeInfo; + pParse = pWalker->pParse; + pTabList = p->pSrc; + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ + /* A sub-query in the FROM clause of a SELECT */ + Select *pSel = pFrom->pSelect; + if( pSel ){ + while( pSel->pPrior ) pSel = pSel->pPrior; + selectAddColumnTypeAndCollation(pParse, pTab, pSel); + } } } } @@ -114230,7 +104901,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ Walker w; memset(&w, 0, sizeof(w)); w.xSelectCallback2 = selectAddSubqueryTypeInfo; - w.xExprCallback = sqlite3ExprWalkNoop; + w.xExprCallback = exprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(&w, pSelect); #endif @@ -114349,15 +105020,14 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); + sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); - testcase( nArg==0 ); /* Error condition */ - testcase( nArg>1 ); /* Also an error */ + assert( nArg==1 ); codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); } if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ @@ -114374,7 +105044,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem, + sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, (void*)pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); @@ -114457,7 +105127,7 @@ SQLITE_PRIVATE int sqlite3Select( WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ Vdbe *v; /* The virtual machine under construction */ int isAgg; /* True for select lists like "count(*)" */ - ExprList *pEList = 0; /* List of columns to extract. */ + ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ @@ -114480,13 +105150,6 @@ SQLITE_PRIVATE int sqlite3Select( } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); -#if SELECTTRACE_ENABLED - pParse->nSelectIndent++; - SELECTTRACE(1,pParse,p, ("begin processing:\n")); - if( sqlite3SelectTrace & 0x100 ){ - sqlite3TreeViewSelect(0, p, 0); - } -#endif assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); @@ -114507,90 +105170,36 @@ SQLITE_PRIVATE int sqlite3Select( memset(&sSort, 0, sizeof(sSort)); sSort.pOrderBy = p->pOrderBy; pTabList = p->pSrc; + pEList = p->pEList; if( pParse->nErr || db->mallocFailed ){ goto select_end; } - assert( p->pEList!=0 ); isAgg = (p->selFlags & SF_Aggregate)!=0; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ - SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif + assert( pEList!=0 ); + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ #ifndef SQLITE_OMIT_SUBQUERY - if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){ + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ goto select_end; } #endif - /* Try to flatten subqueries in the FROM clause up into the main query - */ -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - for(i=0; !p->pPrior && inSrc; i++){ - struct SrcList_item *pItem = &pTabList->a[i]; - Select *pSub = pItem->pSelect; - int isAggSub; - Table *pTab = pItem->pTab; - if( pSub==0 ) continue; - - /* Catch mismatch in the declared columns of a view and the number of - ** columns in the SELECT on the RHS */ - if( pTab->nCol!=pSub->pEList->nExpr ){ - sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", - pTab->nCol, pTab->zName, pSub->pEList->nExpr); - goto select_end; - } - - isAggSub = (pSub->selFlags & SF_Aggregate)!=0; - if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ - /* This subquery can be absorbed into its parent. */ - if( isAggSub ){ - isAgg = 1; - p->selFlags |= SF_Aggregate; - } - i = -1; - } - pTabList = p->pSrc; - if( db->mallocFailed ) goto select_end; - if( !IgnorableOrderby(pDest) ){ - sSort.pOrderBy = p->pOrderBy; - } - } -#endif - - /* Get a pointer the VDBE under construction, allocating a new VDBE if one - ** does not already exist */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto select_end; - -#ifndef SQLITE_OMIT_COMPOUND_SELECT - /* Handle compound SELECT statements using the separate multiSelect() - ** procedure. - */ - if( p->pPrior ){ - rc = multiSelect(pParse, p, pDest); - explainSetInteger(pParse->iSelectId, iRestoreSelectId); -#if SELECTTRACE_ENABLED - SELECTTRACE(1,pParse,p,("end compound-select processing\n")); - pParse->nSelectIndent--; -#endif - return rc; - } -#endif - /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - for(i=0; inSrc; i++){ + for(i=0; !p->pPrior && inSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub = pItem->pSelect; + int isAggSub; + if( pSub==0 ) continue; /* Sometimes the code for a subquery will be generated more than @@ -114600,7 +105209,7 @@ SQLITE_PRIVATE int sqlite3Select( ** is sufficient, though the subroutine to manifest the view does need ** to be invoked again. */ if( pItem->addrFillSub ){ - if( pItem->fg.viaCoroutine==0 ){ + if( pItem->viaCoroutine==0 ){ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); } continue; @@ -114615,25 +105224,16 @@ SQLITE_PRIVATE int sqlite3Select( */ pParse->nHeight += sqlite3SelectExprHeight(p); - /* Make copies of constant WHERE-clause terms in the outer query down - ** inside the subquery. This can help the subquery to run more efficiently. - */ - if( (pItem->fg.jointype & JT_OUTER)==0 - && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor) - ){ -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ - SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); - sqlite3TreeViewSelect(0, p, 0); + isAggSub = (pSub->selFlags & SF_Aggregate)!=0; + if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ + /* This subquery can be absorbed into its parent. */ + if( isAggSub ){ + isAgg = 1; + p->selFlags |= SF_Aggregate; } -#endif - } - - /* Generate code to implement the subquery - */ - if( pTabList->nSrc==1 - && (p->selFlags & SF_All)==0 - && OptimizationEnabled(db, SQLITE_SubqCoroutine) + i = -1; + }else if( pTabList->nSrc==1 + && OptimizationEnabled(db, SQLITE_SubqCoroutine) ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. @@ -114647,7 +105247,7 @@ SQLITE_PRIVATE int sqlite3Select( explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); - pItem->fg.viaCoroutine = 1; + pItem->viaCoroutine = 1; pItem->regResult = dest.iSdst; sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); sqlite3VdbeJumpHere(v, addrTop-1); @@ -114665,7 +105265,7 @@ SQLITE_PRIVATE int sqlite3Select( pItem->regReturn = ++pParse->nMem; topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); pItem->addrFillSub = topAddr+1; - if( pItem->fg.isCorrelated==0 ){ + if( pItem->isCorrelated==0 ){ /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ @@ -114684,23 +105284,29 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeChangeP1(v, topAddr, retAddr); sqlite3ClearTempRegCache(pParse); } - if( db->mallocFailed ) goto select_end; + if( /*pParse->nErr ||*/ db->mallocFailed ){ + goto select_end; + } pParse->nHeight -= sqlite3SelectExprHeight(p); + pTabList = p->pSrc; + if( !IgnorableOrderby(pDest) ){ + sSort.pOrderBy = p->pOrderBy; + } } -#endif - - /* Various elements of the SELECT copied into local variables for - ** convenience */ pEList = p->pEList; +#endif pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x400 ){ - SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n")); - sqlite3TreeViewSelect(0, p, 0); +#ifndef SQLITE_OMIT_COMPOUND_SELECT + /* If there is are a sequence of queries, do the earlier ones first. + */ + if( p->pPrior ){ + rc = multiSelect(pParse, p, pDest); + explainSetInteger(pParse->iSelectId, iRestoreSelectId); + return rc; } #endif @@ -114712,7 +105318,7 @@ SQLITE_PRIVATE int sqlite3Select( ** ** is transformed to: ** - ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz + ** SELECT xyz FROM ... GROUP BY xyz ** ** The second form is preferred as a single index (or temp-table) may be ** used for both the ORDER BY and DISTINCT processing. As originally @@ -114720,33 +105326,33 @@ SQLITE_PRIVATE int sqlite3Select( ** BY and DISTINCT, and an index or separate temp-table for the other. */ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct - && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 + && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0 ){ p->selFlags &= ~SF_Distinct; - pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); + p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); + pGroupBy = p->pGroupBy; + sSort.pOrderBy = 0; /* Notice that even thought SF_Distinct has been cleared from p->selFlags, ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ assert( sDistinct.isTnct ); } - /* If there is an ORDER BY clause, then create an ephemeral index to - ** do the sorting. But this sorting ephemeral index might end up - ** being unused if the data can be extracted in pre-sorted order. - ** If that is the case, then the OP_OpenEphemeral instruction will be - ** changed to an OP_Noop once we figure out that the sorting index is - ** not needed. The sSort.addrSortIndex variable is used to facilitate - ** that change. + /* If there is an ORDER BY clause, then this sorting + ** index might end up being unused if the data can be + ** extracted in pre-sorted order. If that is the case, then the + ** OP_OpenEphemeral instruction will be changed to an OP_Noop once + ** we figure out that the sorting index is not needed. The addrSortIndex + ** variable is used to facilitate that change. */ if( sSort.pOrderBy ){ KeyInfo *pKeyInfo; - pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); + pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0); sSort.iECursor = pParse->nTab++; sSort.addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, - (char*)pKeyInfo, P4_KEYINFO - ); + sSort.iECursor, sSort.pOrderBy->nExpr+2, 0, + (char*)pKeyInfo, P4_KEYINFO); }else{ sSort.addrSortIndex = -1; } @@ -114763,18 +105369,18 @@ SQLITE_PRIVATE int sqlite3Select( p->nSelectRow = LARGEST_INT64; computeLimitRegisters(pParse, p, iEnd); if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ - sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); + sqlite3VdbeGetOp(v, sSort.addrSortIndex)->opcode = OP_SorterOpen; sSort.sortFlags |= SORTFLAG_UseSorter; } - /* Open an ephemeral index to use for the distinct set. + /* Open a virtual index to use for the distinct set. */ if( p->selFlags & SF_Distinct ){ sDistinct.tabTnct = pParse->nTab++; sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sDistinct.tabTnct, 0, 0, - (char*)keyInfoFromExprList(pParse, p->pEList,0,0), - P4_KEYINFO); + sDistinct.tabTnct, 0, 0, + (char*)keyInfoFromExprList(pParse, p->pEList,0,0), + P4_KEYINFO); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; }else{ @@ -114852,10 +105458,11 @@ SQLITE_PRIVATE int sqlite3Select( p->nSelectRow = 1; } + /* If there is both a GROUP BY and an ORDER BY clause and they are ** identical, then it may be possible to disable the ORDER BY clause ** on the grounds that the GROUP BY will cause elements to come out - ** in the correct order. It also may not - the GROUP BY might use a + ** in the correct order. It also may not - the GROUP BY may use a ** database index that causes rows to be grouped together as required ** but not actually sorted. Either way, record the fact that the ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp @@ -114876,7 +105483,7 @@ SQLITE_PRIVATE int sqlite3Select( sNC.pSrcList = pTabList; sNC.pAggInfo = &sAggInfo; sAggInfo.mnReg = pParse->nMem+1; - sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; sAggInfo.pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(&sNC, pEList); sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); @@ -114898,7 +105505,7 @@ SQLITE_PRIVATE int sqlite3Select( */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int addr1; /* A-vs-B comparision jump */ + int j1; /* A-vs-B comparision jump */ int addrOutputRow; /* Start of subroutine that outputs a result row */ int regOutputRow; /* Return address register for output subroutine */ int addrSetAbort; /* Set the abort flag and return */ @@ -114913,7 +105520,7 @@ SQLITE_PRIVATE int sqlite3Select( ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; - pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0); addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 0, (char*)pKeyInfo, P4_KEYINFO); @@ -114969,8 +105576,8 @@ SQLITE_PRIVATE int sqlite3Select( groupBySort = 1; nGroupBy = pGroupBy->nExpr; - nCol = nGroupBy; - j = nGroupBy; + nCol = nGroupBy + 1; + j = nGroupBy+1; for(i=0; i=j ){ nCol++; @@ -114979,14 +105586,20 @@ SQLITE_PRIVATE int sqlite3Select( } regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCacheClear(pParse); - sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); - j = nGroupBy; + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); + sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); + j = nGroupBy+1; for(i=0; iiSorterColumn>=j ){ int r1 = j + regBase; - sqlite3ExprCodeGetColumnToReg(pParse, - pCol->pTab, pCol->iColumn, pCol->iTable, r1); + int r2; + + r2 = sqlite3ExprCodeGetColumn(pParse, + pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); + if( r1!=r2 ){ + sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); + } j++; } } @@ -115028,12 +105641,12 @@ SQLITE_PRIVATE int sqlite3Select( addrTopOfLoop = sqlite3VdbeCurrentAddr(v); sqlite3ExprCacheClear(pParse); if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, - sortOut, sortPTab); + sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut); } for(j=0; jnExpr; j++){ if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); + if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); }else{ sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); @@ -115041,8 +105654,8 @@ SQLITE_PRIVATE int sqlite3Select( } sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - addr1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v); + j1 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v); /* Generate code that runs whenever the GROUP BY changes. ** Changes in the GROUP BY are detected by the previous code @@ -115064,7 +105677,7 @@ SQLITE_PRIVATE int sqlite3Select( /* Update the aggregate accumulators based on the content of ** the current row */ - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); @@ -115086,7 +105699,7 @@ SQLITE_PRIVATE int sqlite3Select( /* Jump over the subroutines */ - sqlite3VdbeGoto(v, addrEnd); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd); /* Generate a subroutine that outputs a single row of the result ** set. This subroutine first looks at the iUseFlag. If iUseFlag @@ -115101,8 +105714,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeResolveLabel(v, addrOutputRow); addrOutputRow = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); - VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); @@ -115240,7 +105852,7 @@ SQLITE_PRIVATE int sqlite3Select( updateAccumulator(pParse, &sAggInfo); assert( pMinMax==0 || pMinMax->nExpr==1 ); if( sqlite3WhereIsOrdered(pWInfo)>0 ){ - sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo)); VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); } @@ -115266,8 +105878,7 @@ SQLITE_PRIVATE int sqlite3Select( ** and send them to the callback one by one. */ if( sSort.pOrderBy ){ - explainTempTable(pParse, - sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); + explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); } @@ -115275,9 +105886,10 @@ SQLITE_PRIVATE int sqlite3Select( */ sqlite3VdbeResolveLabel(v, iEnd); - /* The SELECT has been coded. If there is an error in the Parse structure, - ** set the return code to 1. Otherwise 0. */ - rc = (pParse->nErr>0); + /* The SELECT was successfully coded. Set the return code to 0 + ** to indicate no errors. + */ + rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. @@ -115293,13 +105905,104 @@ select_end: sqlite3DbFree(db, sAggInfo.aCol); sqlite3DbFree(db, sAggInfo.aFunc); -#if SELECTTRACE_ENABLED - SELECTTRACE(1,pParse,p,("end processing\n")); - pParse->nSelectIndent--; -#endif return rc; } +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) +/* +** Generate a human-readable description of a the Select object. +*/ +static void explainOneSelect(Vdbe *pVdbe, Select *p){ + sqlite3ExplainPrintf(pVdbe, "SELECT "); + if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ + if( p->selFlags & SF_Distinct ){ + sqlite3ExplainPrintf(pVdbe, "DISTINCT "); + } + if( p->selFlags & SF_Aggregate ){ + sqlite3ExplainPrintf(pVdbe, "agg_flag "); + } + sqlite3ExplainNL(pVdbe); + sqlite3ExplainPrintf(pVdbe, " "); + } + sqlite3ExplainExprList(pVdbe, p->pEList); + sqlite3ExplainNL(pVdbe); + if( p->pSrc && p->pSrc->nSrc ){ + int i; + sqlite3ExplainPrintf(pVdbe, "FROM "); + sqlite3ExplainPush(pVdbe); + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + sqlite3ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor); + if( pItem->pSelect ){ + sqlite3ExplainSelect(pVdbe, pItem->pSelect); + if( pItem->pTab ){ + sqlite3ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName); + } + }else if( pItem->zName ){ + sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName); + } + if( pItem->zAlias ){ + sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias); + } + if( pItem->jointype & JT_LEFT ){ + sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN"); + } + sqlite3ExplainNL(pVdbe); + } + sqlite3ExplainPop(pVdbe); + } + if( p->pWhere ){ + sqlite3ExplainPrintf(pVdbe, "WHERE "); + sqlite3ExplainExpr(pVdbe, p->pWhere); + sqlite3ExplainNL(pVdbe); + } + if( p->pGroupBy ){ + sqlite3ExplainPrintf(pVdbe, "GROUPBY "); + sqlite3ExplainExprList(pVdbe, p->pGroupBy); + sqlite3ExplainNL(pVdbe); + } + if( p->pHaving ){ + sqlite3ExplainPrintf(pVdbe, "HAVING "); + sqlite3ExplainExpr(pVdbe, p->pHaving); + sqlite3ExplainNL(pVdbe); + } + if( p->pOrderBy ){ + sqlite3ExplainPrintf(pVdbe, "ORDERBY "); + sqlite3ExplainExprList(pVdbe, p->pOrderBy); + sqlite3ExplainNL(pVdbe); + } + if( p->pLimit ){ + sqlite3ExplainPrintf(pVdbe, "LIMIT "); + sqlite3ExplainExpr(pVdbe, p->pLimit); + sqlite3ExplainNL(pVdbe); + } + if( p->pOffset ){ + sqlite3ExplainPrintf(pVdbe, "OFFSET "); + sqlite3ExplainExpr(pVdbe, p->pOffset); + sqlite3ExplainNL(pVdbe); + } +} +SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ + if( p==0 ){ + sqlite3ExplainPrintf(pVdbe, "(null-select)"); + return; + } + sqlite3ExplainPush(pVdbe); + while( p ){ + explainOneSelect(pVdbe, p); + p = p->pNext; + if( p==0 ) break; + sqlite3ExplainNL(pVdbe); + sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op)); + } + sqlite3ExplainPrintf(pVdbe, "END"); + sqlite3ExplainPop(pVdbe); +} + +/* End of the structure debug printing code +*****************************************************************************/ +#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */ + /************** End of select.c **********************************************/ /************** Begin file table.c *******************************************/ /* @@ -115320,7 +106023,6 @@ select_end: ** These routines are in a separate files so that they will not be linked ** if they are not used. */ -/* #include "sqliteInt.h" */ /* #include */ /* #include */ @@ -115333,10 +106035,10 @@ select_end: typedef struct TabResult { char **azResult; /* Accumulated output */ char *zErrMsg; /* Error message text, if an error occurs */ - u32 nAlloc; /* Slots allocated for azResult[] */ - u32 nRow; /* Number of rows in the result */ - u32 nColumn; /* Number of columns in the result */ - u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */ + int nAlloc; /* Slots allocated for azResult[] */ + int nRow; /* Number of rows in the result */ + int nColumn; /* Number of columns in the result */ + int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */ int rc; /* Return code from sqlite3_exec() */ } TabResult; @@ -115362,7 +106064,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ if( p->nData + need > p->nAlloc ){ char **azNew; p->nAlloc = p->nAlloc*2 + need; - azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc ); + azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc ); if( azNew==0 ) goto malloc_failed; p->azResult = azNew; } @@ -115377,7 +106079,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ if( z==0 ) goto malloc_failed; p->azResult[p->nData++] = z; } - }else if( (int)p->nColumn!=nCol ){ + }else if( p->nColumn!=nCol ){ sqlite3_free(p->zErrMsg); p->zErrMsg = sqlite3_mprintf( "sqlite3_get_table() called with two or more incompatible queries" @@ -115394,7 +106096,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ z = 0; }else{ int n = sqlite3Strlen30(argv[i])+1; - z = sqlite3_malloc64( n ); + z = sqlite3_malloc( n ); if( z==0 ) goto malloc_failed; memcpy(z, argv[i], n); } @@ -115419,7 +106121,7 @@ malloc_failed: ** Instead, the entire table should be passed to sqlite3_free_table() when ** the calling procedure is finished using it. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_table( +SQLITE_API int sqlite3_get_table( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ @@ -115430,9 +106132,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( int rc; TabResult res; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; -#endif *pazResult = 0; if( pnColumn ) *pnColumn = 0; if( pnRow ) *pnRow = 0; @@ -115443,7 +106142,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( res.nData = 1; res.nAlloc = 20; res.rc = SQLITE_OK; - res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); + res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc ); if( res.azResult==0 ){ db->errCode = SQLITE_NOMEM; return SQLITE_NOMEM; @@ -115471,7 +106170,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( } if( res.nAlloc>res.nData ){ char **azNew; - azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData ); + azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData ); if( azNew==0 ){ sqlite3_free_table(&res.azResult[1]); db->errCode = SQLITE_NOMEM; @@ -115488,8 +106187,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_table( /* ** This routine frees the space the sqlite3_get_table() malloced. */ -SQLITE_API void SQLITE_STDCALL sqlite3_free_table( - char **azResult /* Result returned from sqlite3_get_table() */ +SQLITE_API void sqlite3_free_table( + char **azResult /* Result returned from from sqlite3_get_table() */ ){ if( azResult ){ int i, n; @@ -115517,7 +106216,6 @@ SQLITE_API void SQLITE_STDCALL sqlite3_free_table( ************************************************************************* ** This file contains the implementation for TRIGGERs */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_TRIGGER /* @@ -115634,7 +106332,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( ** ^^^^^^^^ ** ** To maintain backwards compatibility, ignore the database - ** name on pTableName if we are reparsing out of SQLITE_MASTER. + ** name on pTableName if we are reparsing our of SQLITE_MASTER. */ if( db->init.busy && iDb!=1 ){ sqlite3DbFree(db, pTableName->a[0].zDatabase); @@ -115687,7 +106385,8 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), + zName, sqlite3Strlen30(zName)) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ @@ -115700,6 +106399,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); + pParse->nErr++; goto trigger_cleanup; } @@ -115829,12 +106529,13 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pTrig = sqlite3HashInsert(pHash, zName, pTrig); + pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); if( pTrig ){ db->mallocFailed = 1; }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; - pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); + int n = sqlite3Strlen30(pLink->table); + pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); assert( pTab!=0 ); pLink->pNext = pTab->pTrigger; pTab->pTrigger = pLink; @@ -115879,12 +106580,12 @@ static TriggerStep *triggerStepAllocate( ){ TriggerStep *pTriggerStep; - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; memcpy(z, pName->z, pName->n); - sqlite3Dequote(z); - pTriggerStep->zTarget = z; + pTriggerStep->target.z = z; + pTriggerStep->target.n = pName->n; pTriggerStep->op = op; } return pTriggerStep; @@ -115993,6 +106694,7 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) int i; const char *zDb; const char *zName; + int nName; sqlite3 *db = pParse->db; if( db->mallocFailed ) goto drop_trigger_cleanup; @@ -116003,12 +106705,13 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; + nName = sqlite3Strlen30(zName); assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); + pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } if( !pTrigger ){ @@ -116031,7 +106734,8 @@ drop_trigger_cleanup: ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); + int n = sqlite3Strlen30(pTrigger->table); + return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); } @@ -116066,12 +106770,31 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ */ assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName - ); + int base; + static const int iLn = VDBE_OFFSET_LINENO(2); + static const VdbeOpList dropTrigger[] = { + { OP_Rewind, 0, ADDR(9), 0}, + { OP_String8, 0, 1, 0}, /* 1 */ + { OP_Column, 0, 1, 2}, + { OP_Ne, 2, ADDR(8), 1}, + { OP_String8, 0, 1, 0}, /* 4: "trigger" */ + { OP_Column, 0, 0, 2}, + { OP_Ne, 2, ADDR(8), 1}, + { OP_Delete, 0, 0, 0}, + { OP_Next, 0, ADDR(1), 0}, /* 8 */ + }; + + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3OpenMasterTable(pParse, iDb); + base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn); + sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT); + sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddOp2(v, OP_Close, 0, 0); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); + if( pParse->nMem<3 ){ + pParse->nMem = 3; + } } } @@ -116084,7 +106807,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const ch assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &(db->aDb[iDb].pSchema->trigHash); - pTrigger = sqlite3HashInsert(pHash, zName, 0); + pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); @@ -116148,7 +106871,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist( } /* -** Convert the pStep->zTarget string into a SrcList and return a pointer +** Convert the pStep->target token into a SrcList and return a pointer ** to that SrcList. ** ** This routine adds a specific database name, if needed, to the target when @@ -116161,17 +106884,17 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ - sqlite3 *db = pParse->db; int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - pSrc = sqlite3SrcListAppend(db, 0, 0, 0); + pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); - pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); - iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); + assert( pSrc->a!=0 ); + iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ - assert( iDbnDb ); + sqlite3 *db = pParse->db; + assert( iDbdb->nDb ); pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); } } @@ -116283,7 +107006,6 @@ static void transferParseError(Parse *pTo, Parse *pFrom){ if( pTo->nErr==0 ){ pTo->zErrMsg = pFrom->zErrMsg; pTo->nErr = pFrom->nErr; - pTo->rc = pFrom->rc; }else{ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); } @@ -116622,7 +107344,6 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask( ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ @@ -116744,9 +107465,9 @@ SQLITE_PRIVATE void sqlite3Update( /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ - int regOldRowid = 0; /* The old rowid */ - int regNewRowid = 0; /* The new rowid */ - int regNew = 0; /* Content of the NEW.* table in triggers */ + int regOldRowid; /* The old rowid */ + int regNewRowid; /* The new rowid */ + int regNew; /* Content of the NEW.* table in triggers */ int regOld = 0; /* Content of OLD.* table in triggers */ int regRowSet = 0; /* Rowset of rows to be updated */ int regKey = 0; /* composite PRIMARY KEY value */ @@ -116873,20 +107594,16 @@ SQLITE_PRIVATE void sqlite3Update( assert( chngPk==0 || chngPk==1 ); chngKey = chngRowid + chngPk; - /* The SET expressions are not actually used inside the WHERE loop. - ** So reset the colUsed mask. Unless this is a virtual table. In that - ** case, set all bits of the colUsed mask (to ensure that the virtual - ** table implementation makes all columns available). + /* The SET expressions are not actually used inside the WHERE loop. + ** So reset the colUsed mask */ - pTabList->a[0].colUsed = IsVirtual(pTab) ? (Bitmask)-1 : 0; + pTabList->a[0].colUsed = 0; hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); /* There is one entry in the aRegIdx[] array for each index on the table ** being updated. Fill in aRegIdx[] with a register number that will hold - ** the key for accessing each index. - ** - ** FIXME: Be smarter about omitting indexes that use expressions. + ** the key for accessing each index. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; @@ -116895,8 +107612,7 @@ SQLITE_PRIVATE void sqlite3Update( }else{ reg = 0; for(i=0; inKeyCol; i++){ - i16 iIdxCol = pIdx->aiColumn[i]; - if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ + if( aXRef[pIdx->aiColumn[i]]>=0 ){ reg = ++pParse->nMem; break; } @@ -116912,20 +107628,29 @@ SQLITE_PRIVATE void sqlite3Update( if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, iDb); +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Virtual tables must be handled separately */ + if( IsVirtual(pTab) ){ + updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, + pWhere, onError); + pWhere = 0; + pTabList = 0; + goto update_cleanup; + } +#endif + /* Allocate required registers. */ - if( !IsVirtual(pTab) ){ - regRowSet = ++pParse->nMem; - regOldRowid = regNewRowid = ++pParse->nMem; - if( chngPk || pTrigger || hasFK ){ - regOld = pParse->nMem + 1; - pParse->nMem += pTab->nCol; - } - if( chngKey || pTrigger || hasFK ){ - regNewRowid = ++pParse->nMem; - } - regNew = pParse->nMem + 1; + regRowSet = ++pParse->nMem; + regOldRowid = regNewRowid = ++pParse->nMem; + if( chngPk || pTrigger || hasFK ){ + regOld = pParse->nMem + 1; pParse->nMem += pTab->nCol; } + if( chngKey || pTrigger || hasFK ){ + regNewRowid = ++pParse->nMem; + } + regNew = pParse->nMem + 1; + pParse->nMem += pTab->nCol; /* Start the view context. */ if( isView ){ @@ -116933,7 +107658,7 @@ SQLITE_PRIVATE void sqlite3Update( } /* If we are trying to update a view, realize that view into - ** an ephemeral table. + ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ @@ -116948,15 +107673,6 @@ SQLITE_PRIVATE void sqlite3Update( goto update_cleanup; } -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Virtual tables must be handled separately */ - if( IsVirtual(pTab) ){ - updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, - pWhere, onError); - goto update_cleanup; - } -#endif - /* Begin the database scan */ if( HasRowid(pTab) ){ @@ -116996,7 +107712,6 @@ SQLITE_PRIVATE void sqlite3Update( if( pWInfo==0 ) goto update_cleanup; okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); for(i=0; iaiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], iPk+i); } @@ -117006,7 +107721,7 @@ SQLITE_PRIVATE void sqlite3Update( regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(db, pPk), nPk); + sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); } sqlite3WhereEnd(pWInfo); @@ -117041,21 +107756,20 @@ SQLITE_PRIVATE void sqlite3Update( if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; } - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen, 0, 0); } /* Top of the update loop */ if( okOnePass ){ - if( aToOpen[iDataCur-iBaseCur] && !isView ){ - assert( pPk ); + if( aToOpen[iDataCur-iBaseCur] ){ + assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); VdbeCoverageNeverTaken(v); } labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); - VdbeCoverageIf(v, pPk==0); - VdbeCoverageIf(v, pPk!=0); + VdbeCoverage(v); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); @@ -117104,7 +107818,7 @@ SQLITE_PRIVATE void sqlite3Update( } /* Populate the array of registers beginning at regNew with the new - ** row data. This array is used to check constants, create the new + ** row data. This array is used to check constaints, create the new ** table and index records, and as the values for any new.* references ** made by triggers. ** @@ -117119,6 +107833,7 @@ SQLITE_PRIVATE void sqlite3Update( newmask = sqlite3TriggerColmask( pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); + /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ for(i=0; inCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); @@ -117134,7 +107849,7 @@ SQLITE_PRIVATE void sqlite3Update( */ testcase( i==31 ); testcase( i==32 ); - sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } @@ -117176,7 +107891,7 @@ SQLITE_PRIVATE void sqlite3Update( } if( !isView ){ - int addr1 = 0; /* Address of jump instruction */ + int j1 = 0; /* Address of jump instruction */ int bReplace = 0; /* True if REPLACE conflict resolution might happen */ /* Do constraint checks. */ @@ -117192,20 +107907,20 @@ SQLITE_PRIVATE void sqlite3Update( /* Delete the index entries associated with the current record. */ if( bReplace || chngKey ){ if( pPk ){ - addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); + j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); }else{ - addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); + j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); } VdbeCoverageNeverTaken(v); } - sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); + sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); /* If changing the record number, delete the old record. */ if( hasFK || chngKey || pPk!=0 ){ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } if( bReplace || chngKey ){ - sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeJumpHere(v, j1); } if( hasFK ){ @@ -117242,7 +107957,7 @@ SQLITE_PRIVATE void sqlite3Update( sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ - sqlite3VdbeGoto(v, labelContinue); + sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); @@ -117283,7 +107998,7 @@ update_cleanup: return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise -** they may interfere with compilation of other functions in this file +** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView @@ -117296,23 +108011,21 @@ update_cleanup: /* ** Generate code for an UPDATE of a virtual table. ** -** There are two possible strategies - the default and the special -** "onepass" strategy. Onepass is only used if the virtual table -** implementation indicates that pWhere may match at most one row. -** -** The default strategy is to create an ephemeral table that contains +** The strategy is that we create an ephemerial table that contains ** for each row to be changed: ** ** (A) The original rowid of that row. -** (B) The revised rowid for the row. +** (B) The revised rowid for the row. (note1) ** (C) The content of every column in the row. ** -** Then loop through the contents of this ephemeral table executing a -** VUpdate for each row. When finished, drop the ephemeral table. +** Then we loop over this ephemeral table and for each row in +** the ephermeral table call VUpdate. ** -** The "onepass" strategy does not use an ephemeral table. Instead, it -** stores the same values (A, B and C above) in a register array and -** makes a single invocation of VUpdate. +** When finished, drop the ephemeral table. +** +** (note1) Actually, if we know in advance that (A) is always the same +** as (B) we only store (A), then duplicate (A) when pulling +** it out of the ephemeral table before calling VUpdate. */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ @@ -117325,96 +108038,68 @@ static void updateVirtualTable( int onError /* ON CONFLICT strategy */ ){ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ + ExprList *pEList = 0; /* The result set of the SELECT statement */ + Select *pSelect = 0; /* The SELECT statement */ + Expr *pExpr; /* Temporary expression */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ + int addr; /* Address of top of loop */ + int iReg; /* First register in set passed to OP_VUpdate */ sqlite3 *db = pParse->db; /* Database connection */ const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); - WhereInfo *pWInfo; - int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ - int regArg; /* First register in VUpdate arg array */ - int regRec; /* Register in which to assemble record */ - int regRowid; /* Register for ephem table rowid */ - int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ - int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ - int bOnePass; /* True to use onepass strategy */ - int addr; /* Address of OP_OpenEphemeral */ + SelectDest dest; - /* Allocate nArg registers to martial the arguments to VUpdate. Then - ** create and open the ephemeral table in which the records created from - ** these arguments will be temporarily stored. */ - assert( v ); - ephemTab = pParse->nTab++; - addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); - regArg = pParse->nMem + 1; - pParse->nMem += nArg; - regRec = ++pParse->nMem; - regRowid = ++pParse->nMem; - - /* Start scanning the virtual table */ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); - if( pWInfo==0 ) return; - - /* Populate the argument registers. */ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); + /* Construct the SELECT statement that will find the new values for + ** all updated rows. + */ + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_")); if( pRowid ){ - sqlite3ExprCode(pParse, pRowid, regArg+1); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); + pEList = sqlite3ExprListAppend(pParse, pEList, + sqlite3ExprDup(db, pRowid, 0)); } + assert( pTab->iPKey<0 ); for(i=0; inCol; i++){ if( aXRef[i]>=0 ){ - sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); + pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); }else{ - sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); + pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName); } + pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); } + pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); + + /* Create the ephemeral table into which the update results will + ** be stored. + */ + assert( v ); + ephemTab = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + /* fill the ephemeral table + */ + sqlite3SelectDestInit(&dest, SRT_Table, ephemTab); + sqlite3Select(pParse, pSelect, &dest); - if( bOnePass ){ - /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded - ** above. Also, if this is a top-level parse (not a trigger), clear the - ** multi-write flag so that the VM does not open a statement journal */ - sqlite3VdbeChangeToNoop(v, addr); - if( sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; - } - }else{ - /* Create a record from the argument register contents and insert it into - ** the ephemeral table. */ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); - sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); - } - - - if( bOnePass==0 ){ - /* End the virtual table scan */ - sqlite3WhereEnd(pWInfo); - - /* Begin scannning through the ephemeral table. */ - addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); - - /* Extract arguments from the current row of the ephemeral table and - ** invoke the VUpdate method. */ - for(i=0; inMem; + pParse->nMem += pTab->nCol+1; + addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); + for(i=0; inCol; i++){ + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); } sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); - /* End of the ephemeral table scan. Or, if using the onepass strategy, - ** jump to here if the scan visited zero rows. */ - if( bOnePass==0 ){ - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); - }else{ - sqlite3WhereEnd(pWInfo); - } + /* Cleanup */ + sqlite3SelectDelete(db, pSelect); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -117436,8 +108121,6 @@ static void updateVirtualTable( ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. */ -/* #include "sqliteInt.h" */ -/* #include "vdbeInt.h" */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* @@ -117509,14 +108192,14 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ ** step (3) requires additional temporary disk space approximately equal ** to the size of the original database for the rollback journal. ** Hence, temporary disk space that is approximately 2x the size of the -** original database is required. Every page of the database is written +** orginal database is required. Every page of the database is written ** approximately 3 times: Once for step (2) and twice for step (3). ** Two writes per page are required in step (3) because the original ** database content must be written into the rollback journal prior to ** overwriting the database with the vacuumed content. ** ** Only 1x temporary space and only 1x writes would be required if -** the copy of step (3) were replaced by deleting the original database +** the copy of step (3) were replace by deleting the original database ** and renaming the transient database as the original. But that will ** not work if other processes are attached to the original database. ** And a power loss in between deleting the original and renaming the @@ -117606,7 +108289,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** cause problems for the call to BtreeSetPageSize() below. */ sqlite3BtreeCommit(pTemp); - nRes = sqlite3BtreeGetOptimalReserve(pMain); + nRes = sqlite3BtreeGetReserve(pMain); /* A VACUUM cannot change the pagesize of an encrypted database. */ #ifdef SQLITE_HAS_CODEC @@ -117672,8 +108355,6 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ - assert( (db->flags & SQLITE_Vacuum)==0 ); - db->flags |= SQLITE_Vacuum; rc = execExecSql(db, pzErrMsg, "SELECT 'INSERT INTO vacuum_db.' || quote(name) " "|| ' SELECT * FROM main.' || quote(name) || ';'" @@ -117681,8 +108362,6 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "WHERE type = 'table' AND name!='sqlite_sequence' " " AND coalesce(rootpage,1)>0" ); - assert( (db->flags & SQLITE_Vacuum)!=0 ); - db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy over the sequence table @@ -117810,7 +108489,6 @@ end_of_vacuum: ** This file contains code used to help implement virtual tables. */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* #include "sqliteInt.h" */ /* ** Before a virtual table xCreate() or xConnect() method is invoked, the @@ -117822,8 +108500,6 @@ end_of_vacuum: struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ - VtabCtx *pPrior; /* Parent context (if any) */ - int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* @@ -117843,7 +108519,7 @@ static int createModule( sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); - if( sqlite3HashFind(&db->aModule, zName) ){ + if( sqlite3HashFind(&db->aModule, zName, nName) ){ rc = SQLITE_MISUSE_BKPT; }else{ Module *pMod; @@ -117856,8 +108532,7 @@ static int createModule( pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; - pMod->pEpoTab = 0; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod); assert( pDel==0 || pDel==pMod ); if( pDel ){ db->mallocFailed = 1; @@ -117876,31 +108551,25 @@ static int createModule( /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module( +SQLITE_API int sqlite3_create_module( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux /* Context pointer for xCreate/xConnect */ ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif return createModule(db, zName, pModule, pAux, 0); } /* ** External API function used to create a new virtual-table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2( +SQLITE_API int sqlite3_create_module_v2( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif return createModule(db, zName, pModule, pAux, xDestroy); } @@ -118084,17 +108753,23 @@ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ ** deleted. */ static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ - int nBytes = sizeof(char *)*(2+pTable->nModuleArg); + int i = pTable->nModuleArg++; + int nBytes = sizeof(char *)*(1+pTable->nModuleArg); char **azModuleArg; azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); if( azModuleArg==0 ){ + int j; + for(j=0; jazModuleArg[j]); + } sqlite3DbFree(db, zArg); + sqlite3DbFree(db, pTable->azModuleArg); + pTable->nModuleArg = 0; }else{ - int i = pTable->nModuleArg++; azModuleArg[i] = zArg; azModuleArg[i+1] = 0; - pTable->azModuleArg = azModuleArg; } + pTable->azModuleArg = azModuleArg; } /* @@ -118127,12 +108802,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); addModuleArgument(db, pTable, 0); addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); - assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) - || (pParse->sNameToken.z==pName1->z && pName2->z==0) - ); - pParse->sNameToken.n = (int)( - &pModuleName->z[pModuleName->n] - pParse->sNameToken.z - ); + pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z); #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. @@ -118184,7 +108854,6 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ char *zStmt; char *zWhere; int iDb; - int iReg; Vdbe *v; /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ @@ -118219,10 +108888,8 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); - - iReg = ++pParse->nMem; - sqlite3VdbeLoadString(v, iReg, pTab->zName); - sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); + sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, + pTab->zName, sqlite3Strlen30(pTab->zName) + 1); } /* If we are rereading the sqlite_master table create the in-memory @@ -118234,8 +108901,9 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; + int nName = sqlite3Strlen30(zName); assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); + pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); if( pOld ){ db->mallocFailed = 1; assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ @@ -118265,7 +108933,7 @@ SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){ pArg->z = p->z; pArg->n = p->n; }else{ - assert(pArg->z <= p->z); + assert(pArg->z < p->z); pArg->n = (int)(&p->z[p->n] - pArg->z); } } @@ -118282,27 +108950,15 @@ static int vtabCallConstructor( int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - VtabCtx sCtx; + VtabCtx sCtx, *pPriorCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; - char *zModuleName; + char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); int iDb; - VtabCtx *pCtx; - /* Check that the virtual-table is not already being initialized */ - for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ - if( pCtx->pTab==pTab ){ - *pzErr = sqlite3MPrintf(db, - "vtable constructor called recursively: %s", pTab->zName - ); - return SQLITE_LOCKED; - } - } - - zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } @@ -118323,13 +108979,11 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; - sCtx.pPrior = db->pVtabCtx; - sCtx.bDeclared = 0; + pPriorCtx = db->pVtabCtx; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = sCtx.pPrior; + db->pVtabCtx = pPriorCtx; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ @@ -118342,17 +108996,15 @@ static int vtabCallConstructor( }else if( ALWAYS(pVTable->pVtab) ){ /* Justification of ALWAYS(): A correct vtab constructor must allocate ** the sqlite3_vtab object if successful. */ - memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; - if( sCtx.bDeclared==0 ){ + if( sCtx.pTab ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; - u8 oooHidden = 0; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". @@ -118365,10 +109017,7 @@ static int vtabCallConstructor( char *zType = pTab->aCol[iCol].zType; int nType; int i = 0; - if( !zType ){ - pTab->tabFlags |= oooHidden; - continue; - } + if( !zType ) continue; nType = sqlite3Strlen30(zType); if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ for(i=0; iaCol[iCol].colFlags |= COLFLAG_HIDDEN; - oooHidden = TF_OOOHidden; - }else{ - pTab->tabFlags |= oooHidden; } } } @@ -118423,7 +109069,7 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; @@ -118491,13 +109137,13 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ - if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ + if( !pMod ){ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; }else{ @@ -118521,26 +109167,19 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ -SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ - VtabCtx *pCtx; +SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ Parse *pParse; + int rc = SQLITE_OK; Table *pTab; char *zErr = 0; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif sqlite3_mutex_enter(db->mutex); - pCtx = db->pVtabCtx; - if( !pCtx || pCtx->bDeclared ){ - sqlite3Error(db, SQLITE_MISUSE); + if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ + sqlite3Error(db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } - pTab = pCtx->pTab; assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); @@ -118563,9 +109202,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCre pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } - pCtx->bDeclared = 1; + db->pVtabCtx->pTab = 0; }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); + sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } @@ -118598,18 +109237,11 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ - VTable *p; - int (*xDestroy)(sqlite3_vtab *); - for(p=pTab->pVTable; p; p=p->pNext){ - assert( p->pVtab ); - if( p->pVtab->nRef>0 ){ - return SQLITE_LOCKED; - } - } - p = vtabDisconnectAll(db, pTab); - xDestroy = p->pMod->pModule->xDestroy; - assert( xDestroy!=0 ); /* Checked before the virtual table is created */ - rc = xDestroy(p->pVtab); + VTable *p = vtabDisconnectAll(db, pTab); + + assert( rc==SQLITE_OK ); + rc = p->pMod->pModule->xDestroy(p->pVtab); + /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ assert( pTab->pVTable==p && p->pNext==0 ); @@ -118633,10 +109265,8 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab static void callFinaliser(sqlite3 *db, int offset){ int i; if( db->aVTrans ){ - VTable **aVTrans = db->aVTrans; - db->aVTrans = 0; for(i=0; inVTrans; i++){ - VTable *pVTab = aVTrans[i]; + VTable *pVTab = db->aVTrans[i]; sqlite3_vtab *p = pVTab->pVtab; if( p ){ int (*x)(sqlite3_vtab *); @@ -118646,8 +109276,9 @@ static void callFinaliser(sqlite3 *db, int offset){ pVTab->iSavepoint = 0; sqlite3VtabUnlock(pVTab); } - sqlite3DbFree(db, aVTrans); + sqlite3DbFree(db, db->aVTrans); db->nVTrans = 0; + db->aVTrans = 0; } } @@ -118735,9 +109366,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ if( rc==SQLITE_OK ){ rc = pModule->xBegin(pVTab->pVtab); if( rc==SQLITE_OK ){ - int iSvpt = db->nStatement + db->nSavepoint; addToVTrans(db, pVTab); - if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); } } } @@ -118763,7 +109392,7 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ int rc = SQLITE_OK; assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); - assert( iSavepoint>=-1 ); + assert( iSavepoint>=0 ); if( db->aVTrans ){ int i; for(i=0; rc==SQLITE_OK && inVTrans; i++){ @@ -118881,7 +109510,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ if( pTab==pToplevel->apVtabLock[i] ) return; } n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); + apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); if( apVtabLock ){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; @@ -118890,67 +109519,6 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ } } -/* -** Check to see if virtual tale module pMod can be have an eponymous -** virtual table instance. If it can, create one if one does not already -** exist. Return non-zero if the eponymous virtual table instance exists -** when this routine returns, and return zero if it does not exist. -** -** An eponymous virtual table instance is one that is named after its -** module, and more importantly, does not require a CREATE VIRTUAL TABLE -** statement in order to come into existance. Eponymous virtual table -** instances always exist. They cannot be DROP-ed. -** -** Any virtual table module for which xConnect and xCreate are the same -** method can have an eponymous virtual table instance. -*/ -SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ - const sqlite3_module *pModule = pMod->pModule; - Table *pTab; - char *zErr = 0; - int nName; - int rc; - sqlite3 *db = pParse->db; - if( pMod->pEpoTab ) return 1; - if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; - nName = sqlite3Strlen30(pMod->zName) + 1; - pTab = sqlite3DbMallocZero(db, sizeof(Table) + nName); - if( pTab==0 ) return 0; - pMod->pEpoTab = pTab; - pTab->zName = (char*)&pTab[1]; - memcpy(pTab->zName, pMod->zName, nName); - pTab->nRef = 1; - pTab->pSchema = db->aDb[0].pSchema; - pTab->tabFlags |= TF_Virtual; - pTab->nModuleArg = 0; - pTab->iPKey = -1; - addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); - addModuleArgument(db, pTab, 0); - addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); - rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); - if( rc ){ - sqlite3ErrorMsg(pParse, "%s", zErr); - sqlite3DbFree(db, zErr); - sqlite3VtabEponymousTableClear(db, pMod); - return 0; - } - return 1; -} - -/* -** Erase the eponymous virtual table instance associated with -** virtual table module pMod, if it exists. -*/ -SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ - Table *pTab = pMod->pEpoTab; - if( pTab!=0 ){ - sqlite3DeleteColumnNames(db, pTab); - sqlite3VtabClear(db, pTab); - sqlite3DbFree(db, pTab); - pMod->pEpoTab = 0; - } -} - /* ** Return the ON CONFLICT resolution mode in effect for the virtual ** table update operation currently in progress. @@ -118958,13 +109526,10 @@ SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ ** The results of this routine are undefined unless it is called from ** within an xUpdate method. */ -SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ static const unsigned char aMap[] = { SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE }; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 ); assert( OE_Ignore==4 && OE_Replace==5 ); assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 ); @@ -118976,14 +109541,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){ ** the SQLite core with additional information about the behavior ** of the virtual table being implemented. */ -SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ va_list ap; int rc = SQLITE_OK; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); + va_start(ap, op); switch( op ){ case SQLITE_VTAB_CONSTRAINT_SUPPORT: { @@ -119002,7 +109565,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ } va_end(ap); - if( rc!=SQLITE_OK ) sqlite3Error(db, rc); + if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0); sqlite3_mutex_leave(db->mutex); return rc; } @@ -119010,9 +109573,9 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ #endif /* SQLITE_OMIT_VIRTUALTABLE */ /************** End of vtab.c ************************************************/ -/************** Begin file wherecode.c ***************************************/ +/************** Begin file where.c *******************************************/ /* -** 2015-06-06 +** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -119023,15 +109586,13 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ ** ************************************************************************* ** This module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. -** -** This file was split off from where.c on 2015-06-06 in order to reduce the -** size of where.c and make it easier to edit. This file contains the routines -** that actually generate the bulk of the WHERE loop code. The original where.c -** file retains the code that does query planning and analysis. +** the WHERE clause of SQL statements. This module is responsible for +** generating the code that loops through a table looking for applicable +** rows. Indices are selected and used to speed the search when doing +** so is applicable. Because this module is responsible for selecting +** indices, you might also think of this module as the "query optimizer". */ -/* #include "sqliteInt.h" */ -/************** Include whereInt.h in the middle of wherecode.c **************/ +/************** Include whereInt.h in the middle of where.c ******************/ /************** Begin file whereInt.h ****************************************/ /* ** 2013-11-12 @@ -119054,7 +109615,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){ ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) -/***/ int sqlite3WhereTrace; +/***/ int sqlite3WhereTrace = 0; #endif #if defined(SQLITE_DEBUG) \ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) @@ -119104,10 +109665,6 @@ struct WhereLevel { int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - int iLikeRepCntr; /* LIKE range processing counter register */ - int addrLikeRep; /* LIKE range processing address */ -#endif u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to ends the loop */ @@ -119124,9 +109681,6 @@ struct WhereLevel { } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ Bitmask notReady; /* FROM entries not usable at this level */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrVisit; /* Address at which row is visited */ -#endif }; /* @@ -119157,6 +109711,7 @@ struct WhereLoop { union { struct { /* Information for internal btree tables */ u16 nEq; /* Number of equality constraints */ + u16 nSkip; /* Number of initial index columns to skip */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ @@ -119169,13 +109724,12 @@ struct WhereLoop { } u; u32 wsFlags; /* WHERE_* flags describing the plan */ u16 nLTerm; /* Number of entries in aLTerm[] */ - u16 nSkip; /* Number of NULL aLTerm[] entries */ /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) u16 nLSlot; /* Number of slots allocated for aLTerm[] */ WhereTerm **aLTerm; /* WhereTerms used */ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ - WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */ + WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ }; /* This object holds the prerequisites and the cost of running a @@ -119198,6 +109752,10 @@ struct WhereOrSet { WhereOrCost a[N_OR_COST]; /* Set of best costs */ }; + +/* Forward declaration of methods */ +static int whereLoopResize(sqlite3*, WhereLoop*, int); + /* ** Each instance of this object holds a sequence of WhereLoop objects ** that implement some or all of a query plan. @@ -119214,14 +109772,13 @@ struct WhereOrSet { ** 1. Then using those as a basis to compute the N best WherePath objects ** of length 2. And so forth until the length of WherePaths equals the ** number of nodes in the FROM clause. The best (lowest cost) WherePath -** at the end is the chosen query plan. +** at the end is the choosen query plan. */ struct WherePath { Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ LogEst nRow; /* Estimated number of rows generated by this path */ LogEst rCost; /* Total cost of this path */ - LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */ i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ }; @@ -119288,9 +109845,8 @@ struct WhereTerm { } u; LogEst truthProb; /* Probability of truth for this expression */ u16 eOperator; /* A WO_xx value describing */ - u16 wtFlags; /* TERM_xxx bit flags. See below */ + u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ - u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ @@ -119311,10 +109867,6 @@ struct WhereTerm { #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif -#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ -#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ -#define TERM_LIKE 0x400 /* The original LIKE operator */ -#define TERM_IS 0x800 /* Term.pExpr is an IS operator */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -119323,15 +109875,13 @@ struct WhereTerm { struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ WhereClause *pWC; /* WhereClause currently being scanned */ - const char *zCollName; /* Required collating sequence, if not NULL */ - Expr *pIdxExpr; /* Search for this index expression */ + char *zCollName; /* Required collating sequence, if not NULL */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ unsigned char nEquiv; /* Number of entries in aEquiv[] */ unsigned char iEquiv; /* Next unused slot in aEquiv[] */ u32 opMask; /* Acceptable operators */ int k; /* Resume scanning at this->pWC->a[this->k] */ - int aiCur[11]; /* Cursors in the equivalence class */ - i16 aiColumn[11]; /* Corresponding column number in the eq-class */ + int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */ }; /* @@ -119408,11 +109958,6 @@ struct WhereMaskSet { int ix[BMS]; /* Cursor assigned to each bit */ }; -/* -** Initialize a WhereMaskSet object -*/ -#define initMaskSet(P) (P)->n=0 - /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. @@ -119450,7 +109995,7 @@ struct WhereInfo { u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ u8 sorted; /* True if really sorted (not just grouped) */ - u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ + u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ @@ -119464,85 +110009,27 @@ struct WhereInfo { WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; -/* -** Private interfaces - callable only by other where.c routines. -** -** where.c: -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int); -SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -); - -/* wherecode.c: */ -#ifndef SQLITE_OMIT_EXPLAIN -SQLITE_PRIVATE int sqlite3WhereExplainOneScan( - Parse *pParse, /* Parse context */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -); -#else -# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 -#endif /* SQLITE_OMIT_EXPLAIN */ -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -SQLITE_PRIVATE void sqlite3WhereAddScanStatus( - Vdbe *v, /* Vdbe to add scanstatus entry to */ - SrcList *pSrclist, /* FROM clause pLvl reads data from */ - WhereLevel *pLvl, /* Level to add scanstatus() entry for */ - int addrExplain /* Address of OP_Explain (or 0) */ -); -#else -# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d) -#endif -SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( - WhereInfo *pWInfo, /* Complete information about the WHERE clause */ - int iLevel, /* Which level of pWInfo->a[] should be coded */ - Bitmask notReady /* Which tables are currently available */ -); - -/* whereexpr.c: */ -SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); -SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); -SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); -SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); -SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); -SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); - - - - - /* ** Bitmasks for the operators on WhereTerm objects. These are all ** operators that are of interest to the query planner. An ** OR-ed combination of these values can be used when searching for ** particular WhereTerms within a WhereClause. */ -#define WO_IN 0x0001 -#define WO_EQ 0x0002 +#define WO_IN 0x001 +#define WO_EQ 0x002 #define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) -#define WO_MATCH 0x0040 -#define WO_IS 0x0080 -#define WO_ISNULL 0x0100 -#define WO_OR 0x0200 /* Two or more OR-connected terms */ -#define WO_AND 0x0400 /* Two or more AND-connected terms */ -#define WO_EQUIV 0x0800 /* Of the form A==B, both columns */ -#define WO_NOOP 0x1000 /* This term does not restrict search space */ +#define WO_MATCH 0x040 +#define WO_ISNULL 0x080 +#define WO_OR 0x100 /* Two or more OR-connected terms */ +#define WO_AND 0x200 /* Two or more AND-connected terms */ +#define WO_EQUIV 0x400 /* Of the form A==B, both columns */ +#define WO_NOOP 0x800 /* This term does not restrict search space */ -#define WO_ALL 0x1fff /* Mask of all possible WO_* values */ -#define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */ +#define WO_ALL 0xfff /* Mask of all possible WO_* values */ +#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. @@ -119567,223 +110054,2275 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ -#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ /************** End of whereInt.h ********************************************/ -/************** Continuing where we left off in wherecode.c ******************/ +/************** Continuing where we left off in where.c **********************/ -#ifndef SQLITE_OMIT_EXPLAIN /* -** This routine is a helper for explainIndexRange() below -** -** pStr holds the text of an expression that we are building up one term -** at a time. This routine adds a new term to the end of the expression. -** Terms are separated by AND so add the "AND" text for second and subsequent -** terms only. +** Return the estimated number of output rows from a WHERE clause */ -static void explainAppendTerm( - StrAccum *pStr, /* The text expression being built */ - int iTerm, /* Index of this term. First is zero */ - const char *zColumn, /* Name of the column */ - const char *zOp /* Name of the operator */ +SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ + return sqlite3LogEstToInt(pWInfo->nRowOut); +} + +/* +** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this +** WHERE clause returns outputs for DISTINCT processing. +*/ +SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ + return pWInfo->eDistinct; +} + +/* +** Return TRUE if the WHERE clause returns rows in ORDER BY order. +** Return FALSE if the output needs to be sorted. +*/ +SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ + return pWInfo->nOBSat; +} + +/* +** Return the VDBE address or label to jump to in order to continue +** immediately with the next row of a WHERE clause. +*/ +SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ + assert( pWInfo->iContinue!=0 ); + return pWInfo->iContinue; +} + +/* +** Return the VDBE address or label to jump to in order to break +** out of a WHERE loop. +*/ +SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ + return pWInfo->iBreak; +} + +/* +** Return TRUE if an UPDATE or DELETE statement can operate directly on +** the rowids returned by a WHERE clause. Return FALSE if doing an +** UPDATE or DELETE might change subsequent WHERE clause results. +** +** If the ONEPASS optimization is used (if this routine returns true) +** then also write the indices of open cursors used by ONEPASS +** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data +** table and iaCur[1] gets the cursor used by an auxiliary index. +** Either value may be -1, indicating that cursor is not used. +** Any cursors returned will have been opened for writing. +** +** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is +** unable to use the ONEPASS optimization. +*/ +SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ + memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); + return pWInfo->okOnePass; +} + +/* +** Move the content of pSrc into pDest +*/ +static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ + pDest->n = pSrc->n; + memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); +} + +/* +** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. +** +** The new entry might overwrite an existing entry, or it might be +** appended, or it might be discarded. Do whatever is the right thing +** so that pSet keeps the N_OR_COST best entries seen so far. +*/ +static int whereOrInsert( + WhereOrSet *pSet, /* The WhereOrSet to be updated */ + Bitmask prereq, /* Prerequisites of the new entry */ + LogEst rRun, /* Run-cost of the new entry */ + LogEst nOut /* Number of outputs for the new entry */ ){ - if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppendAll(pStr, zColumn); - sqlite3StrAccumAppend(pStr, zOp, 1); - sqlite3StrAccumAppend(pStr, "?", 1); -} - -/* -** Return the name of the i-th column of the pIdx index. -*/ -static const char *explainIndexColumnName(Index *pIdx, int i){ - i = pIdx->aiColumn[i]; - if( i==XN_EXPR ) return ""; - if( i==XN_ROWID ) return "rowid"; - return pIdx->pTable->aCol[i].zName; -} - -/* -** Argument pLevel describes a strategy for scanning table pTab. This -** function appends text to pStr that describes the subset of table -** rows scanned by the strategy in the form of an SQL expression. -** -** For example, if the query: -** -** SELECT * FROM t1 WHERE a=1 AND b>2; -** -** is run and there is an index on (a, b), then this function returns a -** string similar to: -** -** "a=? AND b>?" -*/ -static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){ - Index *pIndex = pLoop->u.btree.pIndex; - u16 nEq = pLoop->u.btree.nEq; - u16 nSkip = pLoop->nSkip; - int i, j; - - if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; - sqlite3StrAccumAppend(pStr, " (", 2); - for(i=0; i=nSkip ? "%s=?" : "ANY(%s)", z); + u16 i; + WhereOrCost *p; + for(i=pSet->n, p=pSet->a; i>0; i--, p++){ + if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ + goto whereOrInsert_done; + } + if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ + return 0; + } } - - j = i; - if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, i); - explainAppendTerm(pStr, i++, z, ">"); - } - if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ - const char *z = explainIndexColumnName(pIndex, j); - explainAppendTerm(pStr, i, z, "<"); - } - sqlite3StrAccumAppend(pStr, ")", 1); -} - -/* -** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN -** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was -** defined at compile-time. If it is not a no-op, a single OP_Explain opcode -** is added to the output to describe the table scan strategy in pLevel. -** -** If an OP_Explain opcode is added to the VM, its address is returned. -** Otherwise, if no OP_Explain is coded, zero is returned. -*/ -SQLITE_PRIVATE int sqlite3WhereExplainOneScan( - Parse *pParse, /* Parse context */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -){ - int ret = 0; -#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) - if( pParse->explain==2 ) -#endif - { - struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; - Vdbe *v = pParse->pVdbe; /* VM being constructed */ - sqlite3 *db = pParse->db; /* Database handle */ - int iId = pParse->iSelectId; /* Select id (left-most output column) */ - int isSearch; /* True for a SEARCH. False for SCAN. */ - WhereLoop *pLoop; /* The controlling WhereLoop object */ - u32 flags; /* Flags that describe this loop */ - char *zMsg; /* Text to add to EQP output */ - StrAccum str; /* EQP output string */ - char zBuf[100]; /* Initial space for EQP output string */ - - pLoop = pLevel->pWLoop; - flags = pLoop->wsFlags; - if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return 0; - - isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) - || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - - sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); - if( pItem->pSelect ){ - sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); - }else{ - sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); - } - - if( pItem->zAlias ){ - sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias); - } - if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ - const char *zFmt = 0; - Index *pIdx; - - assert( pLoop->u.btree.pIndex!=0 ); - pIdx = pLoop->u.btree.pIndex; - assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); - if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){ - if( isSearch ){ - zFmt = "PRIMARY KEY"; - } - }else if( flags & WHERE_PARTIALIDX ){ - zFmt = "AUTOMATIC PARTIAL COVERING INDEX"; - }else if( flags & WHERE_AUTO_INDEX ){ - zFmt = "AUTOMATIC COVERING INDEX"; - }else if( flags & WHERE_IDX_ONLY ){ - zFmt = "COVERING INDEX %s"; - }else{ - zFmt = "INDEX %s"; - } - if( zFmt ){ - sqlite3StrAccumAppend(&str, " USING ", 7); - sqlite3XPrintf(&str, 0, zFmt, pIdx->zName); - explainIndexRange(&str, pLoop); - } - }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ - const char *zRangeOp; - if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ - zRangeOp = "="; - }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - zRangeOp = ">? AND rowid<"; - }else if( flags&WHERE_BTM_LIMIT ){ - zRangeOp = ">"; - }else{ - assert( flags&WHERE_TOP_LIMIT); - zRangeOp = "<"; - } - sqlite3XPrintf(&str, 0, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ - sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s", - pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); - } -#endif -#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS - if( pLoop->nOut>=10 ){ - sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); - }else{ - sqlite3StrAccumAppend(&str, " (~1 row)", 9); - } -#endif - zMsg = sqlite3StrAccumFinish(&str); - ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); - } - return ret; -} -#endif /* SQLITE_OMIT_EXPLAIN */ - -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS -/* -** Configure the VM passed as the first argument with an -** sqlite3_stmt_scanstatus() entry corresponding to the scan used to -** implement level pLvl. Argument pSrclist is a pointer to the FROM -** clause that the scan reads data from. -** -** If argument addrExplain is not 0, it must be the address of an -** OP_Explain instruction that describes the same loop. -*/ -SQLITE_PRIVATE void sqlite3WhereAddScanStatus( - Vdbe *v, /* Vdbe to add scanstatus entry to */ - SrcList *pSrclist, /* FROM clause pLvl reads data from */ - WhereLevel *pLvl, /* Level to add scanstatus() entry for */ - int addrExplain /* Address of OP_Explain (or 0) */ -){ - const char *zObj = 0; - WhereLoop *pLoop = pLvl->pWLoop; - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ - zObj = pLoop->u.btree.pIndex->zName; + if( pSet->na[pSet->n++]; + p->nOut = nOut; }else{ - zObj = pSrclist->a[pLvl->iFrom].zName; + p = pSet->a; + for(i=1; in; i++){ + if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; + } + if( p->rRun<=rRun ) return 0; } - sqlite3VdbeScanStatus( - v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj - ); +whereOrInsert_done: + p->prereq = prereq; + p->rRun = rRun; + if( p->nOut>nOut ) p->nOut = nOut; + return 1; +} + +/* +** Initialize a preallocated WhereClause structure. +*/ +static void whereClauseInit( + WhereClause *pWC, /* The WhereClause to be initialized */ + WhereInfo *pWInfo /* The WHERE processing context */ +){ + pWC->pWInfo = pWInfo; + pWC->pOuter = 0; + pWC->nTerm = 0; + pWC->nSlot = ArraySize(pWC->aStatic); + pWC->a = pWC->aStatic; +} + +/* Forward reference */ +static void whereClauseClear(WhereClause*); + +/* +** Deallocate all memory associated with a WhereOrInfo object. +*/ +static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){ + whereClauseClear(&p->wc); + sqlite3DbFree(db, p); +} + +/* +** Deallocate all memory associated with a WhereAndInfo object. +*/ +static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){ + whereClauseClear(&p->wc); + sqlite3DbFree(db, p); +} + +/* +** Deallocate a WhereClause structure. The WhereClause structure +** itself is not freed. This routine is the inverse of whereClauseInit(). +*/ +static void whereClauseClear(WhereClause *pWC){ + int i; + WhereTerm *a; + sqlite3 *db = pWC->pWInfo->pParse->db; + for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ + if( a->wtFlags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, a->pExpr); + } + if( a->wtFlags & TERM_ORINFO ){ + whereOrInfoDelete(db, a->u.pOrInfo); + }else if( a->wtFlags & TERM_ANDINFO ){ + whereAndInfoDelete(db, a->u.pAndInfo); + } + } + if( pWC->a!=pWC->aStatic ){ + sqlite3DbFree(db, pWC->a); + } +} + +/* +** Add a single new WhereTerm entry to the WhereClause object pWC. +** The new WhereTerm object is constructed from Expr p and with wtFlags. +** The index in pWC->a[] of the new WhereTerm is returned on success. +** 0 is returned if the new WhereTerm could not be added due to a memory +** allocation error. The memory allocation failure will be recorded in +** the db->mallocFailed flag so that higher-level functions can detect it. +** +** This routine will increase the size of the pWC->a[] array as necessary. +** +** If the wtFlags argument includes TERM_DYNAMIC, then responsibility +** for freeing the expression p is assumed by the WhereClause object pWC. +** This is true even if this routine fails to allocate a new WhereTerm. +** +** WARNING: This routine might reallocate the space used to store +** WhereTerms. All pointers to WhereTerms should be invalidated after +** calling this routine. Such pointers may be reinitialized by referencing +** the pWC->a[] array. +*/ +static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ + WhereTerm *pTerm; + int idx; + testcase( wtFlags & TERM_VIRTUAL ); + if( pWC->nTerm>=pWC->nSlot ){ + WhereTerm *pOld = pWC->a; + sqlite3 *db = pWC->pWInfo->pParse->db; + pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); + if( pWC->a==0 ){ + if( wtFlags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, p); + } + pWC->a = pOld; + return 0; + } + memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); + if( pOld!=pWC->aStatic ){ + sqlite3DbFree(db, pOld); + } + pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); + } + pTerm = &pWC->a[idx = pWC->nTerm++]; + if( p && ExprHasProperty(p, EP_Unlikely) ){ + pTerm->truthProb = sqlite3LogEst(p->iTable) - 99; + }else{ + pTerm->truthProb = 1; + } + pTerm->pExpr = sqlite3ExprSkipCollate(p); + pTerm->wtFlags = wtFlags; + pTerm->pWC = pWC; + pTerm->iParent = -1; + return idx; +} + +/* +** This routine identifies subexpressions in the WHERE clause where +** each subexpression is separated by the AND operator or some other +** operator specified in the op parameter. The WhereClause structure +** is filled with pointers to subexpressions. For example: +** +** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) +** \________/ \_______________/ \________________/ +** slot[0] slot[1] slot[2] +** +** The original WHERE clause in pExpr is unaltered. All this routine +** does is make slot[] entries point to substructure within pExpr. +** +** In the previous sentence and in the diagram, "slot[]" refers to +** the WhereClause.a[] array. The slot[] array grows as needed to contain +** all terms of the WHERE clause. +*/ +static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ + pWC->op = op; + if( pExpr==0 ) return; + if( pExpr->op!=op ){ + whereClauseInsert(pWC, pExpr, 0); + }else{ + whereSplit(pWC, pExpr->pLeft, op); + whereSplit(pWC, pExpr->pRight, op); + } +} + +/* +** Initialize a WhereMaskSet object +*/ +#define initMaskSet(P) (P)->n=0 + +/* +** Return the bitmask for the given cursor number. Return 0 if +** iCursor is not in the set. +*/ +static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){ + int i; + assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); + for(i=0; in; i++){ + if( pMaskSet->ix[i]==iCursor ){ + return MASKBIT(i); + } + } + return 0; +} + +/* +** Create a new mask for cursor iCursor. +** +** There is one cursor per table in the FROM clause. The number of +** tables in the FROM clause is limited by a test early in the +** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[] +** array will never overflow. +*/ +static void createMask(WhereMaskSet *pMaskSet, int iCursor){ + assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); + pMaskSet->ix[pMaskSet->n++] = iCursor; +} + +/* +** These routines walk (recursively) an expression tree and generate +** a bitmask indicating which tables are used in that expression +** tree. +*/ +static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); +static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); +static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){ + Bitmask mask = 0; + if( p==0 ) return 0; + if( p->op==TK_COLUMN ){ + mask = getMask(pMaskSet, p->iTable); + return mask; + } + mask = exprTableUsage(pMaskSet, p->pRight); + mask |= exprTableUsage(pMaskSet, p->pLeft); + if( ExprHasProperty(p, EP_xIsSelect) ){ + mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect); + }else{ + mask |= exprListTableUsage(pMaskSet, p->x.pList); + } + return mask; +} +static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){ + int i; + Bitmask mask = 0; + if( pList ){ + for(i=0; inExpr; i++){ + mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); + } + } + return mask; +} +static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){ + Bitmask mask = 0; + while( pS ){ + SrcList *pSrc = pS->pSrc; + mask |= exprListTableUsage(pMaskSet, pS->pEList); + mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); + mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); + mask |= exprTableUsage(pMaskSet, pS->pWhere); + mask |= exprTableUsage(pMaskSet, pS->pHaving); + if( ALWAYS(pSrc!=0) ){ + int i; + for(i=0; inSrc; i++){ + mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect); + mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn); + } + } + pS = pS->pPrior; + } + return mask; +} + +/* +** Return TRUE if the given operator is one of the operators that is +** allowed for an indexable WHERE clause term. The allowed operators are +** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" +*/ +static int allowedOp(int op){ + assert( TK_GT>TK_EQ && TK_GTTK_EQ && TK_LTTK_EQ && TK_LE=TK_EQ && op<=TK_GE) || op==TK_ISNULL; +} + +/* +** Swap two objects of type TYPE. +*/ +#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} + +/* +** Commute a comparison operator. Expressions of the form "X op Y" +** are converted into "Y op X". +** +** If left/right precedence rules come into play when determining the +** collating sequence, then COLLATE operators are adjusted to ensure +** that the collating sequence does not change. For example: +** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on +** the left hand side of a comparison overrides any collation sequence +** attached to the right. For the same reason the EP_Collate flag +** is not commuted. +*/ +static void exprCommute(Parse *pParse, Expr *pExpr){ + u16 expRight = (pExpr->pRight->flags & EP_Collate); + u16 expLeft = (pExpr->pLeft->flags & EP_Collate); + assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); + if( expRight==expLeft ){ + /* Either X and Y both have COLLATE operator or neither do */ + if( expRight ){ + /* Both X and Y have COLLATE operators. Make sure X is always + ** used by clearing the EP_Collate flag from Y. */ + pExpr->pRight->flags &= ~EP_Collate; + }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ + /* Neither X nor Y have COLLATE operators, but X has a non-default + ** collating sequence. So add the EP_Collate marker on X to cause + ** it to be searched first. */ + pExpr->pLeft->flags |= EP_Collate; + } + } + SWAP(Expr*,pExpr->pRight,pExpr->pLeft); + if( pExpr->op>=TK_GT ){ + assert( TK_LT==TK_GT+2 ); + assert( TK_GE==TK_LE+2 ); + assert( TK_GT>TK_EQ ); + assert( TK_GTop>=TK_GT && pExpr->op<=TK_GE ); + pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; + } +} + +/* +** Translate from TK_xx operator to WO_xx bitmask. +*/ +static u16 operatorMask(int op){ + u16 c; + assert( allowedOp(op) ); + if( op==TK_IN ){ + c = WO_IN; + }else if( op==TK_ISNULL ){ + c = WO_ISNULL; + }else{ + assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); + c = (u16)(WO_EQ<<(op-TK_EQ)); + } + assert( op!=TK_ISNULL || c==WO_ISNULL ); + assert( op!=TK_IN || c==WO_IN ); + assert( op!=TK_EQ || c==WO_EQ ); + assert( op!=TK_LT || c==WO_LT ); + assert( op!=TK_LE || c==WO_LE ); + assert( op!=TK_GT || c==WO_GT ); + assert( op!=TK_GE || c==WO_GE ); + return c; +} + +/* +** Advance to the next WhereTerm that matches according to the criteria +** established when the pScan object was initialized by whereScanInit(). +** Return NULL if there are no more matching WhereTerms. +*/ +static WhereTerm *whereScanNext(WhereScan *pScan){ + int iCur; /* The cursor on the LHS of the term */ + int iColumn; /* The column on the LHS of the term. -1 for IPK */ + Expr *pX; /* An expression being tested */ + WhereClause *pWC; /* Shorthand for pScan->pWC */ + WhereTerm *pTerm; /* The term being tested */ + int k = pScan->k; /* Where to start scanning */ + + while( pScan->iEquiv<=pScan->nEquiv ){ + iCur = pScan->aEquiv[pScan->iEquiv-2]; + iColumn = pScan->aEquiv[pScan->iEquiv-1]; + while( (pWC = pScan->pWC)!=0 ){ + for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ + if( pTerm->leftCursor==iCur + && pTerm->u.leftColumn==iColumn + && (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + ){ + if( (pTerm->eOperator & WO_EQUIV)!=0 + && pScan->nEquivaEquiv) + ){ + int j; + pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); + assert( pX->op==TK_COLUMN ); + for(j=0; jnEquiv; j+=2){ + if( pScan->aEquiv[j]==pX->iTable + && pScan->aEquiv[j+1]==pX->iColumn ){ + break; + } + } + if( j==pScan->nEquiv ){ + pScan->aEquiv[j] = pX->iTable; + pScan->aEquiv[j+1] = pX->iColumn; + pScan->nEquiv += 2; + } + } + if( (pTerm->eOperator & pScan->opMask)!=0 ){ + /* Verify the affinity and collating sequence match */ + if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ + CollSeq *pColl; + Parse *pParse = pWC->pWInfo->pParse; + pX = pTerm->pExpr; + if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ + continue; + } + assert(pX->pLeft); + pColl = sqlite3BinaryCompareCollSeq(pParse, + pX->pLeft, pX->pRight); + if( pColl==0 ) pColl = pParse->db->pDfltColl; + if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ + continue; + } + } + if( (pTerm->eOperator & WO_EQ)!=0 + && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN + && pX->iTable==pScan->aEquiv[0] + && pX->iColumn==pScan->aEquiv[1] + ){ + continue; + } + pScan->k = k+1; + return pTerm; + } + } + } + pScan->pWC = pScan->pWC->pOuter; + k = 0; + } + pScan->pWC = pScan->pOrigWC; + k = 0; + pScan->iEquiv += 2; + } + return 0; +} + +/* +** Initialize a WHERE clause scanner object. Return a pointer to the +** first match. Return NULL if there are no matches. +** +** The scanner will be searching the WHERE clause pWC. It will look +** for terms of the form "X " where X is column iColumn of table +** iCur. The must be one of the operators described by opMask. +** +** If the search is for X and the WHERE clause contains terms of the +** form X=Y then this routine might also return terms of the form +** "Y ". The number of levels of transitivity is limited, +** but is enough to handle most commonly occurring SQL statements. +** +** If X is not the INTEGER PRIMARY KEY then X must be compatible with +** index pIdx. +*/ +static WhereTerm *whereScanInit( + WhereScan *pScan, /* The WhereScan object being initialized */ + WhereClause *pWC, /* The WHERE clause to be scanned */ + int iCur, /* Cursor to scan for */ + int iColumn, /* Column to scan for */ + u32 opMask, /* Operator(s) to scan for */ + Index *pIdx /* Must be compatible with this index */ +){ + int j; + + /* memset(pScan, 0, sizeof(*pScan)); */ + pScan->pOrigWC = pWC; + pScan->pWC = pWC; + if( pIdx && iColumn>=0 ){ + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; + for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ + if( NEVER(j>=pIdx->nKeyCol) ) return 0; + } + pScan->zCollName = pIdx->azColl[j]; + }else{ + pScan->idxaff = 0; + pScan->zCollName = 0; + } + pScan->opMask = opMask; + pScan->k = 0; + pScan->aEquiv[0] = iCur; + pScan->aEquiv[1] = iColumn; + pScan->nEquiv = 2; + pScan->iEquiv = 2; + return whereScanNext(pScan); +} + +/* +** Search for a term in the WHERE clause that is of the form "X " +** where X is a reference to the iColumn of table iCur and is one of +** the WO_xx operator codes specified by the op parameter. +** Return a pointer to the term. Return 0 if not found. +** +** The term returned might by Y= if there is another constraint in +** the WHERE clause that specifies that X=Y. Any such constraints will be +** identified by the WO_EQUIV bit in the pTerm->eOperator field. The +** aEquiv[] array holds X and all its equivalents, with each SQL variable +** taking up two slots in aEquiv[]. The first slot is for the cursor number +** and the second is for the column number. There are 22 slots in aEquiv[] +** so that means we can look for X plus up to 10 other equivalent values. +** Hence a search for X will return if X=A1 and A1=A2 and A2=A3 +** and ... and A9=A10 and A10=. +** +** If there are multiple terms in the WHERE clause of the form "X " +** then try for the one with no dependencies on - in other words where +** is a constant expression of some kind. Only return entries of +** the form "X Y" where Y is a column in another table if no terms of +** the form "X " exist. If no terms with a constant RHS +** exist, try to return a term that does not use WO_EQUIV. +*/ +static WhereTerm *findTerm( + WhereClause *pWC, /* The WHERE clause to be searched */ + int iCur, /* Cursor number of LHS */ + int iColumn, /* Column number of LHS */ + Bitmask notReady, /* RHS must not overlap with this mask */ + u32 op, /* Mask of WO_xx values describing operator */ + Index *pIdx /* Must be compatible with this index, if not NULL */ +){ + WhereTerm *pResult = 0; + WhereTerm *p; + WhereScan scan; + + p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); + while( p ){ + if( (p->prereqRight & notReady)==0 ){ + if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){ + return p; + } + if( pResult==0 ) pResult = p; + } + p = whereScanNext(&scan); + } + return pResult; +} + +/* Forward reference */ +static void exprAnalyze(SrcList*, WhereClause*, int); + +/* +** Call exprAnalyze on all terms in a WHERE clause. +*/ +static void exprAnalyzeAll( + SrcList *pTabList, /* the FROM clause */ + WhereClause *pWC /* the WHERE clause to be analyzed */ +){ + int i; + for(i=pWC->nTerm-1; i>=0; i--){ + exprAnalyze(pTabList, pWC, i); + } +} + +#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION +/* +** Check to see if the given expression is a LIKE or GLOB operator that +** can be optimized using inequality constraints. Return TRUE if it is +** so and false if not. +** +** In order for the operator to be optimizible, the RHS must be a string +** literal that does not begin with a wildcard. +*/ +static int isLikeOrGlob( + Parse *pParse, /* Parsing and code generating context */ + Expr *pExpr, /* Test this expression */ + Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */ + int *pisComplete, /* True if the only wildcard is % in the last character */ + int *pnoCase /* True if uppercase is equivalent to lowercase */ +){ + const char *z = 0; /* String on RHS of LIKE operator */ + Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ + ExprList *pList; /* List of operands to the LIKE operator */ + int c; /* One character in z[] */ + int cnt; /* Number of non-wildcard prefix characters */ + char wc[3]; /* Wildcard characters */ + sqlite3 *db = pParse->db; /* Database connection */ + sqlite3_value *pVal = 0; + int op; /* Opcode of pRight */ + + if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ + return 0; + } +#ifdef SQLITE_EBCDIC + if( *pnoCase ) return 0; +#endif + pList = pExpr->x.pList; + pLeft = pList->a[1].pExpr; + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->pTab) + ){ + /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must + ** be the name of an indexed column with TEXT affinity. */ + return 0; + } + assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ + + pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); + op = pRight->op; + if( op==TK_VARIABLE ){ + Vdbe *pReprepare = pParse->pReprepare; + int iCol = pRight->iColumn; + pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_NONE); + if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ + z = (char *)sqlite3_value_text(pVal); + } + sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); + assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); + }else if( op==TK_STRING ){ + z = pRight->u.zToken; + } + if( z ){ + cnt = 0; + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ + cnt++; + } + if( cnt!=0 && 255!=(u8)z[cnt-1] ){ + Expr *pPrefix; + *pisComplete = c==wc[0] && z[cnt+1]==0; + pPrefix = sqlite3Expr(db, TK_STRING, z); + if( pPrefix ) pPrefix->u.zToken[cnt] = 0; + *ppPrefix = pPrefix; + if( op==TK_VARIABLE ){ + Vdbe *v = pParse->pVdbe; + sqlite3VdbeSetVarmask(v, pRight->iColumn); + if( *pisComplete && pRight->u.zToken[1] ){ + /* If the rhs of the LIKE expression is a variable, and the current + ** value of the variable means there is no need to invoke the LIKE + ** function, then no OP_Variable will be added to the program. + ** This causes problems for the sqlite3_bind_parameter_name() + ** API. To workaround them, add a dummy OP_Variable here. + */ + int r1 = sqlite3GetTempReg(pParse); + sqlite3ExprCodeTarget(pParse, pRight, r1); + sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0); + sqlite3ReleaseTempReg(pParse, r1); + } + } + }else{ + z = 0; + } + } + + sqlite3ValueFree(pVal); + return (z!=0); +} +#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Check to see if the given expression is of the form +** +** column MATCH expr +** +** If it is then return TRUE. If not, return FALSE. +*/ +static int isMatchOfColumn( + Expr *pExpr /* Test this expression */ +){ + ExprList *pList; + + if( pExpr->op!=TK_FUNCTION ){ + return 0; + } + if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){ + return 0; + } + pList = pExpr->x.pList; + if( pList->nExpr!=2 ){ + return 0; + } + if( pList->a[1].pExpr->op != TK_COLUMN ){ + return 0; + } + return 1; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** If the pBase expression originated in the ON or USING clause of +** a join, then transfer the appropriate markings over to derived. +*/ +static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ + if( pDerived ){ + pDerived->flags |= pBase->flags & EP_FromJoin; + pDerived->iRightJoinTable = pBase->iRightJoinTable; + } +} + +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) +/* +** Analyze a term that consists of two or more OR-connected +** subterms. So in: +** +** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13) +** ^^^^^^^^^^^^^^^^^^^^ +** +** This routine analyzes terms such as the middle term in the above example. +** A WhereOrTerm object is computed and attached to the term under +** analysis, regardless of the outcome of the analysis. Hence: +** +** WhereTerm.wtFlags |= TERM_ORINFO +** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object +** +** The term being analyzed must have two or more of OR-connected subterms. +** A single subterm might be a set of AND-connected sub-subterms. +** Examples of terms under analysis: +** +** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5 +** (B) x=expr1 OR expr2=x OR x=expr3 +** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) +** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') +** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) +** +** CASE 1: +** +** If all subterms are of the form T.C=expr for some single column of C and +** a single table T (as shown in example B above) then create a new virtual +** term that is an equivalent IN expression. In other words, if the term +** being analyzed is: +** +** x = expr1 OR expr2 = x OR x = expr3 +** +** then create a new virtual term like this: +** +** x IN (expr1,expr2,expr3) +** +** CASE 2: +** +** If all subterms are indexable by a single table T, then set +** +** WhereTerm.eOperator = WO_OR +** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T +** +** A subterm is "indexable" if it is of the form +** "T.C " where C is any column of table T and +** is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN". +** A subterm is also indexable if it is an AND of two or more +** subsubterms at least one of which is indexable. Indexable AND +** subterms have their eOperator set to WO_AND and they have +** u.pAndInfo set to a dynamically allocated WhereAndTerm object. +** +** From another point of view, "indexable" means that the subterm could +** potentially be used with an index if an appropriate index exists. +** This analysis does not consider whether or not the index exists; that +** is decided elsewhere. This analysis only looks at whether subterms +** appropriate for indexing exist. +** +** All examples A through E above satisfy case 2. But if a term +** also statisfies case 1 (such as B) we know that the optimizer will +** always prefer case 1, so in that case we pretend that case 2 is not +** satisfied. +** +** It might be the case that multiple tables are indexable. For example, +** (E) above is indexable on tables P, Q, and R. +** +** Terms that satisfy case 2 are candidates for lookup by using +** separate indices to find rowids for each subterm and composing +** the union of all rowids using a RowSet object. This is similar +** to "bitmap indices" in other database engines. +** +** OTHERWISE: +** +** If neither case 1 nor case 2 apply, then leave the eOperator set to +** zero. This term is not useful for search. +*/ +static void exprAnalyzeOrTerm( + SrcList *pSrc, /* the FROM clause */ + WhereClause *pWC, /* the complete WHERE clause */ + int idxTerm /* Index of the OR-term to be analyzed */ +){ + WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ + Parse *pParse = pWInfo->pParse; /* Parser context */ + sqlite3 *db = pParse->db; /* Database connection */ + WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ + Expr *pExpr = pTerm->pExpr; /* The expression of the term */ + int i; /* Loop counters */ + WhereClause *pOrWc; /* Breakup of pTerm into subterms */ + WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ + WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ + Bitmask chngToIN; /* Tables that might satisfy case 1 */ + Bitmask indexable; /* Tables that are indexable, satisfying case 2 */ + + /* + ** Break the OR clause into its separate subterms. The subterms are + ** stored in a WhereClause structure containing within the WhereOrInfo + ** object that is attached to the original OR clause term. + */ + assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 ); + assert( pExpr->op==TK_OR ); + pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo)); + if( pOrInfo==0 ) return; + pTerm->wtFlags |= TERM_ORINFO; + pOrWc = &pOrInfo->wc; + whereClauseInit(pOrWc, pWInfo); + whereSplit(pOrWc, pExpr, TK_OR); + exprAnalyzeAll(pSrc, pOrWc); + if( db->mallocFailed ) return; + assert( pOrWc->nTerm>=2 ); + + /* + ** Compute the set of tables that might satisfy cases 1 or 2. + */ + indexable = ~(Bitmask)0; + chngToIN = ~(Bitmask)0; + for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ + if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ + WhereAndInfo *pAndInfo; + assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); + chngToIN = 0; + pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); + if( pAndInfo ){ + WhereClause *pAndWC; + WhereTerm *pAndTerm; + int j; + Bitmask b = 0; + pOrTerm->u.pAndInfo = pAndInfo; + pOrTerm->wtFlags |= TERM_ANDINFO; + pOrTerm->eOperator = WO_AND; + pAndWC = &pAndInfo->wc; + whereClauseInit(pAndWC, pWC->pWInfo); + whereSplit(pAndWC, pOrTerm->pExpr, TK_AND); + exprAnalyzeAll(pSrc, pAndWC); + pAndWC->pOuter = pWC; + testcase( db->mallocFailed ); + if( !db->mallocFailed ){ + for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ + assert( pAndTerm->pExpr ); + if( allowedOp(pAndTerm->pExpr->op) ){ + b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); + } + } + } + indexable &= b; + } + }else if( pOrTerm->wtFlags & TERM_COPIED ){ + /* Skip this term for now. We revisit it when we process the + ** corresponding TERM_VIRTUAL term */ + }else{ + Bitmask b; + b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor); + if( pOrTerm->wtFlags & TERM_VIRTUAL ){ + WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; + b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor); + } + indexable &= b; + if( (pOrTerm->eOperator & WO_EQ)==0 ){ + chngToIN = 0; + }else{ + chngToIN &= b; + } + } + } + + /* + ** Record the set of tables that satisfy case 2. The set might be + ** empty. + */ + pOrInfo->indexable = indexable; + pTerm->eOperator = indexable==0 ? 0 : WO_OR; + + /* + ** chngToIN holds a set of tables that *might* satisfy case 1. But + ** we have to do some additional checking to see if case 1 really + ** is satisfied. + ** + ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means + ** that there is no possibility of transforming the OR clause into an + ** IN operator because one or more terms in the OR clause contain + ** something other than == on a column in the single table. The 1-bit + ** case means that every term of the OR clause is of the form + ** "table.column=expr" for some single table. The one bit that is set + ** will correspond to the common table. We still need to check to make + ** sure the same column is used on all terms. The 2-bit case is when + ** the all terms are of the form "table1.column=table2.column". It + ** might be possible to form an IN operator with either table1.column + ** or table2.column as the LHS if either is common to every term of + ** the OR clause. + ** + ** Note that terms of the form "table.column1=table.column2" (the + ** same table on both sizes of the ==) cannot be optimized. + */ + if( chngToIN ){ + int okToChngToIN = 0; /* True if the conversion to IN is valid */ + int iColumn = -1; /* Column index on lhs of IN operator */ + int iCursor = -1; /* Table cursor common to all terms */ + int j = 0; /* Loop counter */ + + /* Search for a table and column that appears on one side or the + ** other of the == operator in every subterm. That table and column + ** will be recorded in iCursor and iColumn. There might not be any + ** such table and column. Set okToChngToIN if an appropriate table + ** and column is found but leave okToChngToIN false if not found. + */ + for(j=0; j<2 && !okToChngToIN; j++){ + pOrTerm = pOrWc->a; + for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ + assert( pOrTerm->eOperator & WO_EQ ); + pOrTerm->wtFlags &= ~TERM_OR_OK; + if( pOrTerm->leftCursor==iCursor ){ + /* This is the 2-bit case and we are on the second iteration and + ** current term is from the first iteration. So skip this term. */ + assert( j==1 ); + continue; + } + if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){ + /* This term must be of the form t1.a==t2.b where t2 is in the + ** chngToIN set but t1 is not. This term will be either preceeded + ** or follwed by an inverted copy (t2.b==t1.a). Skip this term + ** and use its inversion. */ + testcase( pOrTerm->wtFlags & TERM_COPIED ); + testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); + assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); + continue; + } + iColumn = pOrTerm->u.leftColumn; + iCursor = pOrTerm->leftCursor; + break; + } + if( i<0 ){ + /* No candidate table+column was found. This can only occur + ** on the second iteration */ + assert( j==1 ); + assert( IsPowerOfTwo(chngToIN) ); + assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) ); + break; + } + testcase( j==1 ); + + /* We have found a candidate table and column. Check to see if that + ** table and column is common to every term in the OR clause */ + okToChngToIN = 1; + for(; i>=0 && okToChngToIN; i--, pOrTerm++){ + assert( pOrTerm->eOperator & WO_EQ ); + if( pOrTerm->leftCursor!=iCursor ){ + pOrTerm->wtFlags &= ~TERM_OR_OK; + }else if( pOrTerm->u.leftColumn!=iColumn ){ + okToChngToIN = 0; + }else{ + int affLeft, affRight; + /* If the right-hand side is also a column, then the affinities + ** of both right and left sides must be such that no type + ** conversions are required on the right. (Ticket #2249) + */ + affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); + affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); + if( affRight!=0 && affRight!=affLeft ){ + okToChngToIN = 0; + }else{ + pOrTerm->wtFlags |= TERM_OR_OK; + } + } + } + } + + /* At this point, okToChngToIN is true if original pTerm satisfies + ** case 1. In that case, construct a new virtual term that is + ** pTerm converted into an IN operator. + */ + if( okToChngToIN ){ + Expr *pDup; /* A transient duplicate expression */ + ExprList *pList = 0; /* The RHS of the IN operator */ + Expr *pLeft = 0; /* The LHS of the IN operator */ + Expr *pNew; /* The complete IN operator */ + + for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ + if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; + assert( pOrTerm->eOperator & WO_EQ ); + assert( pOrTerm->leftCursor==iCursor ); + assert( pOrTerm->u.leftColumn==iColumn ); + pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); + pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); + pLeft = pOrTerm->pExpr->pLeft; + } + assert( pLeft!=0 ); + pDup = sqlite3ExprDup(db, pLeft, 0); + pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); + if( pNew ){ + int idxNew; + transferJoinMarkings(pNew, pExpr); + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + pNew->x.pList = pList; + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + exprAnalyze(pSrc, pWC, idxNew); + pTerm = &pWC->a[idxTerm]; + pWC->a[idxNew].iParent = idxTerm; + pTerm->nChild = 1; + }else{ + sqlite3ExprListDelete(db, pList); + } + pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ + } + } +} +#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ + +/* +** The input to this routine is an WhereTerm structure with only the +** "pExpr" field filled in. The job of this routine is to analyze the +** subexpression and populate all the other fields of the WhereTerm +** structure. +** +** If the expression is of the form " X" it gets commuted +** to the standard form of "X ". +** +** If the expression is of the form "X Y" where both X and Y are +** columns, then the original expression is unchanged and a new virtual +** term of the form "Y X" is added to the WHERE clause and +** analyzed separately. The original term is marked with TERM_COPIED +** and the new term is marked with TERM_DYNAMIC (because it's pExpr +** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it +** is a commuted copy of a prior term.) The original term has nChild=1 +** and the copy has idxParent set to the index of the original term. +*/ +static void exprAnalyze( + SrcList *pSrc, /* the FROM clause */ + WhereClause *pWC, /* the WHERE clause */ + int idxTerm /* Index of the term to be analyzed */ +){ + WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ + WhereTerm *pTerm; /* The term to be analyzed */ + WhereMaskSet *pMaskSet; /* Set of table index masks */ + Expr *pExpr; /* The expression to be analyzed */ + Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ + Bitmask prereqAll; /* Prerequesites of pExpr */ + Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ + Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ + int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ + int noCase = 0; /* LIKE/GLOB distinguishes case */ + int op; /* Top-level operator. pExpr->op */ + Parse *pParse = pWInfo->pParse; /* Parsing context */ + sqlite3 *db = pParse->db; /* Database connection */ + + if( db->mallocFailed ){ + return; + } + pTerm = &pWC->a[idxTerm]; + pMaskSet = &pWInfo->sMaskSet; + pExpr = pTerm->pExpr; + assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); + prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); + op = pExpr->op; + if( op==TK_IN ){ + assert( pExpr->pRight==0 ); + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); + }else{ + pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList); + } + }else if( op==TK_ISNULL ){ + pTerm->prereqRight = 0; + }else{ + pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); + } + prereqAll = exprTableUsage(pMaskSet, pExpr); + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable); + prereqAll |= x; + extraRight = x-1; /* ON clause terms may not be used with an index + ** on left table of a LEFT JOIN. Ticket #3015 */ + } + pTerm->prereqAll = prereqAll; + pTerm->leftCursor = -1; + pTerm->iParent = -1; + pTerm->eOperator = 0; + if( allowedOp(op) ){ + Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); + Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); + u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; + if( pLeft->op==TK_COLUMN ){ + pTerm->leftCursor = pLeft->iTable; + pTerm->u.leftColumn = pLeft->iColumn; + pTerm->eOperator = operatorMask(op) & opMask; + } + if( pRight && pRight->op==TK_COLUMN ){ + WhereTerm *pNew; + Expr *pDup; + u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ + if( pTerm->leftCursor>=0 ){ + int idxNew; + pDup = sqlite3ExprDup(db, pExpr, 0); + if( db->mallocFailed ){ + sqlite3ExprDelete(db, pDup); + return; + } + idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); + if( idxNew==0 ) return; + pNew = &pWC->a[idxNew]; + pNew->iParent = idxTerm; + pTerm = &pWC->a[idxTerm]; + pTerm->nChild = 1; + pTerm->wtFlags |= TERM_COPIED; + if( pExpr->op==TK_EQ + && !ExprHasProperty(pExpr, EP_FromJoin) + && OptimizationEnabled(db, SQLITE_Transitive) + ){ + pTerm->eOperator |= WO_EQUIV; + eExtraOp = WO_EQUIV; + } + }else{ + pDup = pExpr; + pNew = pTerm; + } + exprCommute(pParse, pDup); + pLeft = sqlite3ExprSkipCollate(pDup->pLeft); + pNew->leftCursor = pLeft->iTable; + pNew->u.leftColumn = pLeft->iColumn; + testcase( (prereqLeft | extraRight) != prereqLeft ); + pNew->prereqRight = prereqLeft | extraRight; + pNew->prereqAll = prereqAll; + pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; + } + } + +#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION + /* If a term is the BETWEEN operator, create two new virtual terms + ** that define the range that the BETWEEN implements. For example: + ** + ** a BETWEEN b AND c + ** + ** is converted into: + ** + ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c) + ** + ** The two new terms are added onto the end of the WhereClause object. + ** The new terms are "dynamic" and are children of the original BETWEEN + ** term. That means that if the BETWEEN term is coded, the children are + ** skipped. Or, if the children are satisfied by an index, the original + ** BETWEEN term is skipped. + */ + else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ + ExprList *pList = pExpr->x.pList; + int i; + static const u8 ops[] = {TK_GE, TK_LE}; + assert( pList!=0 ); + assert( pList->nExpr==2 ); + for(i=0; i<2; i++){ + Expr *pNewExpr; + int idxNew; + pNewExpr = sqlite3PExpr(pParse, ops[i], + sqlite3ExprDup(db, pExpr->pLeft, 0), + sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); + transferJoinMarkings(pNewExpr, pExpr); + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + exprAnalyze(pSrc, pWC, idxNew); + pTerm = &pWC->a[idxTerm]; + pWC->a[idxNew].iParent = idxTerm; + } + pTerm->nChild = 2; + } +#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ + +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) + /* Analyze a term that is composed of two or more subterms connected by + ** an OR operator. + */ + else if( pExpr->op==TK_OR ){ + assert( pWC->op==TK_AND ); + exprAnalyzeOrTerm(pSrc, pWC, idxTerm); + pTerm = &pWC->a[idxTerm]; + } +#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ + +#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION + /* Add constraints to reduce the search space on a LIKE or GLOB + ** operator. + ** + ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints + ** + ** x>='abc' AND x<'abd' AND x LIKE 'abc%' + ** + ** The last character of the prefix "abc" is incremented to form the + ** termination condition "abd". + */ + if( pWC->op==TK_AND + && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) + ){ + Expr *pLeft; /* LHS of LIKE/GLOB operator */ + Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ + Expr *pNewExpr1; + Expr *pNewExpr2; + int idxNew1; + int idxNew2; + Token sCollSeqName; /* Name of collating sequence */ + + pLeft = pExpr->x.pList->a[1].pExpr; + pStr2 = sqlite3ExprDup(db, pStr1, 0); + if( !db->mallocFailed ){ + u8 c, *pC; /* Last character before the first wildcard */ + pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; + c = *pC; + if( noCase ){ + /* The point is to increment the last character before the first + ** wildcard. But if we increment '@', that will push it into the + ** alphabetic range where case conversions will mess up the + ** inequality. To avoid this, make sure to also run the full + ** LIKE on all candidate expressions by clearing the isComplete flag + */ + if( c=='A'-1 ) isComplete = 0; + c = sqlite3UpperToLower[c]; + } + *pC = c + 1; + } + sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; + sCollSeqName.n = 6; + pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, + sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), + pStr1, 0); + transferJoinMarkings(pNewExpr1, pExpr); + idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew1==0 ); + exprAnalyze(pSrc, pWC, idxNew1); + pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); + pNewExpr2 = sqlite3PExpr(pParse, TK_LT, + sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), + pStr2, 0); + transferJoinMarkings(pNewExpr2, pExpr); + idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew2==0 ); + exprAnalyze(pSrc, pWC, idxNew2); + pTerm = &pWC->a[idxTerm]; + if( isComplete ){ + pWC->a[idxNew1].iParent = idxTerm; + pWC->a[idxNew2].iParent = idxTerm; + pTerm->nChild = 2; + } + } +#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Add a WO_MATCH auxiliary term to the constraint set if the + ** current expression is of the form: column MATCH expr. + ** This information is used by the xBestIndex methods of + ** virtual tables. The native query optimizer does not attempt + ** to do anything with MATCH functions. + */ + if( isMatchOfColumn(pExpr) ){ + int idxNew; + Expr *pRight, *pLeft; + WhereTerm *pNewTerm; + Bitmask prereqColumn, prereqExpr; + + pRight = pExpr->x.pList->a[0].pExpr; + pLeft = pExpr->x.pList->a[1].pExpr; + prereqExpr = exprTableUsage(pMaskSet, pRight); + prereqColumn = exprTableUsage(pMaskSet, pLeft); + if( (prereqExpr & prereqColumn)==0 ){ + Expr *pNewExpr; + pNewExpr = sqlite3PExpr(pParse, TK_MATCH, + 0, sqlite3ExprDup(db, pRight, 0), 0); + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = prereqExpr; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->u.leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_MATCH; + pNewTerm->iParent = idxTerm; + pTerm = &pWC->a[idxTerm]; + pTerm->nChild = 1; + pTerm->wtFlags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + } +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + /* When sqlite_stat3 histogram data is available an operator of the + ** form "x IS NOT NULL" can sometimes be evaluated more efficiently + ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a + ** virtual term of that form. + ** + ** Note that the virtual term must be tagged with TERM_VNULL. This + ** TERM_VNULL tag will suppress the not-null check at the beginning + ** of the loop. Without the TERM_VNULL flag, the not-null check at + ** the start of the loop will prevent any results from being returned. + */ + if( pExpr->op==TK_NOTNULL + && pExpr->pLeft->op==TK_COLUMN + && pExpr->pLeft->iColumn>=0 + && OptimizationEnabled(db, SQLITE_Stat3) + ){ + Expr *pNewExpr; + Expr *pLeft = pExpr->pLeft; + int idxNew; + WhereTerm *pNewTerm; + + pNewExpr = sqlite3PExpr(pParse, TK_GT, + sqlite3ExprDup(db, pLeft, 0), + sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); + + idxNew = whereClauseInsert(pWC, pNewExpr, + TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); + if( idxNew ){ + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = 0; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->u.leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_GT; + pNewTerm->iParent = idxTerm; + pTerm = &pWC->a[idxTerm]; + pTerm->nChild = 1; + pTerm->wtFlags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + } +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + + /* Prevent ON clause terms of a LEFT JOIN from being used to drive + ** an index for tables to the left of the join. + */ + pTerm->prereqRight |= extraRight; +} + +/* +** This function searches pList for a entry that matches the iCol-th column +** of index pIdx. +** +** If such an expression is found, its index in pList->a[] is returned. If +** no expression is found, -1 is returned. +*/ +static int findIndexCol( + Parse *pParse, /* Parse context */ + ExprList *pList, /* Expression list to search */ + int iBase, /* Cursor for table associated with pIdx */ + Index *pIdx, /* Index to match column of */ + int iCol /* Column of index to match */ +){ + int i; + const char *zColl = pIdx->azColl[iCol]; + + for(i=0; inExpr; i++){ + Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); + if( p->op==TK_COLUMN + && p->iColumn==pIdx->aiColumn[iCol] + && p->iTable==iBase + ){ + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); + if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ + return i; + } + } + } + + return -1; +} + +/* +** Return true if the DISTINCT expression-list passed as the third argument +** is redundant. +** +** A DISTINCT list is redundant if the database contains some subset of +** columns that are unique and non-null. +*/ +static int isDistinctRedundant( + Parse *pParse, /* Parsing context */ + SrcList *pTabList, /* The FROM clause */ + WhereClause *pWC, /* The WHERE clause */ + ExprList *pDistinct /* The result set that needs to be DISTINCT */ +){ + Table *pTab; + Index *pIdx; + int i; + int iBase; + + /* If there is more than one table or sub-select in the FROM clause of + ** this query, then it will not be possible to show that the DISTINCT + ** clause is redundant. */ + if( pTabList->nSrc!=1 ) return 0; + iBase = pTabList->a[0].iCursor; + pTab = pTabList->a[0].pTab; + + /* If any of the expressions is an IPK column on table iBase, then return + ** true. Note: The (p->iTable==iBase) part of this test may be false if the + ** current SELECT is a correlated sub-query. + */ + for(i=0; inExpr; i++){ + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); + if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; + } + + /* Loop through all indices on the table, checking each to see if it makes + ** the DISTINCT qualifier redundant. It does so if: + ** + ** 1. The index is itself UNIQUE, and + ** + ** 2. All of the columns in the index are either part of the pDistinct + ** list, or else the WHERE clause contains a term of the form "col=X", + ** where X is a constant value. The collation sequences of the + ** comparison and select-list expressions must match those of the index. + ** + ** 3. All of those index columns for which the WHERE clause does not + ** contain a "col=X" term are subject to a NOT NULL constraint. + */ + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->onError==OE_None ) continue; + for(i=0; inKeyCol; i++){ + i16 iCol = pIdx->aiColumn[i]; + if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){ + int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i); + if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){ + break; + } + } + } + if( i==pIdx->nKeyCol ){ + /* This index implies that the DISTINCT qualifier is redundant. */ + return 1; + } + } + + return 0; +} + + +/* +** Estimate the logarithm of the input value to base 2. +*/ +static LogEst estLog(LogEst N){ + LogEst x = sqlite3LogEst(N); + return x>33 ? x - 33 : 0; +} + +/* +** Two routines for printing the content of an sqlite3_index_info +** structure. Used for testing and debugging only. If neither +** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines +** are no-ops. +*/ +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) +static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ + int i; + if( !sqlite3WhereTrace ) return; + for(i=0; inConstraint; i++){ + sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", + i, + p->aConstraint[i].iColumn, + p->aConstraint[i].iTermOffset, + p->aConstraint[i].op, + p->aConstraint[i].usable); + } + for(i=0; inOrderBy; i++){ + sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", + i, + p->aOrderBy[i].iColumn, + p->aOrderBy[i].desc); + } +} +static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ + int i; + if( !sqlite3WhereTrace ) return; + for(i=0; inConstraint; i++){ + sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", + i, + p->aConstraintUsage[i].argvIndex, + p->aConstraintUsage[i].omit); + } + sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); + sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); + sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); + sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); + sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); +} +#else +#define TRACE_IDX_INPUTS(A) +#define TRACE_IDX_OUTPUTS(A) +#endif + +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX +/* +** Return TRUE if the WHERE clause term pTerm is of a form where it +** could be used with an index to access pSrc, assuming an appropriate +** index existed. +*/ +static int termCanDriveIndex( + WhereTerm *pTerm, /* WHERE clause term to check */ + struct SrcList_item *pSrc, /* Table we are trying to access */ + Bitmask notReady /* Tables in outer loops of the join */ +){ + char aff; + if( pTerm->leftCursor!=pSrc->iCursor ) return 0; + if( (pTerm->eOperator & WO_EQ)==0 ) return 0; + if( (pTerm->prereqRight & notReady)!=0 ) return 0; + if( pTerm->u.leftColumn<0 ) return 0; + aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; + if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; + return 1; } #endif +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX +/* +** Generate code to construct the Index object for an automatic index +** and to set up the WhereLevel object pLevel so that the code generator +** makes use of the automatic index. +*/ +static void constructAutomaticIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ + Bitmask notReady, /* Mask of cursors that are not available */ + WhereLevel *pLevel /* Write new index here */ +){ + int nKeyCol; /* Number of columns in the constructed index */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + WhereTerm *pWCEnd; /* End of pWC->a[] */ + Index *pIdx; /* Object describing the transient index */ + Vdbe *v; /* Prepared statement under construction */ + int addrInit; /* Address of the initialization bypass jump */ + Table *pTable; /* The table being indexed */ + int addrTop; /* Top of the index fill loop */ + int regRecord; /* Register holding an index record */ + int n; /* Column counter */ + int i; /* Loop counter */ + int mxBitCol; /* Maximum column in pSrc->colUsed */ + CollSeq *pColl; /* Collating sequence to on a column */ + WhereLoop *pLoop; /* The Loop object */ + char *zNotUsed; /* Extra space on the end of pIdx */ + Bitmask idxCols; /* Bitmap of columns used for indexing */ + Bitmask extraCols; /* Bitmap of additional columns */ + u8 sentWarning = 0; /* True if a warnning has been issued */ + + /* Generate code to skip over the creation and initialization of the + ** transient index on 2nd and subsequent iterations of the loop. */ + v = pParse->pVdbe; + assert( v!=0 ); + addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); + + /* Count the number of columns that will be added to the index + ** and used to match WHERE clause constraints */ + nKeyCol = 0; + pTable = pSrc->pTab; + pWCEnd = &pWC->a[pWC->nTerm]; + pLoop = pLevel->pWLoop; + idxCols = 0; + for(pTerm=pWC->a; pTermu.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + testcase( iCol==BMS ); + testcase( iCol==BMS-1 ); + if( !sentWarning ){ + sqlite3_log(SQLITE_WARNING_AUTOINDEX, + "automatic index on %s(%s)", pTable->zName, + pTable->aCol[iCol].zName); + sentWarning = 1; + } + if( (idxCols & cMask)==0 ){ + if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return; + pLoop->aLTerm[nKeyCol++] = pTerm; + idxCols |= cMask; + } + } + } + assert( nKeyCol>0 ); + pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol; + pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED + | WHERE_AUTO_INDEX; + + /* Count the number of additional columns needed to create a + ** covering index. A "covering index" is an index that contains all + ** columns that are needed by the query. With a covering index, the + ** original table never needs to be accessed. Automatic indices must + ** be a covering index because the index will not be updated if the + ** original table changes and the index and table cannot both be used + ** if they go out of sync. + */ + extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); + mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol; + testcase( pTable->nCol==BMS-1 ); + testcase( pTable->nCol==BMS-2 ); + for(i=0; icolUsed & MASKBIT(BMS-1) ){ + nKeyCol += pTable->nCol - BMS + 1; + } + pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY; + + /* Construct the Index object to describe this index */ + pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); + if( pIdx==0 ) return; + pLoop->u.btree.pIndex = pIdx; + pIdx->zName = "auto-index"; + pIdx->pTable = pTable; + n = 0; + idxCols = 0; + for(pTerm=pWC->a; pTermu.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + testcase( iCol==BMS-1 ); + testcase( iCol==BMS ); + if( (idxCols & cMask)==0 ){ + Expr *pX = pTerm->pExpr; + idxCols |= cMask; + pIdx->aiColumn[n] = pTerm->u.leftColumn; + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); + pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; + n++; + } + } + } + assert( (u32)n==pLoop->u.btree.nEq ); + + /* Add additional columns needed to make the automatic index into + ** a covering index */ + for(i=0; iaiColumn[n] = i; + pIdx->azColl[n] = "BINARY"; + n++; + } + } + if( pSrc->colUsed & MASKBIT(BMS-1) ){ + for(i=BMS-1; inCol; i++){ + pIdx->aiColumn[n] = i; + pIdx->azColl[n] = "BINARY"; + n++; + } + } + assert( n==nKeyCol ); + pIdx->aiColumn[n] = -1; + pIdx->azColl[n] = "BINARY"; + + /* Create the automatic index */ + assert( pLevel->iIdxCur>=0 ); + pLevel->iIdxCur = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "for %s", pTable->zName)); + + /* Fill the automatic index with content */ + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); + regRecord = sqlite3GetTempReg(pParse); + sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); + sqlite3VdbeJumpHere(v, addrTop); + sqlite3ReleaseTempReg(pParse, regRecord); + + /* Jump here when skipping the initialization */ + sqlite3VdbeJumpHere(v, addrInit); +} +#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Allocate and populate an sqlite3_index_info structure. It is the +** responsibility of the caller to eventually release the structure +** by passing the pointer returned by this function to sqlite3_free(). +*/ +static sqlite3_index_info *allocateIndexInfo( + Parse *pParse, + WhereClause *pWC, + struct SrcList_item *pSrc, + ExprList *pOrderBy +){ + int i, j; + int nTerm; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_orderby *pIdxOrderBy; + struct sqlite3_index_constraint_usage *pUsage; + WhereTerm *pTerm; + int nOrderBy; + sqlite3_index_info *pIdxInfo; + + /* Count the number of possible WHERE clause constraints referring + ** to this virtual table */ + for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; + nTerm++; + } + + /* If the ORDER BY clause contains only columns in the current + ** virtual table then allocate space for the aOrderBy part of + ** the sqlite3_index_info structure. + */ + nOrderBy = 0; + if( pOrderBy ){ + int n = pOrderBy->nExpr; + for(i=0; ia[i].pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + } + if( i==n){ + nOrderBy = n; + } + } + + /* Allocate the sqlite3_index_info structure + */ + pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + + sizeof(*pIdxOrderBy)*nOrderBy ); + if( pIdxInfo==0 ){ + sqlite3ErrorMsg(pParse, "out of memory"); + return 0; + } + + /* Initialize the structure. The sqlite3_index_info structure contains + ** many fields that are declared "const" to prevent xBestIndex from + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ + pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; + pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; + pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; + *(int*)&pIdxInfo->nConstraint = nTerm; + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; + *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + + for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + u8 op; + if( pTerm->leftCursor != pSrc->iCursor ) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; + op = (u8)pTerm->eOperator & WO_ALL; + if( op==WO_IN ) op = WO_EQ; + pIdxCons[j].op = op; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); + assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + j++; + } + for(i=0; ia[i].pExpr; + pIdxOrderBy[i].iColumn = pExpr->iColumn; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + } + + return pIdxInfo; +} + +/* +** The table object reference passed as the second argument to this function +** must represent a virtual table. This function invokes the xBestIndex() +** method of the virtual table with the sqlite3_index_info object that +** comes in as the 3rd argument to this function. +** +** If an error occurs, pParse is populated with an error message and a +** non-zero value is returned. Otherwise, 0 is returned and the output +** part of the sqlite3_index_info structure is left populated. +** +** Whether or not an error is returned, it is the responsibility of the +** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates +** that this is required. +*/ +static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ + sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; + int i; + int rc; + + TRACE_IDX_INPUTS(p); + rc = pVtab->pModule->xBestIndex(pVtab, p); + TRACE_IDX_OUTPUTS(p); + + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + pParse->db->mallocFailed = 1; + }else if( !pVtab->zErrMsg ){ + sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); + }else{ + sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); + } + } + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; + + for(i=0; inConstraint; i++){ + if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ + sqlite3ErrorMsg(pParse, + "table %s: xBestIndex returned an invalid plan", pTab->zName); + } + } + + return pParse->nErr; +} +#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ + + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** Estimate the location of a particular key among all keys in an +** index. Store the results in aStat as follows: +** +** aStat[0] Est. number of rows less than pVal +** aStat[1] Est. number of rows equal to pVal +** +** Return SQLITE_OK on success. +*/ +static void whereKeyStats( + Parse *pParse, /* Database connection */ + Index *pIdx, /* Index to consider domain of */ + UnpackedRecord *pRec, /* Vector of values to consider */ + int roundUp, /* Round up if true. Round down if false */ + tRowcnt *aStat /* OUT: stats written here */ +){ + IndexSample *aSample = pIdx->aSample; + int iCol; /* Index of required stats in anEq[] etc. */ + int iMin = 0; /* Smallest sample not yet tested */ + int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ + int iTest; /* Next sample to test */ + int res; /* Result of comparison operation */ + +#ifndef SQLITE_DEBUG + UNUSED_PARAMETER( pParse ); +#endif + assert( pRec!=0 ); + iCol = pRec->nField - 1; + assert( pIdx->nSample>0 ); + assert( pRec->nField>0 && iColnSampleCol ); + do{ + iTest = (iMin+i)/2; + res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0); + if( res<0 ){ + iMin = iTest+1; + }else{ + i = iTest; + } + }while( res && iMinnSample ); + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0) + || pParse->db->mallocFailed ); + }else{ + /* Otherwise, pRec must be smaller than sample $i and larger than + ** sample ($i-1). */ + assert( i==pIdx->nSample + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0 + || pParse->db->mallocFailed ); + assert( i==0 + || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0 + || pParse->db->mallocFailed ); + } +#endif /* ifdef SQLITE_DEBUG */ + + /* At this point, aSample[i] is the first sample that is greater than + ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less + ** than pVal. If aSample[i]==pVal, then res==0. + */ + if( res==0 ){ + aStat[0] = aSample[i].anLt[iCol]; + aStat[1] = aSample[i].anEq[iCol]; + }else{ + tRowcnt iLower, iUpper, iGap; + if( i==0 ){ + iLower = 0; + iUpper = aSample[0].anLt[iCol]; + }else{ + i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); + iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol]; + iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; + } + aStat[1] = (pIdx->nKeyCol>iCol ? pIdx->aAvgEq[iCol] : 1); + if( iLower>=iUpper ){ + iGap = 0; + }else{ + iGap = iUpper - iLower; + } + if( roundUp ){ + iGap = (iGap*2)/3; + }else{ + iGap = iGap/3; + } + aStat[0] = iLower + iGap; + } +} +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + +/* +** If it is not NULL, pTerm is a term that provides an upper or lower +** bound on a range scan. Without considering pTerm, it is estimated +** that the scan will visit nNew rows. This function returns the number +** estimated to be visited after taking pTerm into account. +** +** If the user explicitly specified a likelihood() value for this term, +** then the return value is the likelihood multiplied by the number of +** input rows. Otherwise, this function assumes that an "IS NOT NULL" term +** has a likelihood of 0.50, and any other term a likelihood of 0.25. +*/ +static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ + LogEst nRet = nNew; + if( pTerm ){ + if( pTerm->truthProb<=0 ){ + nRet += pTerm->truthProb; + }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){ + nRet -= 20; assert( 20==sqlite3LogEst(4) ); + } + } + return nRet; +} + +/* +** This function is used to estimate the number of rows that will be visited +** by scanning an index for a range of values. The range may have an upper +** bound, a lower bound, or both. The WHERE clause terms that set the upper +** and lower bounds are represented by pLower and pUpper respectively. For +** example, assuming that index p is on t1(a): +** +** ... FROM t1 WHERE a > ? AND a < ? ... +** |_____| |_____| +** | | +** pLower pUpper +** +** If either of the upper or lower bound is not present, then NULL is passed in +** place of the corresponding WhereTerm. +** +** The value in (pBuilder->pNew->u.btree.nEq) is the index of the index +** column subject to the range constraint. Or, equivalently, the number of +** equality constraints optimized by the proposed index scan. For example, +** assuming index p is on t1(a, b), and the SQL query is: +** +** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... +** +** then nEq is set to 1 (as the range restricted column, b, is the second +** left-most column of the index). Or, if the query is: +** +** ... FROM t1 WHERE a > ? AND a < ? ... +** +** then nEq is set to 0. +** +** When this function is called, *pnOut is set to the sqlite3LogEst() of the +** number of rows that the index scan is expected to visit without +** considering the range constraints. If nEq is 0, this is the number of +** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) +** to account for the range contraints pLower and pUpper. +** +** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be +** used, each range inequality reduces the search space by a factor of 4. +** Hence a pair of constraints (x>? AND x123" Might be NULL */ + WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ + WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ +){ + int rc = SQLITE_OK; + int nOut = pLoop->nOut; + LogEst nNew; + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + Index *p = pLoop->u.btree.pIndex; + int nEq = pLoop->u.btree.nEq; + + if( p->nSample>0 + && nEq==pBuilder->nRecValid + && nEqnSampleCol + && OptimizationEnabled(pParse->db, SQLITE_Stat3) + ){ + UnpackedRecord *pRec = pBuilder->pRec; + tRowcnt a[2]; + u8 aff; + + /* Variable iLower will be set to the estimate of the number of rows in + ** the index that are less than the lower bound of the range query. The + ** lower bound being the concatenation of $P and $L, where $P is the + ** key-prefix formed by the nEq values matched against the nEq left-most + ** columns of the index, and $L is the value in pLower. + ** + ** Or, if pLower is NULL or $L cannot be extracted from it (because it + ** is not a simple variable or literal value), the lower bound of the + ** range is $P. Due to a quirk in the way whereKeyStats() works, even + ** if $L is available, whereKeyStats() is called for both ($P) and + ** ($P:$L) and the larger of the two returned values used. + ** + ** Similarly, iUpper is to be set to the estimate of the number of rows + ** less than the upper bound of the range query. Where the upper bound + ** is either ($P) or ($P:$U). Again, even if $U is available, both values + ** of iUpper are requested of whereKeyStats() and the smaller used. + */ + tRowcnt iLower; + tRowcnt iUpper; + + if( nEq==p->nKeyCol ){ + aff = SQLITE_AFF_INTEGER; + }else{ + aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; + } + /* Determine iLower and iUpper using ($P) only. */ + if( nEq==0 ){ + iLower = 0; + iUpper = sqlite3LogEstToInt(p->aiRowLogEst[0]); + }else{ + /* Note: this call could be optimized away - since the same values must + ** have been requested when testing key $P in whereEqualScanEst(). */ + whereKeyStats(pParse, p, pRec, 0, a); + iLower = a[0]; + iUpper = a[0] + a[1]; + } + + /* If possible, improve on the iLower estimate using ($P:$L). */ + if( pLower ){ + int bOk; /* True if value is extracted from pExpr */ + Expr *pExpr = pLower->pExpr->pRight; + assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); + if( rc==SQLITE_OK && bOk ){ + tRowcnt iNew; + whereKeyStats(pParse, p, pRec, 0, a); + iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); + if( iNew>iLower ) iLower = iNew; + nOut--; + } + } + + /* If possible, improve on the iUpper estimate using ($P:$U). */ + if( pUpper ){ + int bOk; /* True if value is extracted from pExpr */ + Expr *pExpr = pUpper->pExpr->pRight; + assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); + if( rc==SQLITE_OK && bOk ){ + tRowcnt iNew; + whereKeyStats(pParse, p, pRec, 1, a); + iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); + if( iNewpRec = pRec; + if( rc==SQLITE_OK ){ + if( iUpper>iLower ){ + nNew = sqlite3LogEst(iUpper - iLower); + }else{ + nNew = 10; assert( 10==sqlite3LogEst(2) ); + } + if( nNewnOut = (LogEst)nOut; + WHERETRACE(0x10, ("range scan regions: %u..%u est=%d\n", + (u32)iLower, (u32)iUpper, nOut)); + return SQLITE_OK; + } + } +#else + UNUSED_PARAMETER(pParse); + UNUSED_PARAMETER(pBuilder); +#endif + assert( pLower || pUpper ); + assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); + nNew = whereRangeAdjust(pLower, nOut); + nNew = whereRangeAdjust(pUpper, nNew); + + /* TUNING: If there is both an upper and lower limit, assume the range is + ** reduced by an additional 75%. This means that, by default, an open-ended + ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the + ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to + ** match 1/64 of the index. */ + if( pLower && pUpper ) nNew -= 20; + + nOut -= (pLower!=0) + (pUpper!=0); + if( nNew<10 ) nNew = 10; + if( nNewnOut = (LogEst)nOut; + return rc; +} + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** Estimate the number of rows that will be returned based on +** an equality constraint x=VALUE and where that VALUE occurs in +** the histogram data. This only works when x is the left-most +** column of an index and sqlite_stat3 histogram data is available +** for that index. When pExpr==NULL that means the constraint is +** "x IS NULL" instead of "x=VALUE". +** +** Write the estimated row count into *pnRow and return SQLITE_OK. +** If unable to make an estimate, leave *pnRow unchanged and return +** non-zero. +** +** This routine can fail if it is unable to load a collating sequence +** required for string comparison, or if unable to allocate memory +** for a UTF conversion required for comparison. The error is stored +** in the pParse structure. +*/ +static int whereEqualScanEst( + Parse *pParse, /* Parsing & code generating context */ + WhereLoopBuilder *pBuilder, + Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ + tRowcnt *pnRow /* Write the revised row estimate here */ +){ + Index *p = pBuilder->pNew->u.btree.pIndex; + int nEq = pBuilder->pNew->u.btree.nEq; + UnpackedRecord *pRec = pBuilder->pRec; + u8 aff; /* Column affinity */ + int rc; /* Subfunction return code */ + tRowcnt a[2]; /* Statistics */ + int bOk; + + assert( nEq>=1 ); + assert( nEq<=(p->nKeyCol+1) ); + assert( p->aSample!=0 ); + assert( p->nSample>0 ); + assert( pBuilder->nRecValidnRecValid<(nEq-1) ){ + return SQLITE_NOTFOUND; + } + + /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue() + ** below would return the same value. */ + if( nEq>p->nKeyCol ){ + *pnRow = 1; + return SQLITE_OK; + } + + aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity; + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); + pBuilder->pRec = pRec; + if( rc!=SQLITE_OK ) return rc; + if( bOk==0 ) return SQLITE_NOTFOUND; + pBuilder->nRecValid = nEq; + + whereKeyStats(pParse, p, pRec, 0, a); + WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1])); + *pnRow = a[1]; + + return rc; +} +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +/* +** Estimate the number of rows that will be returned based on +** an IN constraint where the right-hand side of the IN operator +** is a list of values. Example: +** +** WHERE x IN (1,2,3,4) +** +** Write the estimated row count into *pnRow and return SQLITE_OK. +** If unable to make an estimate, leave *pnRow unchanged and return +** non-zero. +** +** This routine can fail if it is unable to load a collating sequence +** required for string comparison, or if unable to allocate memory +** for a UTF conversion required for comparison. The error is stored +** in the pParse structure. +*/ +static int whereInScanEst( + Parse *pParse, /* Parsing & code generating context */ + WhereLoopBuilder *pBuilder, + ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ + tRowcnt *pnRow /* Write the revised row estimate here */ +){ + Index *p = pBuilder->pNew->u.btree.pIndex; + i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); + int nRecValid = pBuilder->nRecValid; + int rc = SQLITE_OK; /* Subfunction return code */ + tRowcnt nEst; /* Number of rows for a single term */ + tRowcnt nRowEst = 0; /* New estimate of the number of rows */ + int i; /* Loop counter */ + + assert( p->aSample!=0 ); + for(i=0; rc==SQLITE_OK && inExpr; i++){ + nEst = nRow0; + rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); + nRowEst += nEst; + pBuilder->nRecValid = nRecValid; + } + + if( rc==SQLITE_OK ){ + if( nRowEst > nRow0 ) nRowEst = nRow0; + *pnRow = nRowEst; + WHERETRACE(0x10,("IN row estimate: est=%g\n", nRowEst)); + } + assert( pBuilder->nRecValid==nRecValid ); + return rc; +} +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ + /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON @@ -119806,43 +112345,20 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus( ** but joins might run a little slower. The trick is to disable as much ** as we can without disabling too much. If we disabled in (1), we'd get ** the wrong answer. See ticket #813. -** -** If all the children of a term are disabled, then that term is also -** automatically disabled. In this way, terms get disabled if derived -** virtual terms are tested first. For example: -** -** x GLOB 'abc*' AND x>='abc' AND x<'acd' -** \___________/ \______/ \_____/ -** parent child1 child2 -** -** Only the parent term was in the original WHERE clause. The child1 -** and child2 terms were added by the LIKE optimization. If both of -** the virtual child terms are valid, then testing of the parent can be -** skipped. -** -** Usually the parent term is marked as TERM_CODED. But if the parent -** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. -** The TERM_LIKECOND marking indicates that the term should be coded inside -** a conditional such that is only evaluated on the second pass of a -** LIKE-optimization loop, when scanning BLOBs instead of strings. */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ - int nLoop = 0; - while( pTerm + if( pTerm && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ - if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ - pTerm->wtFlags |= TERM_LIKECOND; - }else{ - pTerm->wtFlags |= TERM_CODED; + pTerm->wtFlags |= TERM_CODED; + if( pTerm->iParent>=0 ){ + WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent]; + if( (--pOther->nChild)==0 ){ + disableTerm(pLevel, pOther); + } } - if( pTerm->iParent<0 ) break; - pTerm = &pTerm->pWC->a[pTerm->iParent]; - pTerm->nChild--; - if( pTerm->nChild!=0 ) break; - nLoop++; } } @@ -119850,9 +112366,9 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ ** Code an OP_Affinity opcode to apply the column affinity string zAff ** to the n registers starting at base. ** -** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the +** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the ** beginning and end of zAff are ignored. If all entries in zAff are -** SQLITE_AFF_BLOB, then no code gets generated. +** SQLITE_AFF_NONE, then no code gets generated. ** ** This routine makes its own copy of zAff so that the caller is free ** to modify zAff after this routine returns. @@ -119865,15 +112381,15 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ } assert( v!=0 ); - /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning + /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning ** and end of the affinity string. */ - while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){ + while( n>0 && zAff[0]==SQLITE_AFF_NONE ){ n--; base++; zAff++; } - while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){ + while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){ n--; } @@ -119910,7 +112426,7 @@ static int codeEqualityTerm( int iReg; /* Register holding results */ assert( iTarget>0 ); - if( pX->op==TK_EQ || pX->op==TK_IS ){ + if( pX->op==TK_EQ ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; @@ -119932,7 +112448,7 @@ static int codeEqualityTerm( } assert( pX->op==TK_IN ); iReg = iTarget; - eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0); + eType = sqlite3FindInIndex(pParse, pX, 0); if( eType==IN_INDEX_INDEX_DESC ){ testcase( bRev ); bRev = !bRev; @@ -120003,17 +112519,17 @@ static int codeEqualityTerm( ** Before returning, *pzAff is set to point to a buffer containing a ** copy of the column affinity string of the index allocated using ** sqlite3DbMalloc(). Except, entries in the copy of the string associated -** with equality constraints that use BLOB or NONE affinity are set to -** SQLITE_AFF_BLOB. This is to deal with SQL such as the following: +** with equality constraints that use NONE affinity are set to +** SQLITE_AFF_NONE. This is to deal with SQL such as the following: ** ** CREATE TABLE t1(a TEXT PRIMARY KEY, b); ** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b; ** ** In the example above, the index on t1(a) has TEXT affinity. But since -** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity, +** the right hand side of the equality constraint (t2.b) has NONE affinity, ** no conversion should be attempted before using a t2.b value as part of ** a key to search the index. Hence the first byte in the returned affinity -** string in this example would be set to SQLITE_AFF_BLOB. +** string in this example would be set to SQLITE_AFF_NONE. */ static int codeAllEqualityTerms( Parse *pParse, /* Parsing context */ @@ -120037,7 +112553,7 @@ static int codeAllEqualityTerms( pLoop = pLevel->pWLoop; assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); nEq = pLoop->u.btree.nEq; - nSkip = pLoop->nSkip; + nSkip = pLoop->u.btree.nSkip; pIdx = pLoop->u.btree.pIndex; assert( pIdx!=0 ); @@ -120047,7 +112563,7 @@ static int codeAllEqualityTerms( nReg = pLoop->u.btree.nEq + nExtraReg; pParse->nMem += nReg; - zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); + zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx)); if( !zAff ){ pParse->db->mallocFailed = 1; } @@ -120066,8 +112582,8 @@ static int codeAllEqualityTerms( sqlite3VdbeJumpHere(v, j); for(j=0; jaiColumn[j]==XN_EXPR ); - VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); + assert( pIdx->aiColumn[j]>=0 ); + VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName)); } } @@ -120095,16 +112611,16 @@ static int codeAllEqualityTerms( testcase( pTerm->eOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ Expr *pRight = pTerm->pExpr->pRight; - if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ + if( sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } if( zAff ){ - if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){ - zAff[j] = SQLITE_AFF_BLOB; + if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){ + zAff[j] = SQLITE_AFF_NONE; } if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){ - zAff[j] = SQLITE_AFF_BLOB; + zAff[j] = SQLITE_AFF_NONE; } } } @@ -120113,197 +112629,182 @@ static int codeAllEqualityTerms( return regBase; } -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS +#ifndef SQLITE_OMIT_EXPLAIN /* -** If the most recently coded instruction is a constant range contraint -** that originated from the LIKE optimization, then change the P3 to be -** pLoop->iLikeRepCntr and set P5. +** This routine is a helper for explainIndexRange() below ** -** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range -** expression: "x>='ABC' AND x<'abd'". But this requires that the range -** scan loop run twice, once for strings and a second time for BLOBs. -** The OP_String opcodes on the second pass convert the upper and lower -** bound string contants to blobs. This routine makes the necessary changes -** to the OP_String opcodes for that to happen. -** -** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then -** only the one pass through the string space is required, so this routine -** becomes a no-op. +** pStr holds the text of an expression that we are building up one term +** at a time. This routine adds a new term to the end of the expression. +** Terms are separated by AND so add the "AND" text for second and subsequent +** terms only. */ -static void whereLikeOptimizationStringFixup( - Vdbe *v, /* prepared statement under construction */ - WhereLevel *pLevel, /* The loop that contains the LIKE operator */ - WhereTerm *pTerm /* The upper or lower bound just coded */ +static void explainAppendTerm( + StrAccum *pStr, /* The text expression being built */ + int iTerm, /* Index of this term. First is zero */ + const char *zColumn, /* Name of the column */ + const char *zOp /* Name of the operator */ ){ - if( pTerm->wtFlags & TERM_LIKEOPT ){ - VdbeOp *pOp; - assert( pLevel->iLikeRepCntr>0 ); - pOp = sqlite3VdbeGetOp(v, -1); - assert( pOp!=0 ); - assert( pOp->opcode==OP_String8 - || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); - pOp->p3 = pLevel->iLikeRepCntr; - pOp->p5 = 1; - } -} -#else -# define whereLikeOptimizationStringFixup(A,B,C) -#endif - -#ifdef SQLITE_ENABLE_CURSOR_HINTS -/* -** Information is passed from codeCursorHint() down to individual nodes of -** the expression tree (by sqlite3WalkExpr()) using an instance of this -** structure. -*/ -struct CCurHint { - int iTabCur; /* Cursor for the main table */ - int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */ - Index *pIdx; /* The index used to access the table */ -}; - -/* -** This function is called for every node of an expression that is a candidate -** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference -** the table CCurHint.iTabCur, verify that the same column can be -** accessed through the index. If it cannot, then set pWalker->eCode to 1. -*/ -static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ - struct CCurHint *pHint = pWalker->u.pCCurHint; - assert( pHint->pIdx!=0 ); - if( pExpr->op==TK_COLUMN - && pExpr->iTable==pHint->iTabCur - && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0 - ){ - pWalker->eCode = 1; - } - return WRC_Continue; -} - - -/* -** This function is called on every node of an expression tree used as an -** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN -** that accesses any table other than the one identified by -** CCurHint.iTabCur, then do the following: -** -** 1) allocate a register and code an OP_Column instruction to read -** the specified column into the new register, and -** -** 2) transform the expression node to a TK_REGISTER node that reads -** from the newly populated register. -** -** Also, if the node is a TK_COLUMN that does access the table idenified -** by pCCurHint.iTabCur, and an index is being used (which we will -** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into -** an access of the index rather than the original table. -*/ -static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ - int rc = WRC_Continue; - struct CCurHint *pHint = pWalker->u.pCCurHint; - if( pExpr->op==TK_COLUMN ){ - if( pExpr->iTable!=pHint->iTabCur ){ - Vdbe *v = pWalker->pParse->pVdbe; - int reg = ++pWalker->pParse->nMem; /* Register for column value */ - sqlite3ExprCodeGetColumnOfTable( - v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg - ); - pExpr->op = TK_REGISTER; - pExpr->iTable = reg; - }else if( pHint->pIdx!=0 ){ - pExpr->iTable = pHint->iIdxCur; - pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); - assert( pExpr->iColumn>=0 ); - } - }else if( pExpr->op==TK_AGG_FUNCTION ){ - /* An aggregate function in the WHERE clause of a query means this must - ** be a correlated sub-query, and expression pExpr is an aggregate from - ** the parent context. Do not walk the function arguments in this case. - ** - ** todo: It should be possible to replace this node with a TK_REGISTER - ** expression, as the result of the expression must be stored in a - ** register at this point. The same holds for TK_AGG_COLUMN nodes. */ - rc = WRC_Prune; - } - return rc; + if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); + sqlite3StrAccumAppendAll(pStr, zColumn); + sqlite3StrAccumAppend(pStr, zOp, 1); + sqlite3StrAccumAppend(pStr, "?", 1); } /* -** Insert an OP_CursorHint instruction if it is appropriate to do so. +** Argument pLevel describes a strategy for scanning table pTab. This +** function returns a pointer to a string buffer containing a description +** of the subset of table rows scanned by the strategy in the form of an +** SQL expression. Or, if all rows are scanned, NULL is returned. +** +** For example, if the query: +** +** SELECT * FROM t1 WHERE a=1 AND b>2; +** +** is run and there is an index on (a, b), then this function returns a +** string similar to: +** +** "a=? AND b>?" +** +** The returned pointer points to memory obtained from sqlite3DbMalloc(). +** It is the responsibility of the caller to free the buffer when it is +** no longer required. */ -static void codeCursorHint( - WhereInfo *pWInfo, /* The where clause */ - WhereLevel *pLevel, /* Which loop to provide hints for */ - WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */ -){ - Parse *pParse = pWInfo->pParse; - sqlite3 *db = pParse->db; - Vdbe *v = pParse->pVdbe; - Expr *pExpr = 0; - WhereLoop *pLoop = pLevel->pWLoop; - int iCur; - WhereClause *pWC; - WhereTerm *pTerm; +static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){ + Index *pIndex = pLoop->u.btree.pIndex; + u16 nEq = pLoop->u.btree.nEq; + u16 nSkip = pLoop->u.btree.nSkip; int i, j; - struct CCurHint sHint; - Walker sWalker; + Column *aCol = pTab->aCol; + i16 *aiColumn = pIndex->aiColumn; + StrAccum txt; - if( OptimizationDisabled(db, SQLITE_CursorHints) ) return; - iCur = pLevel->iTabCur; - assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor ); - sHint.iTabCur = iCur; - sHint.iIdxCur = pLevel->iIdxCur; - sHint.pIdx = pLoop->u.btree.pIndex; - memset(&sWalker, 0, sizeof(sWalker)); - sWalker.pParse = pParse; - sWalker.u.pCCurHint = &sHint; - pWC = &pWInfo->sWC; - for(i=0; inTerm; i++){ - pTerm = &pWC->a[i]; - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( pTerm->prereqAll & pLevel->notReady ) continue; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; - - /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize - ** the cursor. These terms are not needed as hints for a pure range - ** scan (that has no == terms) so omit them. */ - if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){ - for(j=0; jnLTerm && pLoop->aLTerm[j]!=pTerm; j++){} - if( jnLTerm ) continue; - } - - /* No subqueries or non-deterministic functions allowed */ - if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue; - - /* For an index scan, make sure referenced columns are actually in - ** the index. */ - if( sHint.pIdx!=0 ){ - sWalker.eCode = 0; - sWalker.xExprCallback = codeCursorHintCheckExpr; - sqlite3WalkExpr(&sWalker, pTerm->pExpr); - if( sWalker.eCode ) continue; - } - - /* If we survive all prior tests, that means this term is worth hinting */ - pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); + if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){ + return 0; } - if( pExpr!=0 ){ - sWalker.xExprCallback = codeCursorHintFixExpr; - sqlite3WalkExpr(&sWalker, pExpr); - sqlite3VdbeAddOp4(v, OP_CursorHint, - (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, - (const char*)pExpr, P4_EXPR); + sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH); + txt.db = db; + sqlite3StrAccumAppend(&txt, " (", 2); + for(i=0; inKeyCol ) ? "rowid" : aCol[aiColumn[i]].zName; + if( i>=nSkip ){ + explainAppendTerm(&txt, i, z, "="); + }else{ + if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5); + sqlite3StrAccumAppend(&txt, "ANY(", 4); + sqlite3StrAccumAppendAll(&txt, z); + sqlite3StrAccumAppend(&txt, ")", 1); + } + } + + j = i; + if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ + char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName; + explainAppendTerm(&txt, i++, z, ">"); + } + if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ + char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName; + explainAppendTerm(&txt, i, z, "<"); + } + sqlite3StrAccumAppend(&txt, ")", 1); + return sqlite3StrAccumFinish(&txt); +} + +/* +** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN +** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single +** record is added to the output to describe the table scan strategy in +** pLevel. +*/ +static void explainOneScan( + Parse *pParse, /* Parse context */ + SrcList *pTabList, /* Table list this loop refers to */ + WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ + int iLevel, /* Value for "level" column of output */ + int iFrom, /* Value for "from" column of output */ + u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ +){ +#ifndef SQLITE_DEBUG + if( pParse->explain==2 ) +#endif + { + struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zMsg; /* Text to add to EQP output */ + int iId = pParse->iSelectId; /* Select id (left-most output column) */ + int isSearch; /* True for a SEARCH. False for SCAN. */ + WhereLoop *pLoop; /* The controlling WhereLoop object */ + u32 flags; /* Flags that describe this loop */ + + pLoop = pLevel->pWLoop; + flags = pLoop->wsFlags; + if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return; + + isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 + || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) + || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); + + zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN"); + if( pItem->pSelect ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId); + }else{ + zMsg = sqlite3MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName); + } + + if( pItem->zAlias ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); + } + if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 + && ALWAYS(pLoop->u.btree.pIndex!=0) + ){ + const char *zFmt; + Index *pIdx = pLoop->u.btree.pIndex; + char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); + assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); + if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){ + zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s"; + }else if( flags & WHERE_AUTO_INDEX ){ + zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s"; + }else if( flags & WHERE_IDX_ONLY ){ + zFmt = "%s USING COVERING INDEX %s%s"; + }else{ + zFmt = "%s USING INDEX %s%s"; + } + zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere); + sqlite3DbFree(db, zWhere); + }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg); + + if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg); + }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid?)", zMsg); + }else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s (rowidu.vtab.idxNum, pLoop->u.vtab.idxStr); + } +#endif + zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg); + sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC); } } #else -# define codeCursorHint(A,B,C) /* No-op */ -#endif /* SQLITE_ENABLE_CURSOR_HINTS */ +# define explainOneScan(u,v,w,x,y,z) +#endif /* SQLITE_OMIT_EXPLAIN */ + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ -SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( +static Bitmask codeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ Bitmask notReady /* Which tables are currently available */ @@ -120334,7 +112835,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pLoop = pLevel->pWLoop; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; - pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); + pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur); bRev = (pWInfo->revMask>>iLevel)&1; omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0; @@ -120357,14 +112858,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ - if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ + if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } /* Special case of a FROM clause subquery implemented as a co-routine */ - if( pTabItem->fg.viaCoroutine ){ + if( pTabItem->viaCoroutine ){ int regYield = pTabItem->regReturn; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); @@ -120408,8 +112909,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( disableTerm(pLevel, pLoop->aLTerm[j]); } } + pLevel->op = OP_VNext; pLevel->p1 = iCur; - pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite3ExprCachePop(pParse); @@ -120462,7 +112963,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pStart = pEnd; pEnd = pTerm; } - codeCursorHint(pWInfo, pLevel, pEnd); if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ @@ -120599,7 +113099,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; - assert( nEq>=pLoop->nSkip ); + assert( nEq>=pLoop->u.btree.nSkip ); /* If this loop satisfies a sort order (pOrderBy) request that ** was passed to this function to implement a "SELECT min(x) ..." @@ -120616,7 +113116,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( && pWInfo->nOBSat>0 && (pIdx->nKeyCol>nEq) ){ - assert( pLoop->nSkip==0 ); + assert( pLoop->u.btree.nSkip==0 ); bSeekPastNull = 1; nExtraReg = 1; } @@ -120628,27 +113128,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; nExtraReg = 1; - /* Like optimization range constraints always occur in pairs */ - assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || - (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ - assert( pRangeStart!=0 ); /* LIKE opt constraints */ - assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ - pLevel->iLikeRepCntr = ++pParse->nMem; - testcase( bRev ); - testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); - sqlite3VdbeAddOp2(v, OP_Integer, - bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC), - pLevel->iLikeRepCntr); - VdbeComment((v, "LIKE loop counter")); - pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); - } -#endif if( pRangeStart==0 && (j = pIdx->aiColumn[nEq])>=0 && pIdx->pTable->aCol[j].notNull==0 @@ -120658,6 +113141,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); + /* Generate code to evaluate all constraint terms using == or IN + ** and store the values of those terms in an array of registers + ** starting at regBase. + */ + regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); + assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); + if( zStartAff ) cEndAff = zStartAff[nEq]; + addrNxt = pLevel->addrNxt; + /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). @@ -120669,16 +113161,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( SWAP(u8, bSeekPastNull, bStopAtNull); } - /* Generate code to evaluate all constraint terms using == or IN - ** and store the values of those terms in an array of registers - ** starting at regBase. - */ - codeCursorHint(pWInfo, pLevel, pRangeEnd); - regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); - assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); - if( zStartAff ) cEndAff = zStartAff[nEq]; - addrNxt = pLevel->addrNxt; - testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); @@ -120692,7 +113174,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; sqlite3ExprCode(pParse, pRight, regBase+nEq); - whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -120700,14 +113181,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverage(v); } if( zStartAff ){ - if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_BLOB){ + if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){ /* Since the comparison is to be performed with no conversions ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE_AFF_BLOB. */ - zStartAff[nEq] = SQLITE_AFF_BLOB; + ** SQLITE_AFF_NONE. */ + zStartAff[nEq] = SQLITE_AFF_NONE; } if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){ - zStartAff[nEq] = SQLITE_AFF_BLOB; + zStartAff[nEq] = SQLITE_AFF_NONE; } } nConstraint++; @@ -120738,14 +113219,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); - whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } - if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_BLOB + if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff) ){ codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff); @@ -120781,12 +113261,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); - if( pWInfo->eOnePass!=ONEPASS_OFF ){ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); - VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ - } + sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ }else if( iCur!=iIdxCur ){ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); @@ -120858,7 +113333,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** B: ** ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then - ** use an ephemeral index instead of a RowSet to record the primary + ** use an ephermeral index instead of a RowSet to record the primary ** keys of the rows we have already seen. ** */ @@ -120874,7 +113349,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ - u16 wctrlFlags; /* Flags for sub-WHERE clause */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ Table *pTab = pTabItem->pTab; @@ -120909,7 +113383,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } /* Initialize the rowset register to contain NULL. An SQL NULL is - ** equivalent to an empty rowset. Or, create an ephemeral index + ** equivalent to an empty rowset. Or, create an ephermeral index ** capable of holding primary keys in the case of a WITHOUT ROWID. ** ** Also initialize regReturn to contain the address of the instruction @@ -120954,14 +113428,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; - if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); + if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue; + if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ - pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0); + pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); } } @@ -120969,32 +113444,26 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** eliminating duplicates from other WHERE clauses, the action for each ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ - wctrlFlags = WHERE_OMIT_OPEN_CLOSE - | WHERE_FORCE_TABLE - | WHERE_ONETABLE_ONLY - | WHERE_NO_AUTOINDEX; for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ - int jmp1 = 0; /* Address of jump operation */ + int j1 = 0; /* Address of jump operation */ if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ - WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, - wctrlFlags, iCovCur); + WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY | + WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur); assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; - int addrExplain = sqlite3WhereExplainOneScan( + explainOneScan( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); - sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); - /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same @@ -121005,8 +113474,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); if( HasRowid(pTab) ){ r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); - jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, - r,iSet); + j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet); VdbeCoverage(v); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); @@ -121017,7 +113485,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( r = sqlite3GetTempRange(pParse, nPk); for(iPk=0; iPkaiColumn[iPk]; - sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk); + sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0); } /* Check if the temp table already contains this key. If so, @@ -121032,7 +113500,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** need to insert the key into the temp table, as it will never ** be tested for. */ if( iSet ){ - jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); + j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); VdbeCoverage(v); } if( iSet>=0 ){ @@ -121051,7 +113519,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Jump here (skipping the main loop body subroutine) if the ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */ - if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1); + if( j1 ) sqlite3VdbeJumpHere(v, j1); /* The pSubWInfo->untestedTerms flag means that this OR term ** contained one or more AND term from a notReady table. The @@ -121080,7 +113548,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ){ assert( pSubWInfo->a[0].iIdxCur==iCovCur ); pCov = pSubLoop->u.btree.pIndex; - wctrlFlags |= WHERE_REOPEN_IDX; }else{ pCov = 0; } @@ -121097,7 +113564,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3ExprDelete(db, pAndExpr); } sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeGoto(v, pLevel->addrBrk); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab); @@ -121112,12 +113579,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( static const u8 aStep[] = { OP_Next, OP_Prev }; static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); - if( pTabItem->fg.isRecursive ){ + if( pTabItem->isRecursive ){ /* Tables marked isRecursive have only a single row that is stored in ** a pseudo-cursor. No need to Rewind or Next such cursors. */ pLevel->op = OP_Noop; }else{ - codeCursorHint(pWInfo, pLevel, 0); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); @@ -121127,16 +113593,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } } -#ifdef SQLITE_ENABLE_STMT_SCANSTATUS - pLevel->addrVisit = sqlite3VdbeCurrentAddr(v); -#endif - /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; - int skipLikeAddr = 0; testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; @@ -121151,17 +113612,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } - if( pTerm->wtFlags & TERM_LIKECOND ){ -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - continue; -#else - assert( pLevel->iLikeRepCntr>0 ); - skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr); - VdbeCoverage(v); -#endif - } sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); - if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); pTerm->wtFlags |= TERM_CODED; } @@ -121177,19 +113628,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Expr *pE, *pEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; - if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; + if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; if( pTerm->leftCursor!=iCur ) continue; if( pLevel->iLeftJoin ) continue; pE = pTerm->pExpr; assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); - pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady, - WO_EQ|WO_IN|WO_IS, 0); + pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; testcase( pAlt->eOperator & WO_EQ ); - testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); VdbeModuleComment((v, "begin transitive constraint")); pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); @@ -121226,3010 +113674,21 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( return pLevel->notReady; } -/************** End of wherecode.c *******************************************/ -/************** Begin file whereexpr.c ***************************************/ +#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN) /* -** 2015-06-08 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. -** -** This file was originally part of where.c but was split out to improve -** readability and editabiliity. This file contains utility routines for -** analyzing Expr objects in the WHERE clause. +** Generate "Explanation" text for a WhereTerm. */ -/* #include "sqliteInt.h" */ -/* #include "whereInt.h" */ - -/* Forward declarations */ -static void exprAnalyze(SrcList*, WhereClause*, int); - -/* -** Deallocate all memory associated with a WhereOrInfo object. -*/ -static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){ - sqlite3WhereClauseClear(&p->wc); - sqlite3DbFree(db, p); +static void whereExplainTerm(Vdbe *v, WhereTerm *pTerm){ + char zType[4]; + memcpy(zType, "...", 4); + if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; + if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; + sqlite3ExplainPrintf(v, "%s ", zType); + sqlite3ExplainExpr(v, pTerm->pExpr); } +#endif /* WHERETRACE_ENABLED && SQLITE_ENABLE_TREE_EXPLAIN */ -/* -** Deallocate all memory associated with a WhereAndInfo object. -*/ -static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){ - sqlite3WhereClauseClear(&p->wc); - sqlite3DbFree(db, p); -} - -/* -** Add a single new WhereTerm entry to the WhereClause object pWC. -** The new WhereTerm object is constructed from Expr p and with wtFlags. -** The index in pWC->a[] of the new WhereTerm is returned on success. -** 0 is returned if the new WhereTerm could not be added due to a memory -** allocation error. The memory allocation failure will be recorded in -** the db->mallocFailed flag so that higher-level functions can detect it. -** -** This routine will increase the size of the pWC->a[] array as necessary. -** -** If the wtFlags argument includes TERM_DYNAMIC, then responsibility -** for freeing the expression p is assumed by the WhereClause object pWC. -** This is true even if this routine fails to allocate a new WhereTerm. -** -** WARNING: This routine might reallocate the space used to store -** WhereTerms. All pointers to WhereTerms should be invalidated after -** calling this routine. Such pointers may be reinitialized by referencing -** the pWC->a[] array. -*/ -static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ - WhereTerm *pTerm; - int idx; - testcase( wtFlags & TERM_VIRTUAL ); - if( pWC->nTerm>=pWC->nSlot ){ - WhereTerm *pOld = pWC->a; - sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); - if( pWC->a==0 ){ - if( wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, p); - } - pWC->a = pOld; - return 0; - } - memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - if( pOld!=pWC->aStatic ){ - sqlite3DbFree(db, pOld); - } - pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); - memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); - } - pTerm = &pWC->a[idx = pWC->nTerm++]; - if( p && ExprHasProperty(p, EP_Unlikely) ){ - pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; - }else{ - pTerm->truthProb = 1; - } - pTerm->pExpr = sqlite3ExprSkipCollate(p); - pTerm->wtFlags = wtFlags; - pTerm->pWC = pWC; - pTerm->iParent = -1; - return idx; -} - -/* -** Return TRUE if the given operator is one of the operators that is -** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" -*/ -static int allowedOp(int op){ - assert( TK_GT>TK_EQ && TK_GTTK_EQ && TK_LTTK_EQ && TK_LE=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS; -} - -/* -** Commute a comparison operator. Expressions of the form "X op Y" -** are converted into "Y op X". -** -** If left/right precedence rules come into play when determining the -** collating sequence, then COLLATE operators are adjusted to ensure -** that the collating sequence does not change. For example: -** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on -** the left hand side of a comparison overrides any collation sequence -** attached to the right. For the same reason the EP_Collate flag -** is not commuted. -*/ -static void exprCommute(Parse *pParse, Expr *pExpr){ - u16 expRight = (pExpr->pRight->flags & EP_Collate); - u16 expLeft = (pExpr->pLeft->flags & EP_Collate); - assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); - if( expRight==expLeft ){ - /* Either X and Y both have COLLATE operator or neither do */ - if( expRight ){ - /* Both X and Y have COLLATE operators. Make sure X is always - ** used by clearing the EP_Collate flag from Y. */ - pExpr->pRight->flags &= ~EP_Collate; - }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ - /* Neither X nor Y have COLLATE operators, but X has a non-default - ** collating sequence. So add the EP_Collate marker on X to cause - ** it to be searched first. */ - pExpr->pLeft->flags |= EP_Collate; - } - } - SWAP(Expr*,pExpr->pRight,pExpr->pLeft); - if( pExpr->op>=TK_GT ){ - assert( TK_LT==TK_GT+2 ); - assert( TK_GE==TK_LE+2 ); - assert( TK_GT>TK_EQ ); - assert( TK_GTop>=TK_GT && pExpr->op<=TK_GE ); - pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; - } -} - -/* -** Translate from TK_xx operator to WO_xx bitmask. -*/ -static u16 operatorMask(int op){ - u16 c; - assert( allowedOp(op) ); - if( op==TK_IN ){ - c = WO_IN; - }else if( op==TK_ISNULL ){ - c = WO_ISNULL; - }else if( op==TK_IS ){ - c = WO_IS; - }else{ - assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); - c = (u16)(WO_EQ<<(op-TK_EQ)); - } - assert( op!=TK_ISNULL || c==WO_ISNULL ); - assert( op!=TK_IN || c==WO_IN ); - assert( op!=TK_EQ || c==WO_EQ ); - assert( op!=TK_LT || c==WO_LT ); - assert( op!=TK_LE || c==WO_LE ); - assert( op!=TK_GT || c==WO_GT ); - assert( op!=TK_GE || c==WO_GE ); - assert( op!=TK_IS || c==WO_IS ); - return c; -} - - -#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION -/* -** Check to see if the given expression is a LIKE or GLOB operator that -** can be optimized using inequality constraints. Return TRUE if it is -** so and false if not. -** -** In order for the operator to be optimizible, the RHS must be a string -** literal that does not begin with a wildcard. The LHS must be a column -** that may only be NULL, a string, or a BLOB, never a number. (This means -** that virtual tables cannot participate in the LIKE optimization.) The -** collating sequence for the column on the LHS must be appropriate for -** the operator. -*/ -static int isLikeOrGlob( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* Test this expression */ - Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */ - int *pisComplete, /* True if the only wildcard is % in the last character */ - int *pnoCase /* True if uppercase is equivalent to lowercase */ -){ - const char *z = 0; /* String on RHS of LIKE operator */ - Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ - ExprList *pList; /* List of operands to the LIKE operator */ - int c; /* One character in z[] */ - int cnt; /* Number of non-wildcard prefix characters */ - char wc[3]; /* Wildcard characters */ - sqlite3 *db = pParse->db; /* Database connection */ - sqlite3_value *pVal = 0; - int op; /* Opcode of pRight */ - - if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ - return 0; - } -#ifdef SQLITE_EBCDIC - if( *pnoCase ) return 0; -#endif - pList = pExpr->x.pList; - pLeft = pList->a[1].pExpr; - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ - ){ - /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must - ** be the name of an indexed column with TEXT affinity. */ - return 0; - } - assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ - - pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); - op = pRight->op; - if( op==TK_VARIABLE ){ - Vdbe *pReprepare = pParse->pReprepare; - int iCol = pRight->iColumn; - pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); - if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ - z = (char *)sqlite3_value_text(pVal); - } - sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); - assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); - }else if( op==TK_STRING ){ - z = pRight->u.zToken; - } - if( z ){ - cnt = 0; - while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ - cnt++; - } - if( cnt!=0 && 255!=(u8)z[cnt-1] ){ - Expr *pPrefix; - *pisComplete = c==wc[0] && z[cnt+1]==0; - pPrefix = sqlite3Expr(db, TK_STRING, z); - if( pPrefix ) pPrefix->u.zToken[cnt] = 0; - *ppPrefix = pPrefix; - if( op==TK_VARIABLE ){ - Vdbe *v = pParse->pVdbe; - sqlite3VdbeSetVarmask(v, pRight->iColumn); - if( *pisComplete && pRight->u.zToken[1] ){ - /* If the rhs of the LIKE expression is a variable, and the current - ** value of the variable means there is no need to invoke the LIKE - ** function, then no OP_Variable will be added to the program. - ** This causes problems for the sqlite3_bind_parameter_name() - ** API. To work around them, add a dummy OP_Variable here. - */ - int r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCodeTarget(pParse, pRight, r1); - sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0); - sqlite3ReleaseTempReg(pParse, r1); - } - } - }else{ - z = 0; - } - } - - sqlite3ValueFree(pVal); - return (z!=0); -} -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Check to see if the given expression is of the form -** -** column OP expr -** -** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a -** column of a virtual table. -** -** If it is then return TRUE. If not, return FALSE. -*/ -static int isMatchOfColumn( - Expr *pExpr, /* Test this expression */ - unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */ -){ - struct Op2 { - const char *zOp; - unsigned char eOp2; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - ExprList *pList; - Expr *pCol; /* Column reference */ - int i; - - if( pExpr->op!=TK_FUNCTION ){ - return 0; - } - pList = pExpr->x.pList; - if( pList==0 || pList->nExpr!=2 ){ - return 0; - } - pCol = pList->a[1].pExpr; - if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ - return 0; - } - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - return 1; - } - } - return 0; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** If the pBase expression originated in the ON or USING clause of -** a join, then transfer the appropriate markings over to derived. -*/ -static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ - if( pDerived ){ - pDerived->flags |= pBase->flags & EP_FromJoin; - pDerived->iRightJoinTable = pBase->iRightJoinTable; - } -} - -/* -** Mark term iChild as being a child of term iParent -*/ -static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ - pWC->a[iChild].iParent = iParent; - pWC->a[iChild].truthProb = pWC->a[iParent].truthProb; - pWC->a[iParent].nChild++; -} - -/* -** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not -** a conjunction, then return just pTerm when N==0. If N is exceeds -** the number of available subterms, return NULL. -*/ -static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){ - if( pTerm->eOperator!=WO_AND ){ - return N==0 ? pTerm : 0; - } - if( Nu.pAndInfo->wc.nTerm ){ - return &pTerm->u.pAndInfo->wc.a[N]; - } - return 0; -} - -/* -** Subterms pOne and pTwo are contained within WHERE clause pWC. The -** two subterms are in disjunction - they are OR-ed together. -** -** If these two terms are both of the form: "A op B" with the same -** A and B values but different operators and if the operators are -** compatible (if one is = and the other is <, for example) then -** add a new virtual AND term to pWC that is the combination of the -** two. -** -** Some examples: -** -** x x<=y -** x=y OR x=y --> x=y -** x<=y OR x x<=y -** -** The following is NOT generated: -** -** xy --> x!=y -*/ -static void whereCombineDisjuncts( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* The complete WHERE clause */ - WhereTerm *pOne, /* First disjunct */ - WhereTerm *pTwo /* Second disjunct */ -){ - u16 eOp = pOne->eOperator | pTwo->eOperator; - sqlite3 *db; /* Database connection (for malloc) */ - Expr *pNew; /* New virtual expression */ - int op; /* Operator for the combined expression */ - int idxNew; /* Index in pWC of the next virtual term */ - - if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; - if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; - if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp - && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; - assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); - assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); - if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; - if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return; - /* If we reach this point, it means the two subterms can be combined */ - if( (eOp & (eOp-1))!=0 ){ - if( eOp & (WO_LT|WO_LE) ){ - eOp = WO_LE; - }else{ - assert( eOp & (WO_GT|WO_GE) ); - eOp = WO_GE; - } - } - db = pWC->pWInfo->pParse->db; - pNew = sqlite3ExprDup(db, pOne->pExpr, 0); - if( pNew==0 ) return; - for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; - idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); - exprAnalyze(pSrc, pWC, idxNew); -} - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) -/* -** Analyze a term that consists of two or more OR-connected -** subterms. So in: -** -** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13) -** ^^^^^^^^^^^^^^^^^^^^ -** -** This routine analyzes terms such as the middle term in the above example. -** A WhereOrTerm object is computed and attached to the term under -** analysis, regardless of the outcome of the analysis. Hence: -** -** WhereTerm.wtFlags |= TERM_ORINFO -** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object -** -** The term being analyzed must have two or more of OR-connected subterms. -** A single subterm might be a set of AND-connected sub-subterms. -** Examples of terms under analysis: -** -** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5 -** (B) x=expr1 OR expr2=x OR x=expr3 -** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) -** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') -** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) -** (F) x>A OR (x=A AND y>=B) -** -** CASE 1: -** -** If all subterms are of the form T.C=expr for some single column of C and -** a single table T (as shown in example B above) then create a new virtual -** term that is an equivalent IN expression. In other words, if the term -** being analyzed is: -** -** x = expr1 OR expr2 = x OR x = expr3 -** -** then create a new virtual term like this: -** -** x IN (expr1,expr2,expr3) -** -** CASE 2: -** -** If there are exactly two disjuncts and one side has x>A and the other side -** has x=A (for the same x and A) then add a new virtual conjunct term to the -** WHERE clause of the form "x>=A". Example: -** -** x>A OR (x=A AND y>B) adds: x>=A -** -** The added conjunct can sometimes be helpful in query planning. -** -** CASE 3: -** -** If all subterms are indexable by a single table T, then set -** -** WhereTerm.eOperator = WO_OR -** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T -** -** A subterm is "indexable" if it is of the form -** "T.C " where C is any column of table T and -** is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN". -** A subterm is also indexable if it is an AND of two or more -** subsubterms at least one of which is indexable. Indexable AND -** subterms have their eOperator set to WO_AND and they have -** u.pAndInfo set to a dynamically allocated WhereAndTerm object. -** -** From another point of view, "indexable" means that the subterm could -** potentially be used with an index if an appropriate index exists. -** This analysis does not consider whether or not the index exists; that -** is decided elsewhere. This analysis only looks at whether subterms -** appropriate for indexing exist. -** -** All examples A through E above satisfy case 3. But if a term -** also satisfies case 1 (such as B) we know that the optimizer will -** always prefer case 1, so in that case we pretend that case 3 is not -** satisfied. -** -** It might be the case that multiple tables are indexable. For example, -** (E) above is indexable on tables P, Q, and R. -** -** Terms that satisfy case 3 are candidates for lookup by using -** separate indices to find rowids for each subterm and composing -** the union of all rowids using a RowSet object. This is similar -** to "bitmap indices" in other database engines. -** -** OTHERWISE: -** -** If none of cases 1, 2, or 3 apply, then leave the eOperator set to -** zero. This term is not useful for search. -*/ -static void exprAnalyzeOrTerm( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the complete WHERE clause */ - int idxTerm /* Index of the OR-term to be analyzed */ -){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ - Parse *pParse = pWInfo->pParse; /* Parser context */ - sqlite3 *db = pParse->db; /* Database connection */ - WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ - Expr *pExpr = pTerm->pExpr; /* The expression of the term */ - int i; /* Loop counters */ - WhereClause *pOrWc; /* Breakup of pTerm into subterms */ - WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ - WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ - Bitmask chngToIN; /* Tables that might satisfy case 1 */ - Bitmask indexable; /* Tables that are indexable, satisfying case 2 */ - - /* - ** Break the OR clause into its separate subterms. The subterms are - ** stored in a WhereClause structure containing within the WhereOrInfo - ** object that is attached to the original OR clause term. - */ - assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 ); - assert( pExpr->op==TK_OR ); - pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo)); - if( pOrInfo==0 ) return; - pTerm->wtFlags |= TERM_ORINFO; - pOrWc = &pOrInfo->wc; - sqlite3WhereClauseInit(pOrWc, pWInfo); - sqlite3WhereSplit(pOrWc, pExpr, TK_OR); - sqlite3WhereExprAnalyze(pSrc, pOrWc); - if( db->mallocFailed ) return; - assert( pOrWc->nTerm>=2 ); - - /* - ** Compute the set of tables that might satisfy cases 1 or 3. - */ - indexable = ~(Bitmask)0; - chngToIN = ~(Bitmask)0; - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ - if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ - WhereAndInfo *pAndInfo; - assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); - chngToIN = 0; - pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); - if( pAndInfo ){ - WhereClause *pAndWC; - WhereTerm *pAndTerm; - int j; - Bitmask b = 0; - pOrTerm->u.pAndInfo = pAndInfo; - pOrTerm->wtFlags |= TERM_ANDINFO; - pOrTerm->eOperator = WO_AND; - pAndWC = &pAndInfo->wc; - sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); - sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); - sqlite3WhereExprAnalyze(pSrc, pAndWC); - pAndWC->pOuter = pWC; - testcase( db->mallocFailed ); - if( !db->mallocFailed ){ - for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ - assert( pAndTerm->pExpr ); - if( allowedOp(pAndTerm->pExpr->op) ){ - b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); - } - } - } - indexable &= b; - } - }else if( pOrTerm->wtFlags & TERM_COPIED ){ - /* Skip this term for now. We revisit it when we process the - ** corresponding TERM_VIRTUAL term */ - }else{ - Bitmask b; - b = sqlite3WhereGetMask(&pWInfo->sMaskSet, pOrTerm->leftCursor); - if( pOrTerm->wtFlags & TERM_VIRTUAL ){ - WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; - b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pOther->leftCursor); - } - indexable &= b; - if( (pOrTerm->eOperator & WO_EQ)==0 ){ - chngToIN = 0; - }else{ - chngToIN &= b; - } - } - } - - /* - ** Record the set of tables that satisfy case 3. The set might be - ** empty. - */ - pOrInfo->indexable = indexable; - pTerm->eOperator = indexable==0 ? 0 : WO_OR; - - /* For a two-way OR, attempt to implementation case 2. - */ - if( indexable && pOrWc->nTerm==2 ){ - int iOne = 0; - WhereTerm *pOne; - while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){ - int iTwo = 0; - WhereTerm *pTwo; - while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){ - whereCombineDisjuncts(pSrc, pWC, pOne, pTwo); - } - } - } - - /* - ** chngToIN holds a set of tables that *might* satisfy case 1. But - ** we have to do some additional checking to see if case 1 really - ** is satisfied. - ** - ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means - ** that there is no possibility of transforming the OR clause into an - ** IN operator because one or more terms in the OR clause contain - ** something other than == on a column in the single table. The 1-bit - ** case means that every term of the OR clause is of the form - ** "table.column=expr" for some single table. The one bit that is set - ** will correspond to the common table. We still need to check to make - ** sure the same column is used on all terms. The 2-bit case is when - ** the all terms are of the form "table1.column=table2.column". It - ** might be possible to form an IN operator with either table1.column - ** or table2.column as the LHS if either is common to every term of - ** the OR clause. - ** - ** Note that terms of the form "table.column1=table.column2" (the - ** same table on both sizes of the ==) cannot be optimized. - */ - if( chngToIN ){ - int okToChngToIN = 0; /* True if the conversion to IN is valid */ - int iColumn = -1; /* Column index on lhs of IN operator */ - int iCursor = -1; /* Table cursor common to all terms */ - int j = 0; /* Loop counter */ - - /* Search for a table and column that appears on one side or the - ** other of the == operator in every subterm. That table and column - ** will be recorded in iCursor and iColumn. There might not be any - ** such table and column. Set okToChngToIN if an appropriate table - ** and column is found but leave okToChngToIN false if not found. - */ - for(j=0; j<2 && !okToChngToIN; j++){ - pOrTerm = pOrWc->a; - for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); - pOrTerm->wtFlags &= ~TERM_OR_OK; - if( pOrTerm->leftCursor==iCursor ){ - /* This is the 2-bit case and we are on the second iteration and - ** current term is from the first iteration. So skip this term. */ - assert( j==1 ); - continue; - } - if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet, - pOrTerm->leftCursor))==0 ){ - /* This term must be of the form t1.a==t2.b where t2 is in the - ** chngToIN set but t1 is not. This term will be either preceded - ** or follwed by an inverted copy (t2.b==t1.a). Skip this term - ** and use its inversion. */ - testcase( pOrTerm->wtFlags & TERM_COPIED ); - testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); - assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); - continue; - } - iColumn = pOrTerm->u.leftColumn; - iCursor = pOrTerm->leftCursor; - break; - } - if( i<0 ){ - /* No candidate table+column was found. This can only occur - ** on the second iteration */ - assert( j==1 ); - assert( IsPowerOfTwo(chngToIN) ); - assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) ); - break; - } - testcase( j==1 ); - - /* We have found a candidate table and column. Check to see if that - ** table and column is common to every term in the OR clause */ - okToChngToIN = 1; - for(; i>=0 && okToChngToIN; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); - if( pOrTerm->leftCursor!=iCursor ){ - pOrTerm->wtFlags &= ~TERM_OR_OK; - }else if( pOrTerm->u.leftColumn!=iColumn ){ - okToChngToIN = 0; - }else{ - int affLeft, affRight; - /* If the right-hand side is also a column, then the affinities - ** of both right and left sides must be such that no type - ** conversions are required on the right. (Ticket #2249) - */ - affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); - affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); - if( affRight!=0 && affRight!=affLeft ){ - okToChngToIN = 0; - }else{ - pOrTerm->wtFlags |= TERM_OR_OK; - } - } - } - } - - /* At this point, okToChngToIN is true if original pTerm satisfies - ** case 1. In that case, construct a new virtual term that is - ** pTerm converted into an IN operator. - */ - if( okToChngToIN ){ - Expr *pDup; /* A transient duplicate expression */ - ExprList *pList = 0; /* The RHS of the IN operator */ - Expr *pLeft = 0; /* The LHS of the IN operator */ - Expr *pNew; /* The complete IN operator */ - - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; - assert( pOrTerm->eOperator & WO_EQ ); - assert( pOrTerm->leftCursor==iCursor ); - assert( pOrTerm->u.leftColumn==iColumn ); - pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); - pLeft = pOrTerm->pExpr->pLeft; - } - assert( pLeft!=0 ); - pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); - if( pNew ){ - int idxNew; - transferJoinMarkings(pNew, pExpr); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - pNew->x.pList = pList; - idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - exprAnalyze(pSrc, pWC, idxNew); - pTerm = &pWC->a[idxTerm]; - markTermAsChild(pWC, idxNew, idxTerm); - }else{ - sqlite3ExprListDelete(db, pList); - } - pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ - } - } -} -#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ - -/* -** We already know that pExpr is a binary operator where both operands are -** column references. This routine checks to see if pExpr is an equivalence -** relation: -** 1. The SQLITE_Transitive optimization must be enabled -** 2. Must be either an == or an IS operator -** 3. Not originating in the ON clause of an OUTER JOIN -** 4. The affinities of A and B must be compatible -** 5a. Both operands use the same collating sequence OR -** 5b. The overall collating sequence is BINARY -** If this routine returns TRUE, that means that the RHS can be substituted -** for the LHS anyplace else in the WHERE clause where the LHS column occurs. -** This is an optimization. No harm comes from returning 0. But if 1 is -** returned when it should not be, then incorrect answers might result. -*/ -static int termIsEquivalence(Parse *pParse, Expr *pExpr){ - char aff1, aff2; - CollSeq *pColl; - const char *zColl1, *zColl2; - if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; - if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; - if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; - aff1 = sqlite3ExprAffinity(pExpr->pLeft); - aff2 = sqlite3ExprAffinity(pExpr->pRight); - if( aff1!=aff2 - && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2)) - ){ - return 0; - } - pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); - if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - /* Since pLeft and pRight are both a column references, their collating - ** sequence should always be defined. */ - zColl1 = ALWAYS(pColl) ? pColl->zName : 0; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); - zColl2 = ALWAYS(pColl) ? pColl->zName : 0; - return sqlite3StrICmp(zColl1, zColl2)==0; -} - -/* -** Recursively walk the expressions of a SELECT statement and generate -** a bitmask indicating which tables are used in that expression -** tree. -*/ -static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ - Bitmask mask = 0; - while( pS ){ - SrcList *pSrc = pS->pSrc; - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pEList); - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pGroupBy); - mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy); - mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere); - mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving); - if( ALWAYS(pSrc!=0) ){ - int i; - for(i=0; inSrc; i++){ - mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); - mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); - } - } - pS = pS->pPrior; - } - return mask; -} - -/* -** Expression pExpr is one operand of a comparison operator that might -** be useful for indexing. This routine checks to see if pExpr appears -** in any index. Return TRUE (1) if pExpr is an indexed term and return -** FALSE (0) if not. If TRUE is returned, also set *piCur to the cursor -** number of the table that is indexed and *piColumn to the column number -** of the column that is indexed, or -2 if an expression is being indexed. -** -** If pExpr is a TK_COLUMN column reference, then this routine always returns -** true even if that particular column is not indexed, because the column -** might be added to an automatic index later. -*/ -static int exprMightBeIndexed( - SrcList *pFrom, /* The FROM clause */ - Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ - Expr *pExpr, /* An operand of a comparison operator */ - int *piCur, /* Write the referenced table cursor number here */ - int *piColumn /* Write the referenced table column number here */ -){ - Index *pIdx; - int i; - int iCur; - if( pExpr->op==TK_COLUMN ){ - *piCur = pExpr->iTable; - *piColumn = pExpr->iColumn; - return 1; - } - if( mPrereq==0 ) return 0; /* No table references */ - if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */ - for(i=0; mPrereq>1; i++, mPrereq>>=1){} - iCur = pFrom->a[i].iCursor; - for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr==0 ) continue; - for(i=0; inKeyCol; i++){ - if( pIdx->aiColumn[i]!=(-2) ) continue; - if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ - *piCur = iCur; - *piColumn = -2; - return 1; - } - } - } - return 0; -} - -/* -** The input to this routine is an WhereTerm structure with only the -** "pExpr" field filled in. The job of this routine is to analyze the -** subexpression and populate all the other fields of the WhereTerm -** structure. -** -** If the expression is of the form " X" it gets commuted -** to the standard form of "X ". -** -** If the expression is of the form "X Y" where both X and Y are -** columns, then the original expression is unchanged and a new virtual -** term of the form "Y X" is added to the WHERE clause and -** analyzed separately. The original term is marked with TERM_COPIED -** and the new term is marked with TERM_DYNAMIC (because it's pExpr -** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it -** is a commuted copy of a prior term.) The original term has nChild=1 -** and the copy has idxParent set to the index of the original term. -*/ -static void exprAnalyze( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the WHERE clause */ - int idxTerm /* Index of the term to be analyzed */ -){ - WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ - WhereTerm *pTerm; /* The term to be analyzed */ - WhereMaskSet *pMaskSet; /* Set of table index masks */ - Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequesites of pExpr */ - Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ - Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ - int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ - int noCase = 0; /* uppercase equivalent to lowercase */ - int op; /* Top-level operator. pExpr->op */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - sqlite3 *db = pParse->db; /* Database connection */ - unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ - - if( db->mallocFailed ){ - return; - } - pTerm = &pWC->a[idxTerm]; - pMaskSet = &pWInfo->sMaskSet; - pExpr = pTerm->pExpr; - assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); - prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); - op = pExpr->op; - if( op==TK_IN ){ - assert( pExpr->pRight==0 ); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); - }else{ - pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); - } - }else if( op==TK_ISNULL ){ - pTerm->prereqRight = 0; - }else{ - pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); - } - prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr); - if( ExprHasProperty(pExpr, EP_FromJoin) ){ - Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); - prereqAll |= x; - extraRight = x-1; /* ON clause terms may not be used with an index - ** on left table of a LEFT JOIN. Ticket #3015 */ - } - pTerm->prereqAll = prereqAll; - pTerm->leftCursor = -1; - pTerm->iParent = -1; - pTerm->eOperator = 0; - if( allowedOp(op) ){ - int iCur, iColumn; - Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); - u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - if( exprMightBeIndexed(pSrc, prereqLeft, pLeft, &iCur, &iColumn) ){ - pTerm->leftCursor = iCur; - pTerm->u.leftColumn = iColumn; - pTerm->eOperator = operatorMask(op) & opMask; - } - if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; - if( pRight - && exprMightBeIndexed(pSrc, pTerm->prereqRight, pRight, &iCur, &iColumn) - ){ - WhereTerm *pNew; - Expr *pDup; - u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ - if( pTerm->leftCursor>=0 ){ - int idxNew; - pDup = sqlite3ExprDup(db, pExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - return; - } - idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); - if( idxNew==0 ) return; - pNew = &pWC->a[idxNew]; - markTermAsChild(pWC, idxNew, idxTerm); - if( op==TK_IS ) pNew->wtFlags |= TERM_IS; - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - - if( termIsEquivalence(pParse, pDup) ){ - pTerm->eOperator |= WO_EQUIV; - eExtraOp = WO_EQUIV; - } - }else{ - pDup = pExpr; - pNew = pTerm; - } - exprCommute(pParse, pDup); - pNew->leftCursor = iCur; - pNew->u.leftColumn = iColumn; - testcase( (prereqLeft | extraRight) != prereqLeft ); - pNew->prereqRight = prereqLeft | extraRight; - pNew->prereqAll = prereqAll; - pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; - } - } - -#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION - /* If a term is the BETWEEN operator, create two new virtual terms - ** that define the range that the BETWEEN implements. For example: - ** - ** a BETWEEN b AND c - ** - ** is converted into: - ** - ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c) - ** - ** The two new terms are added onto the end of the WhereClause object. - ** The new terms are "dynamic" and are children of the original BETWEEN - ** term. That means that if the BETWEEN term is coded, the children are - ** skipped. Or, if the children are satisfied by an index, the original - ** BETWEEN term is skipped. - */ - else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ - ExprList *pList = pExpr->x.pList; - int i; - static const u8 ops[] = {TK_GE, TK_LE}; - assert( pList!=0 ); - assert( pList->nExpr==2 ); - for(i=0; i<2; i++){ - Expr *pNewExpr; - int idxNew; - pNewExpr = sqlite3PExpr(pParse, ops[i], - sqlite3ExprDup(db, pExpr->pLeft, 0), - sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); - transferJoinMarkings(pNewExpr, pExpr); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - exprAnalyze(pSrc, pWC, idxNew); - pTerm = &pWC->a[idxTerm]; - markTermAsChild(pWC, idxNew, idxTerm); - } - } -#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) - /* Analyze a term that is composed of two or more subterms connected by - ** an OR operator. - */ - else if( pExpr->op==TK_OR ){ - assert( pWC->op==TK_AND ); - exprAnalyzeOrTerm(pSrc, pWC, idxTerm); - pTerm = &pWC->a[idxTerm]; - } -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - -#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION - /* Add constraints to reduce the search space on a LIKE or GLOB - ** operator. - ** - ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints - ** - ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%' - ** - ** The last character of the prefix "abc" is incremented to form the - ** termination condition "abd". If case is not significant (the default - ** for LIKE) then the lower-bound is made all uppercase and the upper- - ** bound is made all lowercase so that the bounds also work when comparing - ** BLOBs. - */ - if( pWC->op==TK_AND - && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) - ){ - Expr *pLeft; /* LHS of LIKE/GLOB operator */ - Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ - Expr *pNewExpr1; - Expr *pNewExpr2; - int idxNew1; - int idxNew2; - const char *zCollSeqName; /* Name of collating sequence */ - const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC; - - pLeft = pExpr->x.pList->a[1].pExpr; - pStr2 = sqlite3ExprDup(db, pStr1, 0); - - /* Convert the lower bound to upper-case and the upper bound to - ** lower-case (upper-case is less than lower-case in ASCII) so that - ** the range constraints also work for BLOBs - */ - if( noCase && !pParse->db->mallocFailed ){ - int i; - char c; - pTerm->wtFlags |= TERM_LIKE; - for(i=0; (c = pStr1->u.zToken[i])!=0; i++){ - pStr1->u.zToken[i] = sqlite3Toupper(c); - pStr2->u.zToken[i] = sqlite3Tolower(c); - } - } - - if( !db->mallocFailed ){ - u8 c, *pC; /* Last character before the first wildcard */ - pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; - c = *pC; - if( noCase ){ - /* The point is to increment the last character before the first - ** wildcard. But if we increment '@', that will push it into the - ** alphabetic range where case conversions will mess up the - ** inequality. To avoid this, make sure to also run the full - ** LIKE on all candidate expressions by clearing the isComplete flag - */ - if( c=='A'-1 ) isComplete = 0; - c = sqlite3UpperToLower[c]; - } - *pC = c + 1; - } - zCollSeqName = noCase ? "NOCASE" : "BINARY"; - pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, - sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), - pStr1, 0); - transferJoinMarkings(pNewExpr1, pExpr); - idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); - testcase( idxNew1==0 ); - exprAnalyze(pSrc, pWC, idxNew1); - pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr2 = sqlite3PExpr(pParse, TK_LT, - sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), - pStr2, 0); - transferJoinMarkings(pNewExpr2, pExpr); - idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); - testcase( idxNew2==0 ); - exprAnalyze(pSrc, pWC, idxNew2); - pTerm = &pWC->a[idxTerm]; - if( isComplete ){ - markTermAsChild(pWC, idxNew1, idxTerm); - markTermAsChild(pWC, idxNew2, idxTerm); - } - } -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Add a WO_MATCH auxiliary term to the constraint set if the - ** current expression is of the form: column MATCH expr. - ** This information is used by the xBestIndex methods of - ** virtual tables. The native query optimizer does not attempt - ** to do anything with MATCH functions. - */ - if( isMatchOfColumn(pExpr, &eOp2) ){ - int idxNew; - Expr *pRight, *pLeft; - WhereTerm *pNewTerm; - Bitmask prereqColumn, prereqExpr; - - pRight = pExpr->x.pList->a[0].pExpr; - pLeft = pExpr->x.pList->a[1].pExpr; - prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); - prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); - if( (prereqExpr & prereqColumn)==0 ){ - Expr *pNewExpr; - pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0), 0); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = prereqExpr; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_MATCH; - pNewTerm->eMatchOp = eOp2; - markTermAsChild(pWC, idxNew, idxTerm); - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - } -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - /* When sqlite_stat3 histogram data is available an operator of the - ** form "x IS NOT NULL" can sometimes be evaluated more efficiently - ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a - ** virtual term of that form. - ** - ** Note that the virtual term must be tagged with TERM_VNULL. - */ - if( pExpr->op==TK_NOTNULL - && pExpr->pLeft->op==TK_COLUMN - && pExpr->pLeft->iColumn>=0 - && OptimizationEnabled(db, SQLITE_Stat34) - ){ - Expr *pNewExpr; - Expr *pLeft = pExpr->pLeft; - int idxNew; - WhereTerm *pNewTerm; - - pNewExpr = sqlite3PExpr(pParse, TK_GT, - sqlite3ExprDup(db, pLeft, 0), - sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); - - idxNew = whereClauseInsert(pWC, pNewExpr, - TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); - if( idxNew ){ - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = 0; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_GT; - markTermAsChild(pWC, idxNew, idxTerm); - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - } -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ - - /* Prevent ON clause terms of a LEFT JOIN from being used to drive - ** an index for tables to the left of the join. - */ - pTerm->prereqRight |= extraRight; -} - -/*************************************************************************** -** Routines with file scope above. Interface to the rest of the where.c -** subsystem follows. -***************************************************************************/ - -/* -** This routine identifies subexpressions in the WHERE clause where -** each subexpression is separated by the AND operator or some other -** operator specified in the op parameter. The WhereClause structure -** is filled with pointers to subexpressions. For example: -** -** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) -** \________/ \_______________/ \________________/ -** slot[0] slot[1] slot[2] -** -** The original WHERE clause in pExpr is unaltered. All this routine -** does is make slot[] entries point to substructure within pExpr. -** -** In the previous sentence and in the diagram, "slot[]" refers to -** the WhereClause.a[] array. The slot[] array grows as needed to contain -** all terms of the WHERE clause. -*/ -SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - Expr *pE2 = sqlite3ExprSkipCollate(pExpr); - pWC->op = op; - if( pE2==0 ) return; - if( pE2->op!=op ){ - whereClauseInsert(pWC, pExpr, 0); - }else{ - sqlite3WhereSplit(pWC, pE2->pLeft, op); - sqlite3WhereSplit(pWC, pE2->pRight, op); - } -} - -/* -** Initialize a preallocated WhereClause structure. -*/ -SQLITE_PRIVATE void sqlite3WhereClauseInit( - WhereClause *pWC, /* The WhereClause to be initialized */ - WhereInfo *pWInfo /* The WHERE processing context */ -){ - pWC->pWInfo = pWInfo; - pWC->pOuter = 0; - pWC->nTerm = 0; - pWC->nSlot = ArraySize(pWC->aStatic); - pWC->a = pWC->aStatic; -} - -/* -** Deallocate a WhereClause structure. The WhereClause structure -** itself is not freed. This routine is the inverse of -** sqlite3WhereClauseInit(). -*/ -SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ - int i; - WhereTerm *a; - sqlite3 *db = pWC->pWInfo->pParse->db; - for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ - if( a->wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, a->pExpr); - } - if( a->wtFlags & TERM_ORINFO ){ - whereOrInfoDelete(db, a->u.pOrInfo); - }else if( a->wtFlags & TERM_ANDINFO ){ - whereAndInfoDelete(db, a->u.pAndInfo); - } - } - if( pWC->a!=pWC->aStatic ){ - sqlite3DbFree(db, pWC->a); - } -} - - -/* -** These routines walk (recursively) an expression tree and generate -** a bitmask indicating which tables are used in that expression -** tree. -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ - Bitmask mask = 0; - if( p==0 ) return 0; - if( p->op==TK_COLUMN ){ - mask = sqlite3WhereGetMask(pMaskSet, p->iTable); - return mask; - } - mask = sqlite3WhereExprUsage(pMaskSet, p->pRight); - mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); - if( ExprHasProperty(p, EP_xIsSelect) ){ - mask |= exprSelectUsage(pMaskSet, p->x.pSelect); - }else{ - mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); - } - return mask; -} -SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){ - int i; - Bitmask mask = 0; - if( pList ){ - for(i=0; inExpr; i++){ - mask |= sqlite3WhereExprUsage(pMaskSet, pList->a[i].pExpr); - } - } - return mask; -} - - -/* -** Call exprAnalyze on all terms in a WHERE clause. -** -** Note that exprAnalyze() might add new virtual terms onto the -** end of the WHERE clause. We do not want to analyze these new -** virtual terms, so start analyzing at the end and work forward -** so that the added virtual terms are never processed. -*/ -SQLITE_PRIVATE void sqlite3WhereExprAnalyze( - SrcList *pTabList, /* the FROM clause */ - WhereClause *pWC /* the WHERE clause to be analyzed */ -){ - int i; - for(i=pWC->nTerm-1; i>=0; i--){ - exprAnalyze(pTabList, pWC, i); - } -} - -/* -** For table-valued-functions, transform the function arguments into -** new WHERE clause terms. -** -** Each function argument translates into an equality constraint against -** a HIDDEN column in the table. -*/ -SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( - Parse *pParse, /* Parsing context */ - struct SrcList_item *pItem, /* The FROM clause term to process */ - WhereClause *pWC /* Xfer function arguments to here */ -){ - Table *pTab; - int j, k; - ExprList *pArgs; - Expr *pColRef; - Expr *pTerm; - if( pItem->fg.isTabFunc==0 ) return; - pTab = pItem->pTab; - assert( pTab!=0 ); - pArgs = pItem->u1.pFuncArg; - if( pArgs==0 ) return; - for(j=k=0; jnExpr; j++){ - while( knCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} - if( k>=pTab->nCol ){ - sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", - pTab->zName, j); - return; - } - pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); - if( pColRef==0 ) return; - pColRef->iTable = pItem->iCursor; - pColRef->iColumn = k++; - pColRef->pTab = pTab; - pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); - whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); - } -} - -/************** End of whereexpr.c *******************************************/ -/************** Begin file where.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. This module is responsible for -** generating the code that loops through a table looking for applicable -** rows. Indices are selected and used to speed the search when doing -** so is applicable. Because this module is responsible for selecting -** indices, you might also think of this module as the "query optimizer". -*/ -/* #include "sqliteInt.h" */ -/* #include "whereInt.h" */ - -/* Forward declaration of methods */ -static int whereLoopResize(sqlite3*, WhereLoop*, int); - -/* Test variable that can be set to enable WHERE tracing */ -#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) -/***/ int sqlite3WhereTrace = 0; -#endif - - -/* -** Return the estimated number of output rows from a WHERE clause -*/ -SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ - return sqlite3LogEstToInt(pWInfo->nRowOut); -} - -/* -** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this -** WHERE clause returns outputs for DISTINCT processing. -*/ -SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ - return pWInfo->eDistinct; -} - -/* -** Return TRUE if the WHERE clause returns rows in ORDER BY order. -** Return FALSE if the output needs to be sorted. -*/ -SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ - return pWInfo->nOBSat; -} - -/* -** Return the VDBE address or label to jump to in order to continue -** immediately with the next row of a WHERE clause. -*/ -SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ - assert( pWInfo->iContinue!=0 ); - return pWInfo->iContinue; -} - -/* -** Return the VDBE address or label to jump to in order to break -** out of a WHERE loop. -*/ -SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ - return pWInfo->iBreak; -} - -/* -** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to -** operate directly on the rowis returned by a WHERE clause. Return -** ONEPASS_SINGLE (1) if the statement can operation directly because only -** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass -** optimization can be used on multiple -** -** If the ONEPASS optimization is used (if this routine returns true) -** then also write the indices of open cursors used by ONEPASS -** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data -** table and iaCur[1] gets the cursor used by an auxiliary index. -** Either value may be -1, indicating that cursor is not used. -** Any cursors returned will have been opened for writing. -** -** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is -** unable to use the ONEPASS optimization. -*/ -SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ - memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ - sqlite3DebugPrintf("%s cursors: %d %d\n", - pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", - aiCur[0], aiCur[1]); - } -#endif - return pWInfo->eOnePass; -} - -/* -** Move the content of pSrc into pDest -*/ -static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ - pDest->n = pSrc->n; - memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); -} - -/* -** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. -** -** The new entry might overwrite an existing entry, or it might be -** appended, or it might be discarded. Do whatever is the right thing -** so that pSet keeps the N_OR_COST best entries seen so far. -*/ -static int whereOrInsert( - WhereOrSet *pSet, /* The WhereOrSet to be updated */ - Bitmask prereq, /* Prerequisites of the new entry */ - LogEst rRun, /* Run-cost of the new entry */ - LogEst nOut /* Number of outputs for the new entry */ -){ - u16 i; - WhereOrCost *p; - for(i=pSet->n, p=pSet->a; i>0; i--, p++){ - if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ - goto whereOrInsert_done; - } - if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ - return 0; - } - } - if( pSet->na[pSet->n++]; - p->nOut = nOut; - }else{ - p = pSet->a; - for(i=1; in; i++){ - if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; - } - if( p->rRun<=rRun ) return 0; - } -whereOrInsert_done: - p->prereq = prereq; - p->rRun = rRun; - if( p->nOut>nOut ) p->nOut = nOut; - return 1; -} - -/* -** Return the bitmask for the given cursor number. Return 0 if -** iCursor is not in the set. -*/ -SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ - int i; - assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - for(i=0; in; i++){ - if( pMaskSet->ix[i]==iCursor ){ - return MASKBIT(i); - } - } - return 0; -} - -/* -** Create a new mask for cursor iCursor. -** -** There is one cursor per table in the FROM clause. The number of -** tables in the FROM clause is limited by a test early in the -** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[] -** array will never overflow. -*/ -static void createMask(WhereMaskSet *pMaskSet, int iCursor){ - assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); - pMaskSet->ix[pMaskSet->n++] = iCursor; -} - -/* -** Advance to the next WhereTerm that matches according to the criteria -** established when the pScan object was initialized by whereScanInit(). -** Return NULL if there are no more matching WhereTerms. -*/ -static WhereTerm *whereScanNext(WhereScan *pScan){ - int iCur; /* The cursor on the LHS of the term */ - i16 iColumn; /* The column on the LHS of the term. -1 for IPK */ - Expr *pX; /* An expression being tested */ - WhereClause *pWC; /* Shorthand for pScan->pWC */ - WhereTerm *pTerm; /* The term being tested */ - int k = pScan->k; /* Where to start scanning */ - - while( pScan->iEquiv<=pScan->nEquiv ){ - iCur = pScan->aiCur[pScan->iEquiv-1]; - iColumn = pScan->aiColumn[pScan->iEquiv-1]; - if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; - while( (pWC = pScan->pWC)!=0 ){ - for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ - if( pTerm->leftCursor==iCur - && pTerm->u.leftColumn==iColumn - && (iColumn!=XN_EXPR - || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) - && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) - ){ - if( (pTerm->eOperator & WO_EQUIV)!=0 - && pScan->nEquivaiCur) - && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN - ){ - int j; - for(j=0; jnEquiv; j++){ - if( pScan->aiCur[j]==pX->iTable - && pScan->aiColumn[j]==pX->iColumn ){ - break; - } - } - if( j==pScan->nEquiv ){ - pScan->aiCur[j] = pX->iTable; - pScan->aiColumn[j] = pX->iColumn; - pScan->nEquiv++; - } - } - if( (pTerm->eOperator & pScan->opMask)!=0 ){ - /* Verify the affinity and collating sequence match */ - if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - CollSeq *pColl; - Parse *pParse = pWC->pWInfo->pParse; - pX = pTerm->pExpr; - if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ - continue; - } - assert(pX->pLeft); - pColl = sqlite3BinaryCompareCollSeq(pParse, - pX->pLeft, pX->pRight); - if( pColl==0 ) pColl = pParse->db->pDfltColl; - if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ - continue; - } - } - if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 - && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN - && pX->iTable==pScan->aiCur[0] - && pX->iColumn==pScan->aiColumn[0] - ){ - testcase( pTerm->eOperator & WO_IS ); - continue; - } - pScan->k = k+1; - return pTerm; - } - } - } - pScan->pWC = pScan->pWC->pOuter; - k = 0; - } - pScan->pWC = pScan->pOrigWC; - k = 0; - pScan->iEquiv++; - } - return 0; -} - -/* -** Initialize a WHERE clause scanner object. Return a pointer to the -** first match. Return NULL if there are no matches. -** -** The scanner will be searching the WHERE clause pWC. It will look -** for terms of the form "X " where X is column iColumn of table -** iCur. The must be one of the operators described by opMask. -** -** If the search is for X and the WHERE clause contains terms of the -** form X=Y then this routine might also return terms of the form -** "Y ". The number of levels of transitivity is limited, -** but is enough to handle most commonly occurring SQL statements. -** -** If X is not the INTEGER PRIMARY KEY then X must be compatible with -** index pIdx. -*/ -static WhereTerm *whereScanInit( - WhereScan *pScan, /* The WhereScan object being initialized */ - WhereClause *pWC, /* The WHERE clause to be scanned */ - int iCur, /* Cursor to scan for */ - int iColumn, /* Column to scan for */ - u32 opMask, /* Operator(s) to scan for */ - Index *pIdx /* Must be compatible with this index */ -){ - int j = 0; - - /* memset(pScan, 0, sizeof(*pScan)); */ - pScan->pOrigWC = pWC; - pScan->pWC = pWC; - pScan->pIdxExpr = 0; - if( pIdx ){ - j = iColumn; - iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - } - if( pIdx && iColumn>=0 ){ - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; - pScan->zCollName = pIdx->azColl[j]; - }else{ - pScan->idxaff = 0; - pScan->zCollName = 0; - } - pScan->opMask = opMask; - pScan->k = 0; - pScan->aiCur[0] = iCur; - pScan->aiColumn[0] = iColumn; - pScan->nEquiv = 1; - pScan->iEquiv = 1; - return whereScanNext(pScan); -} - -/* -** Search for a term in the WHERE clause that is of the form "X " -** where X is a reference to the iColumn of table iCur and is one of -** the WO_xx operator codes specified by the op parameter. -** Return a pointer to the term. Return 0 if not found. -** -** If pIdx!=0 then search for terms matching the iColumn-th column of pIdx -** rather than the iColumn-th column of table iCur. -** -** The term returned might by Y= if there is another constraint in -** the WHERE clause that specifies that X=Y. Any such constraints will be -** identified by the WO_EQUIV bit in the pTerm->eOperator field. The -** aiCur[]/iaColumn[] arrays hold X and all its equivalents. There are 11 -** slots in aiCur[]/aiColumn[] so that means we can look for X plus up to 10 -** other equivalent values. Hence a search for X will return if X=A1 -** and A1=A2 and A2=A3 and ... and A9=A10 and A10=. -** -** If there are multiple terms in the WHERE clause of the form "X " -** then try for the one with no dependencies on - in other words where -** is a constant expression of some kind. Only return entries of -** the form "X Y" where Y is a column in another table if no terms of -** the form "X " exist. If no terms with a constant RHS -** exist, try to return a term that does not use WO_EQUIV. -*/ -SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -){ - WhereTerm *pResult = 0; - WhereTerm *p; - WhereScan scan; - - p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); - op &= WO_EQ|WO_IS; - while( p ){ - if( (p->prereqRight & notReady)==0 ){ - if( p->prereqRight==0 && (p->eOperator&op)!=0 ){ - testcase( p->eOperator & WO_IS ); - return p; - } - if( pResult==0 ) pResult = p; - } - p = whereScanNext(&scan); - } - return pResult; -} - -/* -** This function searches pList for an entry that matches the iCol-th column -** of index pIdx. -** -** If such an expression is found, its index in pList->a[] is returned. If -** no expression is found, -1 is returned. -*/ -static int findIndexCol( - Parse *pParse, /* Parse context */ - ExprList *pList, /* Expression list to search */ - int iBase, /* Cursor for table associated with pIdx */ - Index *pIdx, /* Index to match column of */ - int iCol /* Column of index to match */ -){ - int i; - const char *zColl = pIdx->azColl[iCol]; - - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); - if( p->op==TK_COLUMN - && p->iColumn==pIdx->aiColumn[iCol] - && p->iTable==iBase - ){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); - if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ - return i; - } - } - } - - return -1; -} - -/* -** Return TRUE if the iCol-th column of index pIdx is NOT NULL -*/ -static int indexColumnNotNull(Index *pIdx, int iCol){ - int j; - assert( pIdx!=0 ); - assert( iCol>=0 && iColnColumn ); - j = pIdx->aiColumn[iCol]; - if( j>=0 ){ - return pIdx->pTable->aCol[j].notNull; - }else if( j==(-1) ){ - return 1; - }else{ - assert( j==(-2) ); - return 0; /* Assume an indexed expression can always yield a NULL */ - - } -} - -/* -** Return true if the DISTINCT expression-list passed as the third argument -** is redundant. -** -** A DISTINCT list is redundant if any subset of the columns in the -** DISTINCT list are collectively unique and individually non-null. -*/ -static int isDistinctRedundant( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* The FROM clause */ - WhereClause *pWC, /* The WHERE clause */ - ExprList *pDistinct /* The result set that needs to be DISTINCT */ -){ - Table *pTab; - Index *pIdx; - int i; - int iBase; - - /* If there is more than one table or sub-select in the FROM clause of - ** this query, then it will not be possible to show that the DISTINCT - ** clause is redundant. */ - if( pTabList->nSrc!=1 ) return 0; - iBase = pTabList->a[0].iCursor; - pTab = pTabList->a[0].pTab; - - /* If any of the expressions is an IPK column on table iBase, then return - ** true. Note: The (p->iTable==iBase) part of this test may be false if the - ** current SELECT is a correlated sub-query. - */ - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); - if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; - } - - /* Loop through all indices on the table, checking each to see if it makes - ** the DISTINCT qualifier redundant. It does so if: - ** - ** 1. The index is itself UNIQUE, and - ** - ** 2. All of the columns in the index are either part of the pDistinct - ** list, or else the WHERE clause contains a term of the form "col=X", - ** where X is a constant value. The collation sequences of the - ** comparison and select-list expressions must match those of the index. - ** - ** 3. All of those index columns for which the WHERE clause does not - ** contain a "col=X" term are subject to a NOT NULL constraint. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( !IsUniqueIndex(pIdx) ) continue; - for(i=0; inKeyCol; i++){ - if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){ - if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break; - if( indexColumnNotNull(pIdx, i)==0 ) break; - } - } - if( i==pIdx->nKeyCol ){ - /* This index implies that the DISTINCT qualifier is redundant. */ - return 1; - } - } - - return 0; -} - - -/* -** Estimate the logarithm of the input value to base 2. -*/ -static LogEst estLog(LogEst N){ - return N<=10 ? 0 : sqlite3LogEst(N) - 33; -} - -/* -** Convert OP_Column opcodes to OP_Copy in previously generated code. -** -** This routine runs over generated VDBE code and translates OP_Column -** opcodes into OP_Copy when the table is being accessed via co-routine -** instead of via table lookup. -** -** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on -** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero, -** then each OP_Rowid is transformed into an instruction to increment the -** value stored in its output register. -*/ -static void translateColumnToCopy( - Vdbe *v, /* The VDBE containing code to translate */ - int iStart, /* Translate from this opcode to the end */ - int iTabCur, /* OP_Column/OP_Rowid references to this table */ - int iRegister, /* The first column is in this register */ - int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */ -){ - VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); - int iEnd = sqlite3VdbeCurrentAddr(v); - for(; iStartp1!=iTabCur ) continue; - if( pOp->opcode==OP_Column ){ - pOp->opcode = OP_Copy; - pOp->p1 = pOp->p2 + iRegister; - pOp->p2 = pOp->p3; - pOp->p3 = 0; - }else if( pOp->opcode==OP_Rowid ){ - if( bIncrRowid ){ - /* Increment the value stored in the P2 operand of the OP_Rowid. */ - pOp->opcode = OP_AddImm; - pOp->p1 = pOp->p2; - pOp->p2 = 1; - }else{ - pOp->opcode = OP_Null; - pOp->p1 = 0; - pOp->p3 = 0; - } - } - } -} - -/* -** Two routines for printing the content of an sqlite3_index_info -** structure. Used for testing and debugging only. If neither -** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines -** are no-ops. -*/ -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) -static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", - i, - p->aConstraint[i].iColumn, - p->aConstraint[i].iTermOffset, - p->aConstraint[i].op, - p->aConstraint[i].usable); - } - for(i=0; inOrderBy; i++){ - sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", - i, - p->aOrderBy[i].iColumn, - p->aOrderBy[i].desc); - } -} -static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", - i, - p->aConstraintUsage[i].argvIndex, - p->aConstraintUsage[i].omit); - } - sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); - sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); - sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); - sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); - sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); -} -#else -#define TRACE_IDX_INPUTS(A) -#define TRACE_IDX_OUTPUTS(A) -#endif - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Return TRUE if the WHERE clause term pTerm is of a form where it -** could be used with an index to access pSrc, assuming an appropriate -** index existed. -*/ -static int termCanDriveIndex( - WhereTerm *pTerm, /* WHERE clause term to check */ - struct SrcList_item *pSrc, /* Table we are trying to access */ - Bitmask notReady /* Tables in outer loops of the join */ -){ - char aff; - if( pTerm->leftCursor!=pSrc->iCursor ) return 0; - if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; - if( (pTerm->prereqRight & notReady)!=0 ) return 0; - if( pTerm->u.leftColumn<0 ) return 0; - aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; - if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; - testcase( pTerm->pExpr->op==TK_IS ); - return 1; -} -#endif - - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Generate code to construct the Index object for an automatic index -** and to set up the WhereLevel object pLevel so that the code generator -** makes use of the automatic index. -*/ -static void constructAutomaticIndex( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ - Bitmask notReady, /* Mask of cursors that are not available */ - WhereLevel *pLevel /* Write new index here */ -){ - int nKeyCol; /* Number of columns in the constructed index */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - WhereTerm *pWCEnd; /* End of pWC->a[] */ - Index *pIdx; /* Object describing the transient index */ - Vdbe *v; /* Prepared statement under construction */ - int addrInit; /* Address of the initialization bypass jump */ - Table *pTable; /* The table being indexed */ - int addrTop; /* Top of the index fill loop */ - int regRecord; /* Register holding an index record */ - int n; /* Column counter */ - int i; /* Loop counter */ - int mxBitCol; /* Maximum column in pSrc->colUsed */ - CollSeq *pColl; /* Collating sequence to on a column */ - WhereLoop *pLoop; /* The Loop object */ - char *zNotUsed; /* Extra space on the end of pIdx */ - Bitmask idxCols; /* Bitmap of columns used for indexing */ - Bitmask extraCols; /* Bitmap of additional columns */ - u8 sentWarning = 0; /* True if a warnning has been issued */ - Expr *pPartial = 0; /* Partial Index Expression */ - int iContinue = 0; /* Jump here to skip excluded rows */ - struct SrcList_item *pTabItem; /* FROM clause term being indexed */ - int addrCounter = 0; /* Address where integer counter is initialized */ - int regBase; /* Array of registers where record is assembled */ - - /* Generate code to skip over the creation and initialization of the - ** transient index on 2nd and subsequent iterations of the loop. */ - v = pParse->pVdbe; - assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); - - /* Count the number of columns that will be added to the index - ** and used to match WHERE clause constraints */ - nKeyCol = 0; - pTable = pSrc->pTab; - pWCEnd = &pWC->a[pWC->nTerm]; - pLoop = pLevel->pWLoop; - idxCols = 0; - for(pTerm=pWC->a; pTermpExpr; - assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ - || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ - || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ - if( pLoop->prereq==0 - && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && !ExprHasProperty(pExpr, EP_FromJoin) - && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ - pPartial = sqlite3ExprAnd(pParse->db, pPartial, - sqlite3ExprDup(pParse->db, pExpr, 0)); - } - if( termCanDriveIndex(pTerm, pSrc, notReady) ){ - int iCol = pTerm->u.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); - testcase( iCol==BMS ); - testcase( iCol==BMS-1 ); - if( !sentWarning ){ - sqlite3_log(SQLITE_WARNING_AUTOINDEX, - "automatic index on %s(%s)", pTable->zName, - pTable->aCol[iCol].zName); - sentWarning = 1; - } - if( (idxCols & cMask)==0 ){ - if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){ - goto end_auto_index_create; - } - pLoop->aLTerm[nKeyCol++] = pTerm; - idxCols |= cMask; - } - } - } - assert( nKeyCol>0 ); - pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol; - pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED - | WHERE_AUTO_INDEX; - - /* Count the number of additional columns needed to create a - ** covering index. A "covering index" is an index that contains all - ** columns that are needed by the query. With a covering index, the - ** original table never needs to be accessed. Automatic indices must - ** be a covering index because the index will not be updated if the - ** original table changes and the index and table cannot both be used - ** if they go out of sync. - */ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); - mxBitCol = MIN(BMS-1,pTable->nCol); - testcase( pTable->nCol==BMS-1 ); - testcase( pTable->nCol==BMS-2 ); - for(i=0; icolUsed & MASKBIT(BMS-1) ){ - nKeyCol += pTable->nCol - BMS + 1; - } - - /* Construct the Index object to describe this index */ - pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); - if( pIdx==0 ) goto end_auto_index_create; - pLoop->u.btree.pIndex = pIdx; - pIdx->zName = "auto-index"; - pIdx->pTable = pTable; - n = 0; - idxCols = 0; - for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); - testcase( iCol==BMS-1 ); - testcase( iCol==BMS ); - if( (idxCols & cMask)==0 ){ - Expr *pX = pTerm->pExpr; - idxCols |= cMask; - pIdx->aiColumn[n] = pTerm->u.leftColumn; - pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; - n++; - } - } - } - assert( (u32)n==pLoop->u.btree.nEq ); - - /* Add additional columns needed to make the automatic index into - ** a covering index */ - for(i=0; iaiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; - } - } - if( pSrc->colUsed & MASKBIT(BMS-1) ){ - for(i=BMS-1; inCol; i++){ - pIdx->aiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; - } - } - assert( n==nKeyCol ); - pIdx->aiColumn[n] = XN_ROWID; - pIdx->azColl[n] = sqlite3StrBINARY; - - /* Create the automatic index */ - assert( pLevel->iIdxCur>=0 ); - pLevel->iIdxCur = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "for %s", pTable->zName)); - - /* Fill the automatic index with content */ - sqlite3ExprCachePush(pParse); - pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; - if( pTabItem->fg.viaCoroutine ){ - int regYield = pTabItem->regReturn; - addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); - VdbeCoverage(v); - VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); - }else{ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); - } - if( pPartial ){ - iContinue = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL); - pLoop->wsFlags |= WHERE_PARTIALIDX; - } - regRecord = sqlite3GetTempReg(pParse); - regBase = sqlite3GenerateIndexKey( - pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 - ); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); - if( pTabItem->fg.viaCoroutine ){ - sqlite3VdbeChangeP2(v, addrCounter, regBase+n); - translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1); - sqlite3VdbeGoto(v, addrTop); - pTabItem->fg.viaCoroutine = 0; - }else{ - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); - } - sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); - sqlite3VdbeJumpHere(v, addrTop); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3ExprCachePop(pParse); - - /* Jump here when skipping the initialization */ - sqlite3VdbeJumpHere(v, addrInit); - -end_auto_index_create: - sqlite3ExprDelete(pParse->db, pPartial); -} -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Allocate and populate an sqlite3_index_info structure. It is the -** responsibility of the caller to eventually release the structure -** by passing the pointer returned by this function to sqlite3_free(). -*/ -static sqlite3_index_info *allocateIndexInfo( - Parse *pParse, - WhereClause *pWC, - Bitmask mUnusable, /* Ignore terms with these prereqs */ - struct SrcList_item *pSrc, - ExprList *pOrderBy -){ - int i, j; - int nTerm; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_orderby *pIdxOrderBy; - struct sqlite3_index_constraint_usage *pUsage; - WhereTerm *pTerm; - int nOrderBy; - sqlite3_index_info *pIdxInfo; - - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ - for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - assert( pTerm->u.leftColumn>=(-1) ); - nTerm++; - } - - /* If the ORDER BY clause contains only columns in the current - ** virtual table then allocate space for the aOrderBy part of - ** the sqlite3_index_info structure. - */ - nOrderBy = 0; - if( pOrderBy ){ - int n = pOrderBy->nExpr; - for(i=0; ia[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; - } - if( i==n){ - nOrderBy = n; - } - } - - /* Allocate the sqlite3_index_info structure - */ - pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) - + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy ); - if( pIdxInfo==0 ){ - sqlite3ErrorMsg(pParse, "out of memory"); - return 0; - } - - /* Initialize the structure. The sqlite3_index_info structure contains - ** many fields that are declared "const" to prevent xBestIndex from - ** changing them. We have to do some funky casting in order to - ** initialize those fields. - */ - pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; - pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; - pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - *(int*)&pIdxInfo->nConstraint = nTerm; - *(int*)&pIdxInfo->nOrderBy = nOrderBy; - *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; - *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; - *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = - pUsage; - - for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - u8 op; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - assert( pTerm->u.leftColumn>=(-1) ); - pIdxCons[j].iColumn = pTerm->u.leftColumn; - pIdxCons[j].iTermOffset = i; - op = (u8)pTerm->eOperator & WO_ALL; - if( op==WO_IN ) op = WO_EQ; - if( op==WO_MATCH ){ - op = pTerm->eMatchOp; - } - pIdxCons[j].op = op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); - assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); - j++; - } - for(i=0; ia[i].pExpr; - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; - } - - return pIdxInfo; -} - -/* -** The table object reference passed as the second argument to this function -** must represent a virtual table. This function invokes the xBestIndex() -** method of the virtual table with the sqlite3_index_info object that -** comes in as the 3rd argument to this function. -** -** If an error occurs, pParse is populated with an error message and a -** non-zero value is returned. Otherwise, 0 is returned and the output -** part of the sqlite3_index_info structure is left populated. -** -** Whether or not an error is returned, it is the responsibility of the -** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates -** that this is required. -*/ -static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ - sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - int i; - int rc; - - TRACE_IDX_INPUTS(p); - rc = pVtab->pModule->xBestIndex(pVtab, p); - TRACE_IDX_OUTPUTS(p); - - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - pParse->db->mallocFailed = 1; - }else if( !pVtab->zErrMsg ){ - sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); - }else{ - sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); - } - } - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; - - for(i=0; inConstraint; i++){ - if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ - sqlite3ErrorMsg(pParse, - "table %s: xBestIndex returned an invalid plan", pTab->zName); - } - } - - return pParse->nErr; -} -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** Estimate the location of a particular key among all keys in an -** index. Store the results in aStat as follows: -** -** aStat[0] Est. number of rows less than pRec -** aStat[1] Est. number of rows equal to pRec -** -** Return the index of the sample that is the smallest sample that -** is greater than or equal to pRec. Note that this index is not an index -** into the aSample[] array - it is an index into a virtual set of samples -** based on the contents of aSample[] and the number of fields in record -** pRec. -*/ -static int whereKeyStats( - Parse *pParse, /* Database connection */ - Index *pIdx, /* Index to consider domain of */ - UnpackedRecord *pRec, /* Vector of values to consider */ - int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ -){ - IndexSample *aSample = pIdx->aSample; - int iCol; /* Index of required stats in anEq[] etc. */ - int i; /* Index of first sample >= pRec */ - int iSample; /* Smallest sample larger than or equal to pRec */ - int iMin = 0; /* Smallest sample not yet tested */ - int iTest; /* Next sample to test */ - int res; /* Result of comparison operation */ - int nField; /* Number of fields in pRec */ - tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ - -#ifndef SQLITE_DEBUG - UNUSED_PARAMETER( pParse ); -#endif - assert( pRec!=0 ); - assert( pIdx->nSample>0 ); - assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); - - /* Do a binary search to find the first sample greater than or equal - ** to pRec. If pRec contains a single field, the set of samples to search - ** is simply the aSample[] array. If the samples in aSample[] contain more - ** than one fields, all fields following the first are ignored. - ** - ** If pRec contains N fields, where N is more than one, then as well as the - ** samples in aSample[] (truncated to N fields), the search also has to - ** consider prefixes of those samples. For example, if the set of samples - ** in aSample is: - ** - ** aSample[0] = (a, 5) - ** aSample[1] = (a, 10) - ** aSample[2] = (b, 5) - ** aSample[3] = (c, 100) - ** aSample[4] = (c, 105) - ** - ** Then the search space should ideally be the samples above and the - ** unique prefixes [a], [b] and [c]. But since that is hard to organize, - ** the code actually searches this set: - ** - ** 0: (a) - ** 1: (a, 5) - ** 2: (a, 10) - ** 3: (a, 10) - ** 4: (b) - ** 5: (b, 5) - ** 6: (c) - ** 7: (c, 100) - ** 8: (c, 105) - ** 9: (c, 105) - ** - ** For each sample in the aSample[] array, N samples are present in the - ** effective sample array. In the above, samples 0 and 1 are based on - ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. - ** - ** Often, sample i of each block of N effective samples has (i+1) fields. - ** Except, each sample may be extended to ensure that it is greater than or - ** equal to the previous sample in the array. For example, in the above, - ** sample 2 is the first sample of a block of N samples, so at first it - ** appears that it should be 1 field in size. However, that would make it - ** smaller than sample 1, so the binary search would not work. As a result, - ** it is extended to two fields. The duplicates that this creates do not - ** cause any problems. - */ - nField = pRec->nField; - iCol = 0; - iSample = pIdx->nSample * nField; - do{ - int iSamp; /* Index in aSample[] of test sample */ - int n; /* Number of fields in test sample */ - - iTest = (iMin+iSample)/2; - iSamp = iTest / nField; - if( iSamp>0 ){ - /* The proposed effective sample is a prefix of sample aSample[iSamp]. - ** Specifically, the shortest prefix of at least (1 + iTest%nField) - ** fields that is greater than the previous effective sample. */ - for(n=(iTest % nField) + 1; nnField = n; - res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); - if( res<0 ){ - iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; - iMin = iTest+1; - }else if( res==0 && ndb->mallocFailed==0 ){ - if( res==0 ){ - /* If (res==0) is true, then pRec must be equal to sample i. */ - assert( inSample ); - assert( iCol==nField-1 ); - pRec->nField = nField; - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed - ); - }else{ - /* Unless i==pIdx->nSample, indicating that pRec is larger than - ** all samples in the aSample[] array, pRec must be smaller than the - ** (iCol+1) field prefix of sample i. */ - assert( i<=pIdx->nSample && i>=0 ); - pRec->nField = iCol+1; - assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 - || pParse->db->mallocFailed ); - - /* if i==0 and iCol==0, then record pRec is smaller than all samples - ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must - ** be greater than or equal to the (iCol) field prefix of sample i. - ** If (i>0), then pRec must also be greater than sample (i-1). */ - if( iCol>0 ){ - pRec->nField = iCol; - assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 - || pParse->db->mallocFailed ); - } - if( i>0 ){ - pRec->nField = nField; - assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed ); - } - } - } -#endif /* ifdef SQLITE_DEBUG */ - - if( res==0 ){ - /* Record pRec is equal to sample i */ - assert( iCol==nField-1 ); - aStat[0] = aSample[i].anLt[iCol]; - aStat[1] = aSample[i].anEq[iCol]; - }else{ - /* At this point, the (iCol+1) field prefix of aSample[i] is the first - ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec - ** is larger than all samples in the array. */ - tRowcnt iUpper, iGap; - if( i>=pIdx->nSample ){ - iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); - }else{ - iUpper = aSample[i].anLt[iCol]; - } - - if( iLower>=iUpper ){ - iGap = 0; - }else{ - iGap = iUpper - iLower; - } - if( roundUp ){ - iGap = (iGap*2)/3; - }else{ - iGap = iGap/3; - } - aStat[0] = iLower + iGap; - aStat[1] = pIdx->aAvgEq[iCol]; - } - - /* Restore the pRec->nField value before returning. */ - pRec->nField = nField; - return i; -} -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ - -/* -** If it is not NULL, pTerm is a term that provides an upper or lower -** bound on a range scan. Without considering pTerm, it is estimated -** that the scan will visit nNew rows. This function returns the number -** estimated to be visited after taking pTerm into account. -** -** If the user explicitly specified a likelihood() value for this term, -** then the return value is the likelihood multiplied by the number of -** input rows. Otherwise, this function assumes that an "IS NOT NULL" term -** has a likelihood of 0.50, and any other term a likelihood of 0.25. -*/ -static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ - LogEst nRet = nNew; - if( pTerm ){ - if( pTerm->truthProb<=0 ){ - nRet += pTerm->truthProb; - }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){ - nRet -= 20; assert( 20==sqlite3LogEst(4) ); - } - } - return nRet; -} - - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** Return the affinity for a single column of an index. -*/ -static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ - assert( iCol>=0 && iColnColumn ); - if( !pIdx->zColAff ){ - if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; - } - return pIdx->zColAff[iCol]; -} -#endif - - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** This function is called to estimate the number of rows visited by a -** range-scan on a skip-scan index. For example: -** -** CREATE INDEX i1 ON t1(a, b, c); -** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?; -** -** Value pLoop->nOut is currently set to the estimated number of rows -** visited for scanning (a=? AND b=?). This function reduces that estimate -** by some factor to account for the (c BETWEEN ? AND ?) expression based -** on the stat4 data for the index. this scan will be peformed multiple -** times (once for each (a,b) combination that matches a=?) is dealt with -** by the caller. -** -** It does this by scanning through all stat4 samples, comparing values -** extracted from pLower and pUpper with the corresponding column in each -** sample. If L and U are the number of samples found to be less than or -** equal to the values extracted from pLower and pUpper respectively, and -** N is the total number of samples, the pLoop->nOut value is adjusted -** as follows: -** -** nOut = nOut * ( min(U - L, 1) / N ) -** -** If pLower is NULL, or a value cannot be extracted from the term, L is -** set to zero. If pUpper is NULL, or a value cannot be extracted from it, -** U is set to N. -** -** Normally, this function sets *pbDone to 1 before returning. However, -** if no value can be extracted from either pLower or pUpper (and so the -** estimate of the number of rows delivered remains unchanged), *pbDone -** is left as is. -** -** If an error occurs, an SQLite error code is returned. Otherwise, -** SQLITE_OK. -*/ -static int whereRangeSkipScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop, /* Update the .nOut value of this loop */ - int *pbDone /* Set to true if at least one expr. value extracted */ -){ - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - sqlite3 *db = pParse->db; - int nLower = -1; - int nUpper = p->nSample+1; - int rc = SQLITE_OK; - u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); - CollSeq *pColl; - - sqlite3_value *p1 = 0; /* Value extracted from pLower */ - sqlite3_value *p2 = 0; /* Value extracted from pUpper */ - sqlite3_value *pVal = 0; /* Value extracted from record */ - - pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]); - if( pLower ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1); - nLower = 0; - } - if( pUpper && rc==SQLITE_OK ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2); - nUpper = p2 ? 0 : p->nSample; - } - - if( p1 || p2 ){ - int i; - int nDiff; - for(i=0; rc==SQLITE_OK && inSample; i++){ - rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal); - if( rc==SQLITE_OK && p1 ){ - int res = sqlite3MemCompare(p1, pVal, pColl); - if( res>=0 ) nLower++; - } - if( rc==SQLITE_OK && p2 ){ - int res = sqlite3MemCompare(p2, pVal, pColl); - if( res>=0 ) nUpper++; - } - } - nDiff = (nUpper - nLower); - if( nDiff<=0 ) nDiff = 1; - - /* If there is both an upper and lower bound specified, and the - ** comparisons indicate that they are close together, use the fallback - ** method (assume that the scan visits 1/64 of the rows) for estimating - ** the number of rows visited. Otherwise, estimate the number of rows - ** using the method described in the header comment for this function. */ - if( nDiff!=1 || pUpper==0 || pLower==0 ){ - int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff)); - pLoop->nOut -= nAdjust; - *pbDone = 1; - WHERETRACE(0x10, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", - nLower, nUpper, nAdjust*-1, pLoop->nOut)); - } - - }else{ - assert( *pbDone==0 ); - } - - sqlite3ValueFree(p1); - sqlite3ValueFree(p2); - sqlite3ValueFree(pVal); - - return rc; -} -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ - -/* -** This function is used to estimate the number of rows that will be visited -** by scanning an index for a range of values. The range may have an upper -** bound, a lower bound, or both. The WHERE clause terms that set the upper -** and lower bounds are represented by pLower and pUpper respectively. For -** example, assuming that index p is on t1(a): -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** |_____| |_____| -** | | -** pLower pUpper -** -** If either of the upper or lower bound is not present, then NULL is passed in -** place of the corresponding WhereTerm. -** -** The value in (pBuilder->pNew->u.btree.nEq) is the number of the index -** column subject to the range constraint. Or, equivalently, the number of -** equality constraints optimized by the proposed index scan. For example, -** assuming index p is on t1(a, b), and the SQL query is: -** -** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... -** -** then nEq is set to 1 (as the range restricted column, b, is the second -** left-most column of the index). Or, if the query is: -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** -** then nEq is set to 0. -** -** When this function is called, *pnOut is set to the sqlite3LogEst() of the -** number of rows that the index scan is expected to visit without -** considering the range constraints. If nEq is 0, then *pnOut is the number of -** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) -** to account for the range constraints pLower and pUpper. -** -** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be -** used, a single range inequality reduces the search space by a factor of 4. -** and a pair of constraints (x>? AND x123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ -){ - int rc = SQLITE_OK; - int nOut = pLoop->nOut; - LogEst nNew; - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - - if( p->nSample>0 && nEqnSampleCol ){ - if( nEq==pBuilder->nRecValid ){ - UnpackedRecord *pRec = pBuilder->pRec; - tRowcnt a[2]; - u8 aff; - - /* Variable iLower will be set to the estimate of the number of rows in - ** the index that are less than the lower bound of the range query. The - ** lower bound being the concatenation of $P and $L, where $P is the - ** key-prefix formed by the nEq values matched against the nEq left-most - ** columns of the index, and $L is the value in pLower. - ** - ** Or, if pLower is NULL or $L cannot be extracted from it (because it - ** is not a simple variable or literal value), the lower bound of the - ** range is $P. Due to a quirk in the way whereKeyStats() works, even - ** if $L is available, whereKeyStats() is called for both ($P) and - ** ($P:$L) and the larger of the two returned values is used. - ** - ** Similarly, iUpper is to be set to the estimate of the number of rows - ** less than the upper bound of the range query. Where the upper bound - ** is either ($P) or ($P:$U). Again, even if $U is available, both values - ** of iUpper are requested of whereKeyStats() and the smaller used. - ** - ** The number of rows between the two bounds is then just iUpper-iLower. - */ - tRowcnt iLower; /* Rows less than the lower bound */ - tRowcnt iUpper; /* Rows less than the upper bound */ - int iLwrIdx = -2; /* aSample[] for the lower bound */ - int iUprIdx = -1; /* aSample[] for the upper bound */ - - if( pRec ){ - testcase( pRec->nField!=pBuilder->nRecValid ); - pRec->nField = pBuilder->nRecValid; - } - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq); - assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER ); - /* Determine iLower and iUpper using ($P) only. */ - if( nEq==0 ){ - iLower = 0; - iUpper = p->nRowEst0; - }else{ - /* Note: this call could be optimized away - since the same values must - ** have been requested when testing key $P in whereEqualScanEst(). */ - whereKeyStats(pParse, p, pRec, 0, a); - iLower = a[0]; - iUpper = a[0] + a[1]; - } - - assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 ); - assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); - assert( p->aSortOrder!=0 ); - if( p->aSortOrder[nEq] ){ - /* The roles of pLower and pUpper are swapped for a DESC index */ - SWAP(WhereTerm*, pLower, pUpper); - } - - /* If possible, improve on the iLower estimate using ($P:$L). */ - if( pLower ){ - int bOk; /* True if value is extracted from pExpr */ - Expr *pExpr = pLower->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; - iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); - if( iNew>iLower ) iLower = iNew; - nOut--; - pLower = 0; - } - } - - /* If possible, improve on the iUpper estimate using ($P:$U). */ - if( pUpper ){ - int bOk; /* True if value is extracted from pExpr */ - Expr *pExpr = pUpper->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); - if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; - iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0); - if( iNewpRec = pRec; - if( rc==SQLITE_OK ){ - if( iUpper>iLower ){ - nNew = sqlite3LogEst(iUpper - iLower); - /* TUNING: If both iUpper and iLower are derived from the same - ** sample, then assume they are 4x more selective. This brings - ** the estimated selectivity more in line with what it would be - ** if estimated without the use of STAT3/4 tables. */ - if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); - }else{ - nNew = 10; assert( 10==sqlite3LogEst(2) ); - } - if( nNewwtFlags & TERM_VNULL)==0 ); - nNew = whereRangeAdjust(pLower, nOut); - nNew = whereRangeAdjust(pUpper, nNew); - - /* TUNING: If there is both an upper and lower limit and neither limit - ** has an application-defined likelihood(), assume the range is - ** reduced by an additional 75%. This means that, by default, an open-ended - ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the - ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to - ** match 1/64 of the index. */ - if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){ - nNew -= 20; - } - - nOut -= (pLower!=0) + (pUpper!=0); - if( nNew<10 ) nNew = 10; - if( nNewnOut>nOut ){ - WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n", - pLoop->nOut, nOut)); - } -#endif - pLoop->nOut = (LogEst)nOut; - return rc; -} - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** Estimate the number of rows that will be returned based on -** an equality constraint x=VALUE and where that VALUE occurs in -** the histogram data. This only works when x is the left-most -** column of an index and sqlite_stat3 histogram data is available -** for that index. When pExpr==NULL that means the constraint is -** "x IS NULL" instead of "x=VALUE". -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereEqualScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - int nEq = pBuilder->pNew->u.btree.nEq; - UnpackedRecord *pRec = pBuilder->pRec; - u8 aff; /* Column affinity */ - int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ - int bOk; - - assert( nEq>=1 ); - assert( nEq<=p->nColumn ); - assert( p->aSample!=0 ); - assert( p->nSample>0 ); - assert( pBuilder->nRecValidnRecValid<(nEq-1) ){ - return SQLITE_NOTFOUND; - } - - /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue() - ** below would return the same value. */ - if( nEq>=p->nColumn ){ - *pnRow = 1; - return SQLITE_OK; - } - - aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1); - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk); - pBuilder->pRec = pRec; - if( rc!=SQLITE_OK ) return rc; - if( bOk==0 ) return SQLITE_NOTFOUND; - pBuilder->nRecValid = nEq; - - whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1])); - *pnRow = a[1]; - - return rc; -} -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ - -#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 -/* -** Estimate the number of rows that will be returned based on -** an IN constraint where the right-hand side of the IN operator -** is a list of values. Example: -** -** WHERE x IN (1,2,3,4) -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereInScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); - int nRecValid = pBuilder->nRecValid; - int rc = SQLITE_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ - int i; /* Loop counter */ - - assert( p->aSample!=0 ); - for(i=0; rc==SQLITE_OK && inExpr; i++){ - nEst = nRow0; - rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); - nRowEst += nEst; - pBuilder->nRecValid = nRecValid; - } - - if( rc==SQLITE_OK ){ - if( nRowEst > nRow0 ) nRowEst = nRow0; - *pnRow = nRowEst; - WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst)); - } - assert( pBuilder->nRecValid==nRecValid ); - return rc; -} -#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ - - -#ifdef WHERETRACE_ENABLED -/* -** Print the content of a WhereTerm object -*/ -static void whereTermPrint(WhereTerm *pTerm, int iTerm){ - if( pTerm==0 ){ - sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); - }else{ - char zType[4]; - memcpy(zType, "...", 4); - if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; - if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; - sqlite3DebugPrintf( - "TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n", - iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb, - pTerm->eOperator, pTerm->wtFlags); - sqlite3TreeViewExpr(0, pTerm->pExpr, 0); - } -} -#endif #ifdef WHERETRACE_ENABLED /* @@ -124245,8 +113704,8 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - const char *zName; - if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ + const char *zName; + if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ int i = sqlite3Strlen30(zName) - 1; while( zName[i]!='_' ) i--; @@ -124267,18 +113726,29 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3DebugPrintf(" %-19s", z); sqlite3_free(z); } - if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); - }else{ - sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); - } + sqlite3DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm); sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); - if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ +#ifdef SQLITE_ENABLE_TREE_EXPLAIN + /* If the 0x100 bit of wheretracing is set, then show all of the constraint + ** expressions in the WhereLoop.aLTerm[] array. + */ + if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */ int i; + Vdbe *v = pWInfo->pParse->pVdbe; + sqlite3ExplainBegin(v); for(i=0; inLTerm; i++){ - whereTermPrint(p->aLTerm[i], i); + WhereTerm *pTerm = p->aLTerm[i]; + if( pTerm==0 ) continue; + sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a)); + sqlite3ExplainPush(v); + whereExplainTerm(v, pTerm); + sqlite3ExplainPop(v); + sqlite3ExplainNL(v); } + sqlite3ExplainFinish(v); + sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v)); } +#endif } #endif @@ -124304,6 +113774,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){ p->u.vtab.idxStr = 0; }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ sqlite3DbFree(db, p->u.btree.pIndex->zColAff); + sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo); sqlite3DbFree(db, p->u.btree.pIndex); p->u.btree.pIndex = 0; } @@ -124367,14 +113838,7 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ if( ALWAYS(pWInfo) ){ - int i; - for(i=0; inLevel; i++){ - WhereLevel *pLevel = &pWInfo->a[i]; - if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ - sqlite3DbFree(db, pLevel->u.in.aInLoop); - } - } - sqlite3WhereClauseClear(&pWInfo->sWC); + whereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; pWInfo->pLoops = p->pNextLoop; @@ -124385,11 +113849,10 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ } /* -** Return TRUE if all of the following are true: +** Return TRUE if both of the following are true: ** ** (1) X has the same or lower cost that Y ** (2) X is a proper subset of Y -** (3) X skips at least as many columns as Y ** ** By "proper subset" we mean that X uses fewer WHERE clause terms ** than Y and that every WHERE clause term used by X is also used @@ -124397,25 +113860,19 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** ** If X is a proper subset of Y then Y is a better choice and ought ** to have a lower cost. This routine returns TRUE when that cost -** relationship is inverted and needs to be adjusted. The third rule -** was added because if X uses skip-scan less than Y it still might -** deserve a lower cost even if it is a proper subset of Y. +** relationship is inverted and needs to be adjusted. */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ const WhereLoop *pY /* Compare against this WhereLoop */ ){ int i, j; - if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ - return 0; /* X is not a subset of Y */ - } - if( pY->nSkip > pX->nSkip ) return 0; + if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */ if( pX->rRun >= pY->rRun ){ if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */ if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */ } for(i=pX->nLTerm-1; i>=0; i--){ - if( pX->aLTerm[i]==0 ) continue; for(j=pY->nLTerm-1; j>=0; j--){ if( pY->aLTerm[j]==pX->aLTerm[i] ) break; } @@ -124437,24 +113894,33 @@ static int whereLoopCheaperProperSubset( ** To say "WhereLoop X is a proper subset of Y" means that X uses fewer ** WHERE clause terms than Y and that every WHERE clause term used by X is ** also used by Y. +** +** This adjustment is omitted for SKIPSCAN loops. In a SKIPSCAN loop, the +** WhereLoop.nLTerm field is not an accurate measure of the number of WHERE +** clause terms covered, since some of the first nLTerm entries in aLTerm[] +** will be NULL (because they are skipped). That makes it more difficult +** to compare the loops. We could add extra code to do the comparison, and +** perhaps we will someday. But SKIPSCAN is sufficiently uncommon, and this +** adjustment is sufficient minor, that it is very difficult to construct +** a test case where the extra code would improve the query plan. Better +** to avoid the added complexity and just omit cost adjustments to SKIPSCAN +** loops. */ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; + if( (pTemplate->wsFlags & WHERE_SKIPSCAN)!=0 ) return; for(; p; p=p->pNextLoop){ if( p->iTab!=pTemplate->iTab ) continue; if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; + if( (p->wsFlags & WHERE_SKIPSCAN)!=0 ) continue; if( whereLoopCheaperProperSubset(p, pTemplate) ){ /* Adjust pTemplate cost downward so that it is cheaper than its - ** subset p. */ - WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1)); + ** subset p */ pTemplate->rRun = p->rRun; pTemplate->nOut = p->nOut - 1; }else if( whereLoopCheaperProperSubset(pTemplate, p) ){ /* Adjust pTemplate cost upward so that it is costlier than p since ** pTemplate is a proper subset of p */ - WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1)); pTemplate->rRun = p->rRun; pTemplate->nOut = p->nOut + 1; } @@ -124497,18 +113963,6 @@ static WhereLoop **whereLoopFindLesser( ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); - /* Any loop using an appliation-defined index (or PRIMARY KEY or - ** UNIQUE constraint) with one or more == constraints is better - ** than an automatic index. Unless it is a skip-scan. */ - if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 - && (pTemplate->nSkip)==0 - && (pTemplate->wsFlags & WHERE_INDEXED)!=0 - && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0 - && (p->prereq & pTemplate->prereq)==pTemplate->prereq - ){ - break; - } - /* If existing WhereLoop p is better than pTemplate, pTemplate can be ** discarded. WhereLoop p is better if: ** (1) p has no more dependencies than pTemplate, and @@ -124571,20 +114025,18 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** and prereqs. */ if( pBuilder->pOrSet!=0 ){ - if( pTemplate->nLTerm ){ #if WHERETRACE_ENABLED - u16 n = pBuilder->pOrSet->n; - int x = + u16 n = pBuilder->pOrSet->n; + int x = #endif - whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, + whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, pTemplate->nOut); #if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); - whereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif + if( sqlite3WhereTrace & 0x8 ){ + sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); + whereLoopPrint(pTemplate, pBuilder->pWC); } +#endif return SQLITE_OK; } @@ -124598,7 +114050,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** than pTemplate, so just ignore pTemplate */ #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" skip: "); + sqlite3DebugPrintf("ins-noop: "); whereLoopPrint(pTemplate, pBuilder->pWC); } #endif @@ -124614,10 +114066,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ if( p!=0 ){ - sqlite3DebugPrintf("replace: "); + sqlite3DebugPrintf("ins-del: "); whereLoopPrint(p, pBuilder->pWC); } - sqlite3DebugPrintf(" add: "); + sqlite3DebugPrintf("ins-new: "); whereLoopPrint(pTemplate, pBuilder->pWC); } #endif @@ -124635,13 +114087,13 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ WhereLoop *pToDel; while( *ppTail ){ ppTail = whereLoopFindLesser(ppTail, pTemplate); - if( ppTail==0 ) break; + if( NEVER(ppTail==0) ) break; pToDel = *ppTail; if( pToDel==0 ) break; *ppTail = pToDel->pNextLoop; #if WHERETRACE_ENABLED /* 0x8 */ if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" delete: "); + sqlite3DebugPrintf("ins-del: "); whereLoopPrint(pToDel, pBuilder->pWC); } #endif @@ -124662,42 +114114,19 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** Adjust the WhereLoop.nOut value downward to account for terms of the ** WHERE clause that reference the loop but which are not used by an ** index. -* -** For every WHERE clause term that is not used by the index -** and which has a truth probability assigned by one of the likelihood(), -** likely(), or unlikely() SQL functions, reduce the estimated number -** of output rows by the probability specified. ** -** TUNING: For every WHERE clause term that is not used by the index -** and which does not have an assigned truth probability, heuristics -** described below are used to try to estimate the truth probability. -** TODO --> Perhaps this is something that could be improved by better -** table statistics. -** -** Heuristic 1: Estimate the truth probability as 93.75%. The 93.75% -** value corresponds to -1 in LogEst notation, so this means decrement -** the WhereLoop.nOut field for every such WHERE clause term. -** -** Heuristic 2: If there exists one or more WHERE clause terms of the -** form "x==EXPR" and EXPR is not a constant 0 or 1, then make sure the -** final output row estimate is no greater than 1/4 of the total number -** of rows in the table. In other words, assume that x==EXPR will filter -** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the -** "x" column is boolean or else -1 or 0 or 1 is a common default value -** on the "x" column and so in that case only cap the output row estimate -** at 1/2 instead of 1/4. +** In the current implementation, the first extra WHERE clause term reduces +** the number of output rows by a factor of 10 and each additional term +** reduces the number of output rows by sqrt(2). */ -static void whereLoopOutputAdjust( - WhereClause *pWC, /* The WHERE clause */ - WhereLoop *pLoop, /* The loop to adjust downward */ - LogEst nRow /* Number of rows in the entire table */ -){ +static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){ WhereTerm *pTerm, *pX; Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int i, j, k; - LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ + int i, j; - assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); + if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){ + return; + } for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; @@ -124709,40 +114138,11 @@ static void whereLoopOutputAdjust( if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; } if( j<0 ){ - if( pTerm->truthProb<=0 ){ - /* If a truth probability is specified using the likelihood() hints, - ** then use the probability provided by the application. */ - pLoop->nOut += pTerm->truthProb; - }else{ - /* In the absence of explicit truth probabilities, use heuristics to - ** guess a reasonable truth probability. */ - pLoop->nOut--; - if( pTerm->eOperator&(WO_EQ|WO_IS) ){ - Expr *pRight = pTerm->pExpr->pRight; - testcase( pTerm->pExpr->op==TK_IS ); - if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){ - k = 10; - }else{ - k = 20; - } - if( iReducenOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1); } } - if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; } -/* -** Adjust the cost C by the costMult facter T. This only occurs if -** compiled with -DSQLITE_ENABLE_COSTMULT -*/ -#ifdef SQLITE_ENABLE_COSTMULT -# define ApplyCostMultiplier(C,T) C += T -#else -# define ApplyCostMultiplier(C,T) -#endif - /* ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the ** index pIndex. Try to match one more. @@ -124771,11 +114171,11 @@ static int whereLoopAddBtreeIndex( Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ - u16 saved_nSkip; /* Original value of pNew->nSkip */ + u16 saved_nSkip; /* Original value of pNew->u.btree.nSkip */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ LogEst saved_nOut; /* Original value of pNew->nOut */ + int iCol; /* Index of the column in the table */ int rc = SQLITE_OK; /* Return code */ - LogEst rSize; /* Number of rows in the table */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ @@ -124786,26 +114186,57 @@ static int whereLoopAddBtreeIndex( assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; - }else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){ + }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; }else{ - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; + opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; } if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); - assert( pNew->u.btree.nEqnColumn ); - + assert( pNew->u.btree.nEq<=pProbe->nKeyCol ); + if( pNew->u.btree.nEq < pProbe->nKeyCol ){ + iCol = pProbe->aiColumn[pNew->u.btree.nEq]; + }else{ + iCol = -1; + } + pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, + opMask, pProbe); saved_nEq = pNew->u.btree.nEq; - saved_nSkip = pNew->nSkip; + saved_nSkip = pNew->u.btree.nSkip; saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; - pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq, - opMask, pProbe); pNew->rSetup = 0; - rSize = pProbe->aiRowLogEst[0]; - rLogSize = estLog(rSize); + rLogSize = estLog(pProbe->aiRowLogEst[0]); + + /* Consider using a skip-scan if there are no WHERE clause constraints + ** available for the left-most terms of the index, and if the average + ** number of repeats in the left-most terms is at least 18. + ** + ** The magic number 18 is selected on the basis that scanning 17 rows + ** is almost always quicker than an index seek (even though if the index + ** contains fewer than 2^17 rows we assume otherwise in other parts of + ** the code). And, even if it is not, it should not be too much slower. + ** On the other hand, the extra seeks could end up being significantly + ** more expensive. */ + assert( 42==sqlite3LogEst(18) ); + if( pTerm==0 + && saved_nEq==saved_nSkip + && saved_nEq+1nKeyCol + && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ + && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK + ){ + LogEst nIter; + pNew->u.btree.nEq++; + pNew->u.btree.nSkip++; + pNew->aLTerm[pNew->nLTerm++] = 0; + pNew->wsFlags |= WHERE_SKIPSCAN; + nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; + pNew->nOut -= nIter; + whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); + pNew->nOut = saved_nOut; + } for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ LogEst rCostIdx; @@ -124815,16 +114246,12 @@ static int whereLoopAddBtreeIndex( int nRecValid = pBuilder->nRecValid; #endif if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) - && indexColumnNotNull(pProbe, saved_nEq) + && (iCol<0 || pSrc->pTab->aCol[iCol].notNull) ){ continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */ } if( pTerm->prereqRight & pNew->maskSelf ) continue; - /* Do not allow the upper bound of a LIKE optimization range constraint - ** to mix with a lower range bound from some other source */ - if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; - pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; @@ -124851,14 +114278,10 @@ static int whereLoopAddBtreeIndex( assert( nIn>0 ); /* RHS always has 2 or more terms... The parser ** changes "x IN (?)" into "x=?". */ - }else if( eOp & (WO_EQ|WO_IS) ){ - int iCol = pProbe->aiColumn[saved_nEq]; + }else if( eOp & (WO_EQ) ){ pNew->wsFlags |= WHERE_COLUMN_EQ; - assert( saved_nEq==pNew->u.btree.nEq ); - if( iCol==XN_ROWID - || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) - ){ - if( iCol>=0 && pProbe->uniqNotNull==0 ){ + if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ + if( iCol>=0 && pProbe->onError==OE_None ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ pNew->wsFlags |= WHERE_ONEROW; @@ -124872,17 +114295,6 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; pBtm = pTerm; pTop = 0; - if( pTerm->wtFlags & TERM_LIKEOPT ){ - /* Range contraints that come from the LIKE optimization are - ** always used in pairs. */ - pTop = &pTerm[1]; - assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); - assert( pTop->wtFlags & TERM_LIKEOPT ); - assert( pTop->eOperator==WO_LT ); - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTop; - pNew->wsFlags |= WHERE_TOP_LIMIT; - } }else{ assert( eOp & (WO_LT|WO_LE) ); testcase( eOp & WO_LT ); @@ -124905,10 +114317,10 @@ static int whereLoopAddBtreeIndex( whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); }else{ int nEq = ++pNew->u.btree.nEq; - assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) ); + assert( eOp & (WO_ISNULL|WO_EQ|WO_IN) ); assert( pNew->nOut==saved_nOut ); - if( pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0 ){ + if( pTerm->truthProb<=0 && iCol>=0 ){ assert( (eOp & WO_IN) || nIn==0 ); testcase( eOp & WO_IN ); pNew->nOut += pTerm->truthProb; @@ -124919,17 +114331,18 @@ static int whereLoopAddBtreeIndex( if( nInMul==0 && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol + && OptimizationEnabled(db, SQLITE_Stat3) && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) ){ Expr *pExpr = pTerm->pExpr; - if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ + if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){ testcase( eOp & WO_EQ ); - testcase( eOp & WO_IS ); testcase( eOp & WO_ISNULL ); rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); }else{ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } + assert( rc!=SQLITE_OK || nOut>0 ); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ if( nOut ){ @@ -124961,12 +114374,11 @@ static int whereLoopAddBtreeIndex( if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); } - ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); nOutUnadjusted = pNew->nOut; pNew->rRun += nInMul + nIn; pNew->nOut += nInMul + nIn; - whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); + whereLoopOutputAdjust(pBuilder->pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ @@ -124976,7 +114388,7 @@ static int whereLoopAddBtreeIndex( } if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 - && pNew->u.btree.nEqnColumn + && pNew->u.btree.nEq<(pProbe->nKeyCol + (pProbe->zName!=0)) ){ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } @@ -124987,45 +114399,10 @@ static int whereLoopAddBtreeIndex( } pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; - pNew->nSkip = saved_nSkip; + pNew->u.btree.nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; pNew->nOut = saved_nOut; pNew->nLTerm = saved_nLTerm; - - /* Consider using a skip-scan if there are no WHERE clause constraints - ** available for the left-most terms of the index, and if the average - ** number of repeats in the left-most terms is at least 18. - ** - ** The magic number 18 is selected on the basis that scanning 17 rows - ** is almost always quicker than an index seek (even though if the index - ** contains fewer than 2^17 rows we assume otherwise in other parts of - ** the code). And, even if it is not, it should not be too much slower. - ** On the other hand, the extra seeks could end up being significantly - ** more expensive. */ - assert( 42==sqlite3LogEst(18) ); - if( saved_nEq==saved_nSkip - && saved_nEq+1nKeyCol - && pProbe->noSkipScan==0 - && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ - && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK - ){ - LogEst nIter; - pNew->u.btree.nEq++; - pNew->nSkip++; - pNew->aLTerm[pNew->nLTerm++] = 0; - pNew->wsFlags |= WHERE_SKIPSCAN; - nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; - pNew->nOut -= nIter; - /* TUNING: Because uncertainties in the estimates for skip-scan queries, - ** add a 1.375 fudge factor to make skip-scan slightly less likely. */ - nIter += 5; - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); - pNew->nOut = saved_nOut; - pNew->u.btree.nEq = saved_nEq; - pNew->nSkip = saved_nSkip; - pNew->wsFlags = saved_wsFlags; - } - return rc; } @@ -125043,25 +114420,17 @@ static int indexMightHelpWithOrderBy( int iCursor ){ ExprList *pOB; - ExprList *aColExpr; int ii, jj; if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); - if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ - if( pExpr->iColumn<0 ) return 1; + if( pExpr->op!=TK_COLUMN ) return 0; + if( pExpr->iTable==iCursor ){ for(jj=0; jjnKeyCol; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; } - }else if( (aColExpr = pIndex->aColExpr)!=0 ){ - for(jj=0; jjnKeyCol; jj++){ - if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ - return 1; - } - } } } return 0; @@ -125091,17 +114460,8 @@ static Bitmask columnsInIndex(Index *pIdx){ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ int i; WhereTerm *pTerm; - while( pWhere->op==TK_AND ){ - if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0; - pWhere = pWhere->pRight; - } for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr = pTerm->pExpr; - if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab) - && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) - ){ - return 1; - } + if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) ) return 1; } return 0; } @@ -125133,14 +114493,6 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ ** Normally, nSeek is 1. nSeek values greater than 1 come about if the ** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when ** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans. -** -** The estimated values (nRow, nVisit, nSeek) often contain a large amount -** of uncertainty. For this reason, scoring is designed to pick plans that -** "do the least harm" if the estimates are inaccurate. For example, a -** log(nRow) factor is omitted from a non-covering index scan in order to -** bias the scoring in favor of using an index, since the worst-case -** performance of using an index is far better than the worst-case performance -** of a full table scan. */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ @@ -125170,9 +114522,9 @@ static int whereLoopAddBtree( pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); - if( pSrc->pIBIndex ){ + if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ - pProbe = pSrc->pIBIndex; + pProbe = pSrc->pIndex; }else if( !HasRowid(pTab) ){ pProbe = pTab->pIndex; }else{ @@ -125183,7 +114535,6 @@ static int whereLoopAddBtree( Index *pFirst; /* First of real indices on the table */ memset(&sPk, 0, sizeof(Index)); sPk.nKeyCol = 1; - sPk.nColumn = 1; sPk.aiColumn = &aiColumnPk; sPk.aiRowLogEst = aiRowEstPk; sPk.onError = OE_Replace; @@ -125192,7 +114543,7 @@ static int whereLoopAddBtree( aiRowEstPk[0] = pTab->nRowLogEst; aiRowEstPk[1] = 0; pFirst = pSrc->pTab->pIndex; - if( pSrc->fg.notIndexed==0 ){ + if( pSrc->notIndexed==0 ){ /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; @@ -125204,14 +114555,14 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ - if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0 + if( !pBuilder->pOrSet && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 - && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ - && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ - && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ - && !pSrc->fg.isCorrelated /* Not a correlated subquery */ - && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ + && pSrc->pIndex==0 + && !pSrc->viaCoroutine + && !pSrc->notIndexed + && HasRowid(pTab) + && !pSrc->isCorrelated + && !pSrc->isRecursive ){ /* Generate auto-index WhereLoops */ WhereTerm *pTerm; @@ -125220,26 +114571,17 @@ static int whereLoopAddBtree( if( pTerm->prereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; - pNew->nSkip = 0; + pNew->u.btree.nSkip = 0; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is - ** estimated to be X*N*log2(N) where N is the number of rows in - ** the table being indexed and where X is 7 (LogEst=28) for normal - ** tables or 1.375 (LogEst=4) for views and subqueries. The value - ** of X is smaller for views and subqueries so that the query planner - ** will be more aggressive about generating automatic indexes for - ** those objects, since there is no opportunity to add schema - ** indexes on subqueries and views. */ - pNew->rSetup = rLogSize + rSize + 4; - if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ - pNew->rSetup += 24; - } - ApplyCostMultiplier(pNew->rSetup, pTab->costMult); + ** approximately 7*N*log2(N) where N is the number of rows in + ** the table being indexed. */ + pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) ); /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way - ** of knowing how selective the index will ultimately be. It would + ** of knowning how selective the index will ultimately be. It would ** not be unreasonable to make this value much larger. */ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) ); pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); @@ -125255,13 +114597,12 @@ static int whereLoopAddBtree( */ for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ if( pProbe->pPartIdxWhere!=0 - && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){ - testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ + && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){ continue; /* Partial index inappropriate for this query */ } rSize = pProbe->aiRowLogEst[0]; pNew->u.btree.nEq = 0; - pNew->nSkip = 0; + pNew->u.btree.nSkip = 0; pNew->nLTerm = 0; pNew->iSortIdx = 0; pNew->rSetup = 0; @@ -125279,8 +114620,7 @@ static int whereLoopAddBtree( pNew->iSortIdx = b ? iSortIdx : 0; /* TUNING: Cost of full table scan is (N*3.0). */ pNew->rRun = rSize + 16; - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); + whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; @@ -125315,8 +114655,8 @@ static int whereLoopAddBtree( if( m!=0 ){ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16); } - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); + + whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; @@ -125332,7 +114672,7 @@ static int whereLoopAddBtree( /* If there was an INDEXED BY clause, then only that one index is ** considered. */ - if( pSrc->pIBIndex ) break; + if( pSrc->pIndex ) break; } return rc; } @@ -125341,32 +114681,10 @@ static int whereLoopAddBtree( /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. -** -** If there are no LEFT or CROSS JOIN joins in the query, both mExtra and -** mUnusable are set to 0. Otherwise, mExtra is a mask of all FROM clause -** entries that occur before the virtual table in the FROM clause and are -** separated from it by at least one LEFT or CROSS JOIN. Similarly, the -** mUnusable mask contains all FROM clause entries that occur after the -** virtual table and are separated from it by at least one LEFT or -** CROSS JOIN. -** -** For example, if the query were: -** -** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6; -** -** then mExtra corresponds to (t1, t2) and mUnusable to (t5, t6). -** -** All the tables in mExtra must be scanned before the current virtual -** table. So any terms for which all prerequisites are satisfied by -** mExtra may be specified as "usable" in all calls to xBestIndex. -** Conversely, all tables in mUnusable must be scanned after the current -** virtual table, so any terms for which the prerequisites overlap with -** mUnusable should always be configured as "not-usable" for xBestIndex. */ static int whereLoopAddVirtual( WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mExtra, /* Tables that must be scanned before this one */ - Bitmask mUnusable /* Tables that must be scanned after this one */ + Bitmask mExtra ){ WhereInfo *pWInfo; /* WHERE analysis context */ Parse *pParse; /* The parsing context */ @@ -125387,7 +114705,6 @@ static int whereLoopAddVirtual( WhereLoop *pNew; int rc = SQLITE_OK; - assert( (mExtra & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; db = pParse->db; @@ -125396,7 +114713,7 @@ static int whereLoopAddVirtual( pSrc = &pWInfo->pTabList->a[pNew->iTab]; pTab = pSrc->pTab; assert( IsVirtual(pTab) ); - pIdxInfo = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy); + pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy); if( pIdxInfo==0 ) return SQLITE_NOMEM; pNew->prereq = 0; pNew->rSetup = 0; @@ -125426,7 +114743,7 @@ static int whereLoopAddVirtual( if( (pTerm->eOperator & WO_IN)!=0 ){ seenIn = 1; } - if( (pTerm->prereqRight & ~mExtra)!=0 ){ + if( pTerm->prereqRight!=0 ){ seenVar = 1; }else if( (pTerm->eOperator & WO_IN)==0 ){ pIdxCons->usable = 1; @@ -125434,7 +114751,7 @@ static int whereLoopAddVirtual( break; case 1: /* Constants with IN operators */ assert( seenIn ); - pIdxCons->usable = (pTerm->prereqRight & ~mExtra)==0; + pIdxCons->usable = (pTerm->prereqRight==0); break; case 2: /* Variables without IN */ assert( seenVar ); @@ -125454,8 +114771,6 @@ static int whereLoopAddVirtual( pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; - pIdxInfo->idxFlags = 0; - pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; rc = vtabBestIndex(pParse, pTab, pIdxInfo); if( rc ) goto whereLoopAddVtab_exit; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; @@ -125501,7 +114816,6 @@ static int whereLoopAddVirtual( ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; - pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; } } } @@ -125517,14 +114831,6 @@ static int whereLoopAddVirtual( pNew->rSetup = 0; pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); - - /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated - ** that the scan will visit at most one row. Clear it otherwise. */ - if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags &= ~WHERE_ONEROW; - } whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); @@ -125544,11 +114850,7 @@ whereLoopAddVtab_exit: ** Add WhereLoop entries to handle OR terms. This works for either ** btrees or virtual tables. */ -static int whereLoopAddOr( - WhereLoopBuilder *pBuilder, - Bitmask mExtra, - Bitmask mUnusable -){ +static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){ WhereInfo *pWInfo = pBuilder->pWInfo; WhereClause *pWC; WhereLoop *pNew; @@ -125561,6 +114863,7 @@ static int whereLoopAddOr( struct SrcList_item *pItem; pWC = pBuilder->pWC; + if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; pWCEnd = pWC->a + pWC->nTerm; pNew = pBuilder->pNew; memset(&sSum, 0, sizeof(sSum)); @@ -125581,7 +114884,6 @@ static int whereLoopAddOr( sSubBuild.pOrderBy = 0; sSubBuild.pOrSet = &sCur; - WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); for(pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0 ){ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; @@ -125596,26 +114898,14 @@ static int whereLoopAddOr( continue; } sCur.n = 0; -#ifdef WHERETRACE_ENABLED - WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", - (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); - if( sqlite3WhereTrace & 0x400 ){ - for(i=0; inTerm; i++){ - whereTermPrint(&sSubBuild.pWC->a[i], i); - } - } -#endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ - rc = whereLoopAddVirtual(&sSubBuild, mExtra, mUnusable); + rc = whereLoopAddVirtual(&sSubBuild, mExtra); }else #endif { rc = whereLoopAddBtree(&sSubBuild, mExtra); } - if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(&sSubBuild, mExtra, mUnusable); - } assert( rc==SQLITE_OK || sCur.n==0 ); if( sCur.n==0 ){ sSum.n = 0; @@ -125660,7 +114950,6 @@ static int whereLoopAddOr( pNew->prereq = sSum.a[i].prereq; rc = whereLoopInsert(pBuilder, pNew); } - WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm)); } } return rc; @@ -125676,43 +114965,33 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ int iTab; SrcList *pTabList = pWInfo->pTabList; struct SrcList_item *pItem; - struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel]; sqlite3 *db = pWInfo->pParse->db; + int nTabList = pWInfo->nLevel; int rc = SQLITE_OK; + u8 priorJoinType = 0; WhereLoop *pNew; - u8 priorJointype = 0; /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); - for(iTab=0, pItem=pTabList->a; pItema; iTabiTab = iTab; - pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); - if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ - /* This condition is true when pItem is the FROM clause term on the - ** right-hand-side of a LEFT or CROSS JOIN. */ + pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor); + if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){ mExtra = mPrior; } - priorJointype = pItem->fg.jointype; + priorJoinType = pItem->jointype; if( IsVirtual(pItem->pTab) ){ - struct SrcList_item *p; - for(p=&pItem[1]; pfg.jointype & (JT_LEFT|JT_CROSS)) ){ - mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); - } - } - rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable); + rc = whereLoopAddVirtual(pBuilder, mExtra); }else{ rc = whereLoopAddBtree(pBuilder, mExtra); } if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(pBuilder, mExtra, mUnusable); + rc = whereLoopAddOr(pBuilder, mExtra); } mPrior |= pNew->maskSelf; if( rc || db->mallocFailed ) break; } - whereLoopClear(db, pNew); return rc; } @@ -125730,7 +115009,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ ** strict. With GROUP BY and DISTINCT the only requirement is that ** equivalent rows appear immediately adjacent to one another. GROUP BY ** and DISTINCT do not require rows to appear in any particular order as long -** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT +** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT ** the pOrderBy terms can be matched in any order. With ORDER BY, the ** pOrderBy terms must be matched in strict left-to-right order. */ @@ -125818,10 +115097,10 @@ static i8 wherePathSatisfiesOrderBy( pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr); if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; - pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, - ~ready, WO_EQ|WO_ISNULL|WO_IS, 0); + pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, + ~ready, WO_EQ|WO_ISNULL, 0); if( pTerm==0 ) continue; - if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ + if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){ const char *z1, *z2; pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; @@ -125830,7 +115109,6 @@ static i8 wherePathSatisfiesOrderBy( if( !pColl ) pColl = db->pDfltColl; z2 = pColl->zName; if( sqlite3StrICmp(z1, z2)!=0 ) continue; - testcase( pTerm->pExpr->op==TK_IS ); } obSat |= MASKBIT(i); } @@ -125846,9 +115124,8 @@ static i8 wherePathSatisfiesOrderBy( nKeyCol = pIndex->nKeyCol; nColumn = pIndex->nColumn; assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); - assert( pIndex->aiColumn[nColumn-1]==XN_ROWID - || !HasRowid(pIndex->pTable)); - isOrderDistinct = IsUniqueIndex(pIndex); + assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable)); + isOrderDistinct = pIndex->onError!=OE_None; } /* Loop through all columns of the index and deal with the ones @@ -125861,8 +115138,8 @@ static i8 wherePathSatisfiesOrderBy( /* Skip over == and IS NULL terms */ if( ju.btree.nEq - && pLoop->nSkip==0 - && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL|WO_IS))!=0 + && pLoop->u.btree.nSkip==0 + && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0 ){ if( i & WO_ISNULL ){ testcase( isOrderDistinct ); @@ -125879,7 +115156,7 @@ static i8 wherePathSatisfiesOrderBy( revIdx = pIndex->aSortOrder[j]; if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; }else{ - iColumn = XN_ROWID; + iColumn = -1; revIdx = 0; } @@ -125905,15 +115182,9 @@ static i8 wherePathSatisfiesOrderBy( testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( iColumn>=(-1) ){ - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; - }else{ - if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ - continue; - } - } + if( pOBExpr->op!=TK_COLUMN ) continue; + if( pOBExpr->iTable!=iCur ) continue; + if( pOBExpr->iColumn!=iColumn ) continue; if( iColumn>=0 ){ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; @@ -125922,7 +115193,7 @@ static i8 wherePathSatisfiesOrderBy( isMatch = 1; break; } - if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){ + if( isMatch && (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ @@ -125962,7 +115233,7 @@ static i8 wherePathSatisfiesOrderBy( Bitmask mTerm; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; - mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); + mTerm = exprTableUsage(&pWInfo->sMaskSet,p); if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); @@ -126023,45 +115294,6 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ } #endif -/* -** Return the cost of sorting nRow rows, assuming that the keys have -** nOrderby columns and that the first nSorted columns are already in -** order. -*/ -static LogEst whereSortingCost( - WhereInfo *pWInfo, - LogEst nRow, - int nOrderBy, - int nSorted -){ - /* TUNING: Estimated cost of a full external sort, where N is - ** the number of rows to sort is: - ** - ** cost = (3.0 * N * log(N)). - ** - ** Or, if the order-by clause has X terms but only the last Y - ** terms are out of order, then block-sorting will reduce the - ** sorting cost to: - ** - ** cost = (3.0 * N * log(N)) * (Y/X) - ** - ** The (Y/X) term is implemented using stack variable rScale - ** below. */ - LogEst rScale, rSortCost; - assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); - rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; - rSortCost = nRow + estLog(nRow) + rScale + 16; - - /* TUNING: The cost of implementing DISTINCT using a B-TREE is - ** similar but with a larger constant of proportionality. - ** Multiply by an additional factor of 3.0. */ - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - rSortCost += 16; - } - - return rSortCost; -} - /* ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine ** attempts to find the lowest cost path that visits each WhereLoop @@ -126083,8 +115315,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ int ii, jj; /* Loop counters */ int mxI = 0; /* Index of next entry to replace */ int nOrderBy; /* Number of ORDER BY clause terms */ + LogEst rCost; /* Cost of a path */ + LogEst nOut; /* Number of outputs */ LogEst mxCost = 0; /* Maximum cost of a set of paths */ - LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */ + LogEst mxOut = 0; /* Maximum nOut value on the set of paths */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aTo; /* The nTo best paths at the current level */ @@ -126092,9 +115326,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ WherePath *pTo; /* An element of aTo[] that we are working on */ WhereLoop *pWLoop; /* One of the WhereLoop objects */ WhereLoop **pX; /* Used to divy up the pSpace memory */ - LogEst *aSortCost = 0; /* Sorting and partial sorting costs */ char *pSpace; /* Temporary memory used by this routine */ - int nSpace; /* Bytes of space allocated at pSpace */ pParse = pWInfo->pParse; db = pParse->db; @@ -126104,23 +115336,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** For joins of 3 or more tables, track the 10 best paths */ mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); assert( nLoop<=pWInfo->pTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); + WHERETRACE(0x002, ("---- begin solver\n")); - /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this - ** case the purpose of this call is to estimate the number of rows returned - ** by the overall query. Once this estimate has been obtained, the caller - ** will invoke this function a second time, passing the estimate as the - ** nRowEst parameter. */ - if( pWInfo->pOrderBy==0 || nRowEst==0 ){ - nOrderBy = 0; - }else{ - nOrderBy = pWInfo->pOrderBy->nExpr; - } - - /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ - nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; - nSpace += sizeof(LogEst) * nOrderBy; - pSpace = sqlite3DbMallocRaw(db, nSpace); + /* Allocate and initialize space for aTo and aFrom */ + ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; + pSpace = sqlite3DbMallocRaw(db, ii); if( pSpace==0 ) return SQLITE_NOMEM; aTo = (WherePath*)pSpace; aFrom = aTo+mxChoice; @@ -126129,35 +115349,23 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){ pFrom->aLoop = pX; } - if( nOrderBy ){ - /* If there is an ORDER BY clause and it is not being ignored, set up - ** space for the aSortCost[] array. Each element of the aSortCost array - ** is either zero - meaning it has not yet been initialized - or the - ** cost of sorting nRowEst rows of data where the first X terms of - ** the ORDER BY clause are already in order, where X is the array - ** index. */ - aSortCost = (LogEst*)pX; - memset(aSortCost, 0, sizeof(LogEst) * nOrderBy); - } - assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] ); - assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX ); /* Seed the search with a single WherePath containing zero WhereLoops. ** - ** TUNING: Do not let the number of iterations go above 28. If the cost - ** of computing an automatic index is not paid back within the first 28 + ** TUNING: Do not let the number of iterations go above 25. If the cost + ** of computing an automatic index is not paid back within the first 25 ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) ); + aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) ); nFrom = 1; - assert( aFrom[0].isOrdered==0 ); - if( nOrderBy ){ - /* If nLoop is zero, then there are no FROM terms in the query. Since - ** in this case the query may return a maximum of one row, the results - ** are already in the requested order. Set isOrdered to nOrderBy to - ** indicate this. Or, if nLoop is greater than zero, set isOrdered to - ** -1, indicating that the result set may or may not be ordered, - ** depending on the loops added to the current plan. */ - aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy; + + /* Precompute the cost of sorting the final result set, if the caller + ** to sqlite3WhereBegin() was concerned about sorting */ + if( pWInfo->pOrderBy==0 || nRowEst==0 ){ + aFrom[0].isOrdered = 0; + nOrderBy = 0; + }else{ + aFrom[0].isOrdered = nLoop>0 ? -1 : 1; + nOrderBy = pWInfo->pOrderBy->nExpr; } /* Compute successively longer WherePaths using the previous generation @@ -126167,71 +115375,68 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ nTo = 0; for(ii=0, pFrom=aFrom; iipLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - LogEst nOut; /* Rows visited by (pFrom+pWLoop) */ - LogEst rCost; /* Cost of path (pFrom+pWLoop) */ - LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */ - i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */ - Bitmask maskNew; /* Mask of src visited by (..) */ - Bitmask revMask = 0; /* Mask of rev-order loops for (..) */ - + Bitmask maskNew; + Bitmask revMask = 0; + i8 isOrdered = pFrom->isOrdered; if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ - rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); - rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted); + rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); + rCost = sqlite3LogEstAdd(rCost, pFrom->rCost); nOut = pFrom->nRow + pWLoop->nOut; maskNew = pFrom->maskLoop | pWLoop->maskSelf; if( isOrdered<0 ){ isOrdered = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, iLoop, pWLoop, &revMask); + if( isOrdered>=0 && isOrdered0 && 66==sqlite3LogEst(100) ); + rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66; + rSortCost = nRowEst + estLog(nRowEst) + rScale + 16; + + /* TUNING: The cost of implementing DISTINCT using a B-TREE is + ** similar but with a larger constant of proportionality. + ** Multiply by an additional factor of 3.0. */ + if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ + rSortCost += 16; + } + WHERETRACE(0x002, + ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n", + rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost, + sqlite3LogEstAdd(rCost,rSortCost))); + rCost = sqlite3LogEstAdd(rCost, rSortCost); + } }else{ revMask = pFrom->revLoop; } - if( isOrdered>=0 && isOrderedisOrdered^isOrdered)&0x80)==0" is equivalent - ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range - ** of legal values for isOrdered, -1..64. - */ + /* Check to see if pWLoop should be added to the mxChoice best so far */ for(jj=0, pTo=aTo; jjmaskLoop==maskNew - && ((pTo->isOrdered^isOrdered)&0x80)==0 + && ((pTo->isOrdered^isOrdered)&80)==0 + && ((pTo->rCost<=rCost && pTo->nRow<=nOut) || + (pTo->rCost>=rCost && pTo->nRow>=nOut)) ){ testcase( jj==nTo-1 ); break; } } if( jj>=nTo ){ - /* None of the existing best-so-far paths match the candidate. */ - if( nTo>=mxChoice - && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted)) - ){ - /* The current candidate is no better than any of the mxChoice - ** paths currently in the best-so-far buffer. So discard - ** this candidate as not viable. */ + if( nTo>=mxChoice && rCost>=mxCost ){ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n", @@ -126241,8 +115446,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ #endif continue; } - /* If we reach this points it means that the new candidate path - ** needs to be added to the set of best-so-far paths. */ + /* Add a new Path to the aTo[] set */ if( nTorCostrCost==rCost && pTo->nRow<=nOut) ){ + if( pTo->rCost<=rCost && pTo->nRow<=nOut ){ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( @@ -126275,13 +115475,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); } #endif - /* Discard the candidate path from further consideration */ testcase( pTo->rCost==rCost ); continue; } testcase( pTo->rCost==rCost+1 ); - /* Control reaches here if the candidate path is better than the - ** pTo path. Replace pTo with the candidate. */ + /* A new and better score for a previously created equivalent path */ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( @@ -126299,20 +115497,17 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pTo->revLoop = revMask; pTo->nRow = nOut; pTo->rCost = rCost; - pTo->rUnsorted = rUnsorted; pTo->isOrdered = isOrdered; memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); pTo->aLoop[iLoop] = pWLoop; if( nTo>=mxChoice ){ mxI = 0; mxCost = aTo[0].rCost; - mxUnsorted = aTo[0].nRow; + mxOut = aTo[0].nRow; for(jj=1, pTo=&aTo[1]; jjrCost>mxCost - || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted) - ){ + if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){ mxCost = pTo->rCost; - mxUnsorted = pTo->rUnsorted; + mxOut = pTo->nRow; mxI = jj; } } @@ -126321,7 +115516,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } #ifdef WHERETRACE_ENABLED /* >=2 */ - if( sqlite3WhereTrace & 0x02 ){ + if( sqlite3WhereTrace>=2 ){ sqlite3DebugPrintf("---- after round %d ----\n", iLoop); for(ii=0, pTo=aTo; iirevMask = pFrom->revLoop; } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr ){ - Bitmask revMask = 0; + Bitmask notUsed = 0; int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, - pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask + pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used ); assert( pWInfo->sorted==0 ); - if( nOrder==pWInfo->pOrderBy->nExpr ){ - pWInfo->sorted = 1; - pWInfo->revMask = revMask; - } + pWInfo->sorted = (nOrder==pWInfo->pOrderBy->nExpr); } } @@ -126435,15 +115627,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ pItem = pWInfo->pTabList->a; pTab = pItem->pTab; if( IsVirtual(pTab) ) return 0; - if( pItem->fg.isIndexedBy ) return 0; + if( pItem->zIndex ) return 0; iCur = pItem->iCursor; pWC = &pWInfo->sWC; pLoop = pBuilder->pNew; pLoop->wsFlags = 0; - pLoop->nSkip = 0; - pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0); + pLoop->u.btree.nSkip = 0; + pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0); if( pTerm ){ - testcase( pTerm->eOperator & WO_IS ); pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->aLTerm[0] = pTerm; pLoop->nLTerm = 1; @@ -126452,17 +115643,15 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int opMask; assert( pLoop->aLTermSpace==pLoop->aLTerm ); - if( !IsUniqueIndex(pIdx) + assert( ArraySize(pLoop->aLTermSpace)==4 ); + if( pIdx->onError==OE_None || pIdx->pPartIdxWhere!=0 || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) ) continue; - opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ; for(j=0; jnKeyCol; j++){ - pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx); + pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); if( pTerm==0 ) break; - testcase( pTerm->eOperator & WO_IS ); pLoop->aLTerm[j] = pTerm; } if( j!=pIdx->nKeyCol ) continue; @@ -126481,7 +115670,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ if( pLoop->wsFlags ){ pLoop->nOut = (LogEst)1; pWInfo->a[0].pWLoop = pLoop; - pLoop->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); + pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur); pWInfo->a[0].iTabCur = iCur; pWInfo->nRowOut = 1; if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr; @@ -126605,12 +115794,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( int ii; /* Loop counter */ sqlite3 *db; /* Database connection */ int rc; /* Return code */ - u8 bFordelete = 0; - assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( - (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 - )); /* Variable initialization */ db = pParse->db; @@ -126666,7 +115850,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; - assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; @@ -126681,8 +115864,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); - sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); - sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); + whereClauseInit(&pWInfo->sWC, pWInfo); + whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. @@ -126706,12 +115889,14 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* Assign a bit from the bitmask to every term in the FROM clause. ** - ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally @@ -126720,18 +115905,27 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ for(ii=0; iinSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); - sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); } -#ifdef SQLITE_DEBUG - for(ii=0; iinSrc; ii++){ - Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); - assert( m==MASKBIT(ii) ); +#ifndef NDEBUG + { + Bitmask toTheLeft = 0; + for(ii=0; iinSrc; ii++){ + Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); + assert( (m-1)==toTheLeft ); + toTheLeft |= m; + } } #endif - /* Analyze all of the subexpressions. */ - sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( db->mallocFailed ) goto whereBeginError; + /* Analyze all of the subexpressions. Note that exprAnalyze() might + ** add new virtual terms onto the end of the WHERE clause. We do not + ** want to analyze these virtual terms, so start analyzing at the end + ** and work forward so that the added virtual terms are never processed. + */ + exprAnalyzeAll(pTabList, &pWInfo->sWC); + if( db->mallocFailed ){ + goto whereBeginError; + } if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ @@ -126745,27 +115939,35 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } /* Construct the WhereLoop objects */ - WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n", - wctrlFlags)); -#if defined(WHERETRACE_ENABLED) - if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ + WHERETRACE(0xffff,("*** Optimizer Start ***\n")); + /* Display all terms of the WHERE clause */ +#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN) + if( sqlite3WhereTrace & 0x100 ){ int i; + Vdbe *v = pParse->pVdbe; + sqlite3ExplainBegin(v); for(i=0; inTerm; i++){ - whereTermPrint(&sWLB.pWC->a[i], i); + sqlite3ExplainPrintf(v, "#%-2d ", i); + sqlite3ExplainPush(v); + whereExplainTerm(v, &sWLB.pWC->a[i]); + sqlite3ExplainPop(v); + sqlite3ExplainNL(v); } + sqlite3ExplainFinish(v); + sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v)); } #endif - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ + /* Display all of the WhereLoop objects if wheretrace is enabled */ +#ifdef WHERETRACE_ENABLED /* !=0 */ + if( sqlite3WhereTrace ){ WhereLoop *p; int i; - static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" - "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; + static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" + "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ p->cId = zLabel[i%sizeof(zLabel)]; whereLoopPrint(p, sWLB.pWC); @@ -126786,8 +115988,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( pParse->nErr || NEVER(db->mallocFailed) ){ goto whereBeginError; } -#ifdef WHERETRACE_ENABLED +#ifdef WHERETRACE_ENABLED /* !=0 */ if( sqlite3WhereTrace ){ + int ii; sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); @@ -126817,14 +116020,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( && pResultSet!=0 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); - if( sWLB.pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); - } + Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); + if( sWLB.pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, sWLB.pOrderBy); while( pWInfo->nLevel>=2 ){ WhereTerm *pTerm, *pEnd; pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; - if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break; + if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 && (pLoop->wsFlags & WHERE_ONEROW)==0 ){ @@ -126851,28 +116052,21 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. ** The one-pass algorithm only works if the WHERE clause constrains - ** the statement to update or delete a single row. + ** the statement to update a single row. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); - if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ - int wsFlags = pWInfo->a[0].pWLoop->wsFlags; - int bOnerow = (wsFlags & WHERE_ONEROW)!=0; - if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW) - && 0==(wsFlags & WHERE_VIRTUALTABLE) - )){ - pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; - if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ - if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ - bFordelete = OPFLAG_FORDELETE; - } - pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY); - } + if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 + && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){ + pWInfo->okOnePass = 1; + if( HasRowid(pTabList->a[0].pTab) ){ + pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; } } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ + notReady = ~(Bitmask)0; for(ii=0, pLevel=pWInfo->a; iiwsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = OP_OpenRead; - if( pWInfo->eOnePass!=ONEPASS_OFF ){ + if( pWInfo->okOnePass ){ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); - if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nColokOnePass && pTab->nCol==BMS-1 ); + testcase( !pWInfo->okOnePass && pTab->nCol==BMS ); + if( !pWInfo->okOnePass && pTab->nColcolUsed; int n = 0; for(; b; b=b>>1, n++){} @@ -126913,18 +116107,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - if( pLoop->u.btree.pIndex!=0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); - }else -#endif - { - sqlite3VdbeChangeP5(v, bFordelete); - } -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, - (const u8*)&pTabItem->colUsed, P4_INT64); -#endif }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } @@ -126941,7 +116123,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** WITHOUT ROWID table. No need for a separate index */ iIndexCur = pLevel->iTabCur; op = 0; - }else if( pWInfo->eOnePass!=ONEPASS_OFF ){ + }else if( pWInfo->okOnePass ){ Index *pJ = pTabItem->pTab->pIndex; iIndexCur = iIdxCur; assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); @@ -126953,7 +116135,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pWInfo->aiCurOnePass[1] = iIndexCur; }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){ iIndexCur = iIdxCur; - if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx; }else{ iIndexCur = pParse->nTab++; } @@ -126963,31 +116144,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( op ){ sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); - if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 - && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 - && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 - ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ - } VdbeComment((v, "%s", pIx->zName)); -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - { - u64 colUsed = 0; - int ii, jj; - for(ii=0; iinColumn; ii++){ - jj = pIx->aiColumn[ii]; - if( jj<0 ) continue; - if( jj>63 ) jj = 63; - if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue; - colUsed |= ((u64)1)<<(ii<63 ? ii : 63); - } - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0, - (u8*)&colUsed, P4_INT64); - } -#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ } } if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); + notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; @@ -126998,10 +116159,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ notReady = ~(Bitmask)0; for(ii=0; iia[ii]; - wsFlags = pLevel->pWLoop->wsFlags; #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ constructAutomaticIndex(pParse, &pWInfo->sWC, @@ -127009,15 +116167,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( db->mallocFailed ) goto whereBeginError; } #endif - addrExplain = sqlite3WhereExplainOneScan( - pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags - ); + explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); - notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); + notReady = codeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; - if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_ONETABLE_ONLY)==0 ){ - sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); - } } /* Done. */ @@ -127075,26 +116228,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } + sqlite3DbFree(db, pLevel->u.in.aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->addrSkip ){ - sqlite3VdbeGoto(v, pLevel->addrSkip); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip); VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); sqlite3VdbeJumpHere(v, pLevel->addrSkip); sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); } -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pLevel->addrLikeRep ){ - int op; - if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){ - op = OP_DecrJumpZero; - }else{ - op = OP_JumpZeroIncr; - } - sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep); - VdbeCoverage(v); - } -#endif if( pLevel->iLeftJoin ){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 @@ -127108,7 +116250,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ if( pLevel->op==OP_Return ){ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ - sqlite3VdbeGoto(v, pLevel->addrFirst); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst); } sqlite3VdbeJumpHere(v, addr); } @@ -127132,12 +116274,26 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pLoop = pLevel->pWLoop; /* For a co-routine, change all OP_Column references to the table of - ** the co-routine into OP_Copy of result contained in a register. + ** the co-routine into OP_SCopy of result contained in a register. ** OP_Rowid becomes OP_Null. */ - if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){ - translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur, - pTabItem->regResult, 0); + if( pTabItem->viaCoroutine && !db->mallocFailed ){ + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; + pOp = sqlite3VdbeGetOp(v, k); + for(; kp1!=pLevel->iTabCur ) continue; + if( pOp->opcode==OP_Column ){ + pOp->opcode = OP_Copy; + pOp->p1 = pOp->p2 + pTabItem->regResult; + pOp->p2 = pOp->p3; + pOp->p3 = 0; + }else if( pOp->opcode==OP_Rowid ){ + pOp->opcode = OP_Null; + pOp->p1 = 0; + pOp->p3 = 0; + } + } continue; } @@ -127151,7 +116307,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int ws = pLoop->wsFlags; - if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ + if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } if( (ws & WHERE_INDEXED)!=0 @@ -127178,10 +116334,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ pIdx = pLevel->u.pCovidx; } - if( pIdx - && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable)) - && !db->mallocFailed - ){ + if( pIdx && !db->mallocFailed ){ last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); @@ -127193,7 +116346,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ if( !HasRowid(pTab) ){ Index *pPk = sqlite3PrimaryKeyIndex(pTab); x = pPk->aiColumn[x]; - assert( x>=0 ); } x = sqlite3ColumnOfIndex(pIdx, x); if( x>=0 ){ @@ -127218,34 +116370,19 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ /************** End of where.c ***********************************************/ /************** Begin file parse.c *******************************************/ -/* -** 2000-05-29 +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. ** -** 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. -** -************************************************************************* -** Driver template for the LEMON parser generator. -** -** The "lemon" program processes an LALR(1) input grammar file, then uses -** this template to construct a parser. The "lemon" program inserts text -** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the -** interstitial "-" characters) contained in this template is changed into -** the value of the %name directive from the grammar. Otherwise, the content -** of this template is copied straight through into the generate parser -** source file. -** -** The following is the concatenation of all %include directives from the -** input grammar file: +** This version of "lempar.c" is modified, slightly, for use by SQLite. +** The only modifications are the addition of a couple of NEVER() +** macros to disable tests that are needed in the case of a general +** LALR(1) grammar but which are always false in the +** specific grammar used by SQLite. */ +/* First off, code is included that follows the "include" declaration +** in the input grammar file. */ /* #include */ -/************ Begin %include sections from the grammar ************************/ -/* #include "sqliteInt.h" */ /* ** Disable all error recovery processing in the parser push-down @@ -127258,18 +116395,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ */ #define yytestcase(X) testcase(X) -/* -** Indicate that sqlite3ParserFree() will never be called with a null -** pointer. -*/ -#define YYPARSEFREENEVERNULL 1 - -/* -** Alternative datatype for the argument to the malloc() routine passed -** into sqlite3ParserAlloc(). The default is size_t. -*/ -#define YYMALLOCARGTYPE u64 - /* ** An instance of this structure holds information about the ** LIMIT clause of a SELECT statement. @@ -127305,28 +116430,6 @@ struct TrigEvent { int a; IdList * b; }; struct AttachKey { int type; Token key; }; - /* - ** For a compound SELECT statement, make sure p->pPrior->pNext==p for - ** all elements in the list. And make sure list length does not exceed - ** SQLITE_LIMIT_COMPOUND_SELECT. - */ - static void parserDoubleLinkSelect(Parse *pParse, Select *p){ - if( p->pPrior ){ - Select *pNext = 0, *pLoop; - int mxSelect, cnt = 0; - for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ - pLoop->pNext = pNext; - pLoop->selFlags |= SF_Compound; - } - if( (p->selFlags & SF_MultiValue)==0 && - (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && - cnt>mxSelect - ){ - sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); - } - } - } - /* This is a utility routine used to set the ExprSpan.zStart and ** ExprSpan.zEnd values of pOut so that the span covers the complete ** range of text beginning with pStart and going to the end of pEnd. @@ -127361,13 +116464,6 @@ struct AttachKey { int type; Token key; }; pOut->zEnd = pRight->zEnd; } - /* If doNot is true, then add a TK_NOT Expr-node wrapper around the - ** outside of *ppExpr. - */ - static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){ - if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0); - } - /* Construct an expression node for a unary postfix operator */ static void spanUnaryPostfix( @@ -127386,7 +116482,7 @@ struct AttachKey { int type; Token key; }; ** unary TK_ISNULL or TK_NOTNULL expression. */ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ sqlite3 *db = pParse->db; - if( pY && pA && pY->op==TK_NULL ){ + if( db->mallocFailed==0 && pY->op==TK_NULL ){ pA->op = (u8)op; sqlite3ExprDelete(db, pA->pRight); pA->pRight = 0; @@ -127406,108 +116502,78 @@ struct AttachKey { int type; Token key; }; pOut->zStart = pPreOp->z; pOut->zEnd = pOperand->zEnd; } - - /* Add a single new term to an ExprList that is used to store a - ** list of identifiers. Report an error if the ID list contains - ** a COLLATE clause or an ASC or DESC keyword, except ignore the - ** error while parsing a legacy schema. - */ - static ExprList *parserAddExprIdListTerm( - Parse *pParse, - ExprList *pPrior, - Token *pIdToken, - int hasCollate, - int sortOrder - ){ - ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0); - if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED) - && pParse->db->init.busy==0 - ){ - sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"", - pIdToken->n, pIdToken->z); - } - sqlite3ExprListSetName(pParse, p, pIdToken, 1); - return p; - } -/**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols -** in a format understandable to "makeheaders". This section is blank unless -** "lemon" is run with the "-m" command-line option. -***************** Begin makeheaders token definitions *************************/ -/**************** End makeheaders token definitions ***************************/ - -/* The next sections is a series of control #defines. +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control ** various aspects of the generated parser. -** YYCODETYPE is the data type used to store the integer codes -** that represent terminal and non-terminal symbols. -** "unsigned char" is used if there are fewer than -** 256 symbols. Larger types otherwise. -** YYNOCODE is a number of type YYCODETYPE that is not used for -** any terminal or nonterminal symbol. +** YYCODETYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 terminals +** and nonterminals. "int" is used otherwise. +** YYNOCODE is a number of type YYCODETYPE which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. ** YYFALLBACK If defined, this indicates that one or more tokens -** (also known as: "terminal symbols") have fall-back -** values which should be used if the original symbol -** would not parse. This permits keywords to sometimes -** be used as identifiers, for example. -** YYACTIONTYPE is the data type used for "action codes" - numbers -** that indicate what to do in response to the next -** token. -** sqlite3ParserTOKENTYPE is the data type used for minor type for terminal -** symbols. Background: A "minor type" is a semantic -** value associated with a terminal or non-terminal -** symbols. For example, for an "ID" terminal symbol, -** the minor type might be the name of the identifier. -** Each non-terminal can have a different minor type. -** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal -** symbols. -** YYMINORTYPE is the data type used for all minor types. +** have fall-back values which should be used if the +** original value of the token will not parse. +** YYACTIONTYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 rules and +** states combined. "int" is used otherwise. +** sqlite3ParserTOKENTYPE is the data type used for minor tokens given +** directly to the parser from the tokenizer. +** YYMINORTYPE is the data type used for all minor tokens. ** This is typically a union of many types, one of ** which is sqlite3ParserTOKENTYPE. The entry in the union -** for terminal symbols is called "yy0". +** for base tokens is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar -** YY_MAX_SHIFT Maximum value for shift actions -** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions -** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_MIN_REDUCE Maximum value for reduce actions -** YY_ERROR_ACTION The yy_action[] code for syntax error -** YY_ACCEPT_ACTION The yy_action[] code for accept -** YY_NO_ACTION The yy_action[] code for no-op +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. */ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned char -#define YYNOCODE 253 +#define YYNOCODE 254 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 70 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - int yy4; - struct TrigEvent yy90; - ExprSpan yy118; - TriggerStep* yy203; - struct {int value; int mask;} yy215; - SrcList* yy259; - struct LimitVal yy292; - Expr* yy314; - ExprList* yy322; - struct LikeOp yy342; - IdList* yy384; - Select* yy387; - With* yy451; + Select* yy3; + ExprList* yy14; + With* yy59; + SrcList* yy65; + struct LikeOp yy96; + Expr* yy132; + u8 yy186; + int yy328; + ExprSpan yy346; + struct TrigEvent yy378; + u16 yy381; + IdList* yy408; + struct {int value; int mask;} yy429; + TriggerStep* yy473; + struct LimitVal yy476; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -127516,18 +116582,12 @@ typedef union { #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse +#define YYNSTATE 642 +#define YYNRULE 327 #define YYFALLBACK 1 -#define YYNSTATE 436 -#define YYNRULE 328 -#define YY_MAX_SHIFT 435 -#define YY_MIN_SHIFTREDUCE 649 -#define YY_MAX_SHIFTREDUCE 976 -#define YY_MIN_REDUCE 977 -#define YY_MAX_REDUCE 1304 -#define YY_ERROR_ACTION 1305 -#define YY_ACCEPT_ACTION 1306 -#define YY_NO_ACTION 1307 -/************* End control #defines *******************************************/ +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* The yyzerominor constant is used to initialize instances of ** YYMINORTYPE objects to zero. */ @@ -127554,20 +116614,16 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** Suppose the action integer is N. Then the action is determined as ** follows ** -** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** -** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then -** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. ** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE - -** N == YY_ERROR_ACTION A syntax error has occurred. +** N == YYNSTATE+YYNRULE A syntax error has occurred. ** -** N == YY_ACCEPT_ACTION The parser accepts its input. +** N == YYNSTATE+YYNRULE+1 The parser accepts its input. ** -** N == YY_NO_ACTION No such action. Denotes unused +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. @@ -127596,453 +116652,468 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. -** -*********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (1501) +*/ +#define YY_ACTTAB_COUNT (1497) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 311, 1306, 145, 651, 2, 192, 652, 338, 780, 92, - /* 10 */ 92, 92, 92, 85, 90, 90, 90, 90, 89, 89, - /* 20 */ 88, 88, 88, 87, 335, 88, 88, 88, 87, 335, - /* 30 */ 327, 856, 856, 92, 92, 92, 92, 697, 90, 90, - /* 40 */ 90, 90, 89, 89, 88, 88, 88, 87, 335, 76, - /* 50 */ 807, 74, 93, 94, 84, 868, 871, 860, 860, 91, - /* 60 */ 91, 92, 92, 92, 92, 335, 90, 90, 90, 90, - /* 70 */ 89, 89, 88, 88, 88, 87, 335, 311, 780, 90, - /* 80 */ 90, 90, 90, 89, 89, 88, 88, 88, 87, 335, - /* 90 */ 356, 808, 776, 701, 689, 689, 86, 83, 166, 257, - /* 100 */ 809, 715, 430, 86, 83, 166, 324, 697, 856, 856, - /* 110 */ 201, 158, 276, 387, 271, 386, 188, 689, 689, 828, - /* 120 */ 86, 83, 166, 269, 833, 49, 123, 87, 335, 93, - /* 130 */ 94, 84, 868, 871, 860, 860, 91, 91, 92, 92, - /* 140 */ 92, 92, 239, 90, 90, 90, 90, 89, 89, 88, - /* 150 */ 88, 88, 87, 335, 311, 763, 333, 332, 216, 408, - /* 160 */ 394, 69, 231, 393, 690, 691, 396, 910, 251, 354, - /* 170 */ 250, 288, 315, 430, 908, 430, 909, 89, 89, 88, - /* 180 */ 88, 88, 87, 335, 391, 856, 856, 690, 691, 183, - /* 190 */ 95, 123, 384, 381, 380, 833, 31, 833, 49, 912, - /* 200 */ 912, 751, 752, 379, 123, 311, 93, 94, 84, 868, - /* 210 */ 871, 860, 860, 91, 91, 92, 92, 92, 92, 114, - /* 220 */ 90, 90, 90, 90, 89, 89, 88, 88, 88, 87, - /* 230 */ 335, 430, 408, 399, 435, 657, 856, 856, 346, 57, - /* 240 */ 232, 828, 109, 704, 366, 689, 689, 363, 825, 760, - /* 250 */ 97, 749, 752, 833, 49, 708, 708, 93, 94, 84, - /* 260 */ 868, 871, 860, 860, 91, 91, 92, 92, 92, 92, - /* 270 */ 423, 90, 90, 90, 90, 89, 89, 88, 88, 88, - /* 280 */ 87, 335, 311, 114, 22, 361, 688, 58, 408, 390, - /* 290 */ 251, 349, 240, 213, 762, 689, 689, 847, 685, 115, - /* 300 */ 361, 231, 393, 689, 689, 396, 183, 689, 689, 384, - /* 310 */ 381, 380, 361, 856, 856, 690, 691, 160, 159, 223, - /* 320 */ 379, 738, 25, 806, 707, 841, 143, 689, 689, 835, - /* 330 */ 392, 339, 766, 766, 93, 94, 84, 868, 871, 860, - /* 340 */ 860, 91, 91, 92, 92, 92, 92, 914, 90, 90, - /* 350 */ 90, 90, 89, 89, 88, 88, 88, 87, 335, 311, - /* 360 */ 840, 840, 840, 266, 257, 690, 691, 778, 706, 86, - /* 370 */ 83, 166, 219, 690, 691, 737, 1, 690, 691, 689, - /* 380 */ 689, 689, 689, 430, 86, 83, 166, 249, 688, 937, - /* 390 */ 856, 856, 427, 699, 700, 828, 298, 690, 691, 221, - /* 400 */ 686, 115, 123, 944, 795, 833, 48, 342, 305, 970, - /* 410 */ 847, 93, 94, 84, 868, 871, 860, 860, 91, 91, - /* 420 */ 92, 92, 92, 92, 114, 90, 90, 90, 90, 89, - /* 430 */ 89, 88, 88, 88, 87, 335, 311, 940, 841, 679, - /* 440 */ 713, 429, 835, 430, 251, 354, 250, 355, 288, 690, - /* 450 */ 691, 690, 691, 285, 941, 340, 971, 287, 210, 23, - /* 460 */ 174, 793, 832, 430, 353, 833, 10, 856, 856, 24, - /* 470 */ 942, 151, 753, 840, 840, 840, 794, 968, 1290, 321, - /* 480 */ 398, 1290, 356, 352, 754, 833, 49, 935, 93, 94, - /* 490 */ 84, 868, 871, 860, 860, 91, 91, 92, 92, 92, - /* 500 */ 92, 430, 90, 90, 90, 90, 89, 89, 88, 88, - /* 510 */ 88, 87, 335, 311, 376, 114, 907, 705, 430, 907, - /* 520 */ 328, 890, 114, 833, 10, 966, 430, 857, 857, 320, - /* 530 */ 189, 163, 832, 165, 430, 906, 344, 323, 906, 904, - /* 540 */ 833, 10, 965, 306, 856, 856, 187, 419, 833, 10, - /* 550 */ 220, 869, 872, 832, 222, 403, 833, 49, 1219, 793, - /* 560 */ 68, 937, 406, 245, 66, 93, 94, 84, 868, 871, - /* 570 */ 860, 860, 91, 91, 92, 92, 92, 92, 861, 90, - /* 580 */ 90, 90, 90, 89, 89, 88, 88, 88, 87, 335, - /* 590 */ 311, 404, 213, 762, 834, 345, 114, 940, 902, 368, - /* 600 */ 727, 5, 316, 192, 396, 772, 780, 269, 230, 242, - /* 610 */ 771, 244, 397, 164, 941, 385, 123, 347, 55, 355, - /* 620 */ 329, 856, 856, 728, 333, 332, 688, 968, 1291, 724, - /* 630 */ 942, 1291, 413, 214, 833, 9, 362, 286, 955, 115, - /* 640 */ 718, 311, 93, 94, 84, 868, 871, 860, 860, 91, - /* 650 */ 91, 92, 92, 92, 92, 430, 90, 90, 90, 90, - /* 660 */ 89, 89, 88, 88, 88, 87, 335, 912, 912, 1300, - /* 670 */ 1300, 758, 856, 856, 325, 966, 780, 833, 35, 747, - /* 680 */ 720, 334, 699, 700, 977, 652, 338, 243, 745, 920, - /* 690 */ 920, 369, 187, 93, 94, 84, 868, 871, 860, 860, - /* 700 */ 91, 91, 92, 92, 92, 92, 114, 90, 90, 90, - /* 710 */ 90, 89, 89, 88, 88, 88, 87, 335, 311, 430, - /* 720 */ 954, 430, 112, 310, 430, 693, 317, 698, 400, 430, - /* 730 */ 793, 359, 430, 1017, 430, 192, 430, 401, 780, 430, - /* 740 */ 360, 833, 36, 833, 12, 430, 833, 27, 316, 856, - /* 750 */ 856, 833, 37, 20, 833, 38, 833, 39, 833, 28, - /* 760 */ 72, 833, 29, 663, 664, 665, 264, 833, 40, 234, - /* 770 */ 93, 94, 84, 868, 871, 860, 860, 91, 91, 92, - /* 780 */ 92, 92, 92, 430, 90, 90, 90, 90, 89, 89, - /* 790 */ 88, 88, 88, 87, 335, 311, 430, 698, 430, 917, - /* 800 */ 147, 430, 165, 916, 275, 833, 41, 430, 780, 430, - /* 810 */ 21, 430, 259, 430, 262, 274, 430, 367, 833, 42, - /* 820 */ 833, 11, 430, 833, 43, 235, 856, 856, 793, 833, - /* 830 */ 99, 833, 44, 833, 45, 833, 32, 75, 833, 46, - /* 840 */ 305, 967, 257, 257, 833, 47, 311, 93, 94, 84, - /* 850 */ 868, 871, 860, 860, 91, 91, 92, 92, 92, 92, - /* 860 */ 430, 90, 90, 90, 90, 89, 89, 88, 88, 88, - /* 870 */ 87, 335, 430, 186, 185, 184, 238, 856, 856, 650, - /* 880 */ 2, 1064, 833, 33, 739, 217, 218, 257, 971, 257, - /* 890 */ 426, 317, 257, 774, 833, 117, 257, 311, 93, 94, - /* 900 */ 84, 868, 871, 860, 860, 91, 91, 92, 92, 92, - /* 910 */ 92, 430, 90, 90, 90, 90, 89, 89, 88, 88, - /* 920 */ 88, 87, 335, 430, 318, 124, 212, 163, 856, 856, - /* 930 */ 943, 900, 898, 833, 118, 759, 726, 725, 257, 755, - /* 940 */ 289, 289, 733, 734, 961, 833, 119, 682, 311, 93, - /* 950 */ 82, 84, 868, 871, 860, 860, 91, 91, 92, 92, - /* 960 */ 92, 92, 430, 90, 90, 90, 90, 89, 89, 88, - /* 970 */ 88, 88, 87, 335, 430, 716, 246, 322, 331, 856, - /* 980 */ 856, 256, 114, 357, 833, 53, 808, 913, 913, 932, - /* 990 */ 156, 416, 420, 424, 930, 809, 833, 34, 364, 311, - /* 1000 */ 253, 94, 84, 868, 871, 860, 860, 91, 91, 92, - /* 1010 */ 92, 92, 92, 430, 90, 90, 90, 90, 89, 89, - /* 1020 */ 88, 88, 88, 87, 335, 430, 114, 114, 114, 960, - /* 1030 */ 856, 856, 307, 258, 830, 833, 100, 191, 252, 377, - /* 1040 */ 267, 68, 197, 68, 261, 716, 769, 833, 50, 71, - /* 1050 */ 911, 911, 263, 84, 868, 871, 860, 860, 91, 91, - /* 1060 */ 92, 92, 92, 92, 430, 90, 90, 90, 90, 89, - /* 1070 */ 89, 88, 88, 88, 87, 335, 80, 425, 802, 3, - /* 1080 */ 1214, 191, 430, 265, 336, 336, 833, 101, 741, 80, - /* 1090 */ 425, 897, 3, 723, 722, 428, 721, 336, 336, 430, - /* 1100 */ 893, 270, 430, 197, 833, 102, 430, 800, 428, 430, - /* 1110 */ 695, 430, 843, 111, 414, 430, 784, 409, 430, 831, - /* 1120 */ 430, 833, 98, 123, 833, 116, 847, 414, 833, 49, - /* 1130 */ 779, 833, 113, 833, 106, 226, 123, 833, 105, 847, - /* 1140 */ 833, 103, 833, 104, 791, 411, 77, 78, 290, 412, - /* 1150 */ 430, 291, 114, 79, 432, 431, 389, 430, 835, 77, - /* 1160 */ 78, 897, 839, 408, 410, 430, 79, 432, 431, 372, - /* 1170 */ 703, 835, 833, 52, 430, 80, 425, 430, 3, 833, - /* 1180 */ 54, 772, 843, 336, 336, 684, 771, 833, 51, 840, - /* 1190 */ 840, 840, 842, 19, 428, 672, 833, 26, 671, 833, - /* 1200 */ 30, 673, 840, 840, 840, 842, 19, 207, 661, 278, - /* 1210 */ 304, 148, 280, 414, 282, 248, 358, 822, 382, 6, - /* 1220 */ 348, 161, 273, 80, 425, 847, 3, 934, 895, 720, - /* 1230 */ 894, 336, 336, 296, 157, 415, 241, 284, 674, 958, - /* 1240 */ 194, 953, 428, 951, 948, 77, 78, 777, 319, 56, - /* 1250 */ 59, 135, 79, 432, 431, 121, 66, 835, 146, 128, - /* 1260 */ 350, 414, 819, 130, 351, 131, 132, 133, 375, 173, - /* 1270 */ 107, 138, 149, 847, 365, 178, 62, 70, 425, 936, - /* 1280 */ 3, 827, 889, 371, 255, 336, 336, 792, 840, 840, - /* 1290 */ 840, 842, 19, 77, 78, 915, 428, 208, 179, 144, - /* 1300 */ 79, 432, 431, 373, 260, 835, 180, 326, 675, 181, - /* 1310 */ 308, 744, 388, 743, 731, 414, 718, 742, 730, 712, - /* 1320 */ 402, 309, 711, 272, 788, 65, 710, 847, 709, 277, - /* 1330 */ 193, 789, 787, 279, 876, 73, 840, 840, 840, 842, - /* 1340 */ 19, 786, 281, 418, 283, 422, 227, 77, 78, 330, - /* 1350 */ 228, 229, 96, 767, 79, 432, 431, 407, 67, 835, - /* 1360 */ 215, 292, 293, 405, 294, 303, 302, 301, 204, 299, - /* 1370 */ 295, 202, 676, 681, 7, 433, 669, 203, 205, 206, - /* 1380 */ 125, 110, 313, 434, 667, 666, 658, 168, 224, 237, - /* 1390 */ 840, 840, 840, 842, 19, 120, 656, 337, 236, 155, - /* 1400 */ 167, 341, 233, 314, 108, 905, 903, 826, 127, 126, - /* 1410 */ 756, 170, 129, 172, 247, 928, 134, 136, 171, 60, - /* 1420 */ 61, 123, 169, 137, 933, 175, 176, 927, 8, 13, - /* 1430 */ 177, 254, 918, 139, 191, 924, 140, 370, 678, 150, - /* 1440 */ 374, 182, 274, 268, 141, 122, 63, 14, 378, 15, - /* 1450 */ 383, 64, 225, 846, 845, 874, 16, 4, 729, 765, - /* 1460 */ 770, 162, 395, 209, 211, 142, 801, 878, 796, 312, - /* 1470 */ 71, 68, 875, 873, 939, 190, 417, 938, 17, 195, - /* 1480 */ 196, 152, 18, 975, 199, 976, 153, 198, 154, 421, - /* 1490 */ 877, 844, 696, 81, 200, 297, 343, 1019, 1018, 300, - /* 1500 */ 653, + /* 0 */ 306, 212, 432, 955, 639, 191, 955, 295, 559, 88, + /* 10 */ 88, 88, 88, 81, 86, 86, 86, 86, 85, 85, + /* 20 */ 84, 84, 84, 83, 330, 185, 184, 183, 635, 635, + /* 30 */ 292, 606, 606, 88, 88, 88, 88, 683, 86, 86, + /* 40 */ 86, 86, 85, 85, 84, 84, 84, 83, 330, 16, + /* 50 */ 436, 597, 89, 90, 80, 600, 599, 601, 601, 87, + /* 60 */ 87, 88, 88, 88, 88, 684, 86, 86, 86, 86, + /* 70 */ 85, 85, 84, 84, 84, 83, 330, 306, 559, 84, + /* 80 */ 84, 84, 83, 330, 65, 86, 86, 86, 86, 85, + /* 90 */ 85, 84, 84, 84, 83, 330, 635, 635, 634, 633, + /* 100 */ 182, 682, 550, 379, 376, 375, 17, 322, 606, 606, + /* 110 */ 371, 198, 479, 91, 374, 82, 79, 165, 85, 85, + /* 120 */ 84, 84, 84, 83, 330, 598, 635, 635, 107, 89, + /* 130 */ 90, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 140 */ 88, 88, 186, 86, 86, 86, 86, 85, 85, 84, + /* 150 */ 84, 84, 83, 330, 306, 594, 594, 142, 328, 327, + /* 160 */ 484, 249, 344, 238, 635, 635, 634, 633, 585, 448, + /* 170 */ 526, 525, 229, 388, 1, 394, 450, 584, 449, 635, + /* 180 */ 635, 635, 635, 319, 395, 606, 606, 199, 157, 273, + /* 190 */ 382, 268, 381, 187, 635, 635, 634, 633, 311, 555, + /* 200 */ 266, 593, 593, 266, 347, 588, 89, 90, 80, 600, + /* 210 */ 599, 601, 601, 87, 87, 88, 88, 88, 88, 478, + /* 220 */ 86, 86, 86, 86, 85, 85, 84, 84, 84, 83, + /* 230 */ 330, 306, 272, 536, 634, 633, 146, 610, 197, 310, + /* 240 */ 575, 182, 482, 271, 379, 376, 375, 506, 21, 634, + /* 250 */ 633, 634, 633, 635, 635, 374, 611, 574, 548, 440, + /* 260 */ 111, 563, 606, 606, 634, 633, 324, 479, 608, 608, + /* 270 */ 608, 300, 435, 573, 119, 407, 210, 162, 562, 883, + /* 280 */ 592, 592, 306, 89, 90, 80, 600, 599, 601, 601, + /* 290 */ 87, 87, 88, 88, 88, 88, 506, 86, 86, 86, + /* 300 */ 86, 85, 85, 84, 84, 84, 83, 330, 620, 111, + /* 310 */ 635, 635, 361, 606, 606, 358, 249, 349, 248, 433, + /* 320 */ 243, 479, 586, 634, 633, 195, 611, 93, 119, 221, + /* 330 */ 575, 497, 534, 534, 89, 90, 80, 600, 599, 601, + /* 340 */ 601, 87, 87, 88, 88, 88, 88, 574, 86, 86, + /* 350 */ 86, 86, 85, 85, 84, 84, 84, 83, 330, 306, + /* 360 */ 77, 429, 638, 573, 589, 530, 240, 230, 242, 105, + /* 370 */ 249, 349, 248, 515, 588, 208, 460, 529, 564, 173, + /* 380 */ 634, 633, 970, 144, 430, 2, 424, 228, 380, 557, + /* 390 */ 606, 606, 190, 153, 159, 158, 514, 51, 632, 631, + /* 400 */ 630, 71, 536, 432, 954, 196, 610, 954, 614, 45, + /* 410 */ 18, 89, 90, 80, 600, 599, 601, 601, 87, 87, + /* 420 */ 88, 88, 88, 88, 261, 86, 86, 86, 86, 85, + /* 430 */ 85, 84, 84, 84, 83, 330, 306, 608, 608, 608, + /* 440 */ 542, 424, 402, 385, 241, 506, 451, 320, 211, 543, + /* 450 */ 164, 436, 386, 293, 451, 587, 108, 496, 111, 334, + /* 460 */ 391, 591, 424, 614, 27, 452, 453, 606, 606, 72, + /* 470 */ 257, 70, 259, 452, 339, 342, 564, 582, 68, 415, + /* 480 */ 469, 328, 327, 62, 614, 45, 110, 393, 89, 90, + /* 490 */ 80, 600, 599, 601, 601, 87, 87, 88, 88, 88, + /* 500 */ 88, 152, 86, 86, 86, 86, 85, 85, 84, 84, + /* 510 */ 84, 83, 330, 306, 110, 499, 520, 538, 402, 389, + /* 520 */ 424, 110, 566, 500, 593, 593, 454, 82, 79, 165, + /* 530 */ 424, 591, 384, 564, 340, 615, 188, 162, 424, 350, + /* 540 */ 616, 424, 614, 44, 606, 606, 445, 582, 300, 434, + /* 550 */ 151, 19, 614, 9, 568, 580, 348, 615, 469, 567, + /* 560 */ 614, 26, 616, 614, 45, 89, 90, 80, 600, 599, + /* 570 */ 601, 601, 87, 87, 88, 88, 88, 88, 411, 86, + /* 580 */ 86, 86, 86, 85, 85, 84, 84, 84, 83, 330, + /* 590 */ 306, 579, 110, 578, 521, 282, 433, 398, 400, 255, + /* 600 */ 486, 82, 79, 165, 487, 164, 82, 79, 165, 488, + /* 610 */ 488, 364, 387, 424, 544, 544, 509, 350, 362, 155, + /* 620 */ 191, 606, 606, 559, 642, 640, 333, 82, 79, 165, + /* 630 */ 305, 564, 507, 312, 357, 614, 45, 329, 596, 595, + /* 640 */ 194, 337, 89, 90, 80, 600, 599, 601, 601, 87, + /* 650 */ 87, 88, 88, 88, 88, 424, 86, 86, 86, 86, + /* 660 */ 85, 85, 84, 84, 84, 83, 330, 306, 20, 323, + /* 670 */ 150, 263, 211, 543, 421, 596, 595, 614, 22, 424, + /* 680 */ 193, 424, 284, 424, 391, 424, 509, 424, 577, 424, + /* 690 */ 186, 335, 424, 559, 424, 313, 120, 546, 606, 606, + /* 700 */ 67, 614, 47, 614, 50, 614, 48, 614, 100, 614, + /* 710 */ 99, 614, 101, 576, 614, 102, 614, 109, 326, 89, + /* 720 */ 90, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 730 */ 88, 88, 424, 86, 86, 86, 86, 85, 85, 84, + /* 740 */ 84, 84, 83, 330, 306, 424, 311, 424, 585, 54, + /* 750 */ 424, 516, 517, 590, 614, 112, 424, 584, 424, 572, + /* 760 */ 424, 195, 424, 571, 424, 67, 424, 614, 94, 614, + /* 770 */ 98, 424, 614, 97, 264, 606, 606, 195, 614, 46, + /* 780 */ 614, 96, 614, 30, 614, 49, 614, 115, 614, 114, + /* 790 */ 418, 229, 388, 614, 113, 306, 89, 90, 80, 600, + /* 800 */ 599, 601, 601, 87, 87, 88, 88, 88, 88, 424, + /* 810 */ 86, 86, 86, 86, 85, 85, 84, 84, 84, 83, + /* 820 */ 330, 119, 424, 590, 110, 372, 606, 606, 195, 53, + /* 830 */ 250, 614, 29, 195, 472, 438, 729, 190, 302, 498, + /* 840 */ 14, 523, 641, 2, 614, 43, 306, 89, 90, 80, + /* 850 */ 600, 599, 601, 601, 87, 87, 88, 88, 88, 88, + /* 860 */ 424, 86, 86, 86, 86, 85, 85, 84, 84, 84, + /* 870 */ 83, 330, 424, 613, 964, 964, 354, 606, 606, 420, + /* 880 */ 312, 64, 614, 42, 391, 355, 283, 437, 301, 255, + /* 890 */ 414, 410, 495, 492, 614, 28, 471, 306, 89, 90, + /* 900 */ 80, 600, 599, 601, 601, 87, 87, 88, 88, 88, + /* 910 */ 88, 424, 86, 86, 86, 86, 85, 85, 84, 84, + /* 920 */ 84, 83, 330, 424, 110, 110, 110, 110, 606, 606, + /* 930 */ 110, 254, 13, 614, 41, 532, 531, 283, 481, 531, + /* 940 */ 457, 284, 119, 561, 356, 614, 40, 284, 306, 89, + /* 950 */ 78, 80, 600, 599, 601, 601, 87, 87, 88, 88, + /* 960 */ 88, 88, 424, 86, 86, 86, 86, 85, 85, 84, + /* 970 */ 84, 84, 83, 330, 110, 424, 341, 220, 555, 606, + /* 980 */ 606, 351, 555, 318, 614, 95, 413, 255, 83, 330, + /* 990 */ 284, 284, 255, 640, 333, 356, 255, 614, 39, 306, + /* 1000 */ 356, 90, 80, 600, 599, 601, 601, 87, 87, 88, + /* 1010 */ 88, 88, 88, 424, 86, 86, 86, 86, 85, 85, + /* 1020 */ 84, 84, 84, 83, 330, 424, 317, 316, 141, 465, + /* 1030 */ 606, 606, 219, 619, 463, 614, 10, 417, 462, 255, + /* 1040 */ 189, 510, 553, 351, 207, 363, 161, 614, 38, 315, + /* 1050 */ 218, 255, 255, 80, 600, 599, 601, 601, 87, 87, + /* 1060 */ 88, 88, 88, 88, 424, 86, 86, 86, 86, 85, + /* 1070 */ 85, 84, 84, 84, 83, 330, 76, 419, 255, 3, + /* 1080 */ 878, 461, 424, 247, 331, 331, 614, 37, 217, 76, + /* 1090 */ 419, 390, 3, 216, 215, 422, 4, 331, 331, 424, + /* 1100 */ 547, 12, 424, 545, 614, 36, 424, 541, 422, 424, + /* 1110 */ 540, 424, 214, 424, 408, 424, 539, 403, 605, 605, + /* 1120 */ 237, 614, 25, 119, 614, 24, 588, 408, 614, 45, + /* 1130 */ 118, 614, 35, 614, 34, 614, 33, 614, 23, 588, + /* 1140 */ 60, 223, 603, 602, 513, 378, 73, 74, 140, 139, + /* 1150 */ 424, 110, 265, 75, 426, 425, 59, 424, 610, 73, + /* 1160 */ 74, 549, 402, 404, 424, 373, 75, 426, 425, 604, + /* 1170 */ 138, 610, 614, 11, 392, 76, 419, 181, 3, 614, + /* 1180 */ 32, 271, 369, 331, 331, 493, 614, 31, 149, 608, + /* 1190 */ 608, 608, 607, 15, 422, 365, 614, 8, 137, 489, + /* 1200 */ 136, 190, 608, 608, 608, 607, 15, 485, 176, 135, + /* 1210 */ 7, 252, 477, 408, 174, 133, 175, 474, 57, 56, + /* 1220 */ 132, 130, 119, 76, 419, 588, 3, 468, 245, 464, + /* 1230 */ 171, 331, 331, 125, 123, 456, 447, 122, 446, 104, + /* 1240 */ 336, 231, 422, 166, 154, 73, 74, 332, 116, 431, + /* 1250 */ 121, 309, 75, 426, 425, 222, 106, 610, 308, 637, + /* 1260 */ 204, 408, 629, 627, 628, 6, 200, 428, 427, 290, + /* 1270 */ 203, 622, 201, 588, 62, 63, 289, 66, 419, 399, + /* 1280 */ 3, 401, 288, 92, 143, 331, 331, 287, 608, 608, + /* 1290 */ 608, 607, 15, 73, 74, 227, 422, 325, 69, 416, + /* 1300 */ 75, 426, 425, 612, 412, 610, 192, 61, 569, 209, + /* 1310 */ 396, 226, 278, 225, 383, 408, 527, 558, 276, 533, + /* 1320 */ 552, 528, 321, 523, 370, 508, 180, 588, 494, 179, + /* 1330 */ 366, 117, 253, 269, 522, 503, 608, 608, 608, 607, + /* 1340 */ 15, 551, 502, 58, 274, 524, 178, 73, 74, 304, + /* 1350 */ 501, 368, 303, 206, 75, 426, 425, 491, 360, 610, + /* 1360 */ 213, 177, 483, 131, 345, 298, 297, 296, 202, 294, + /* 1370 */ 480, 490, 466, 134, 172, 129, 444, 346, 470, 128, + /* 1380 */ 314, 459, 103, 127, 126, 148, 124, 167, 443, 235, + /* 1390 */ 608, 608, 608, 607, 15, 442, 439, 623, 234, 299, + /* 1400 */ 145, 583, 291, 377, 581, 160, 119, 156, 270, 636, + /* 1410 */ 971, 169, 279, 626, 520, 625, 473, 624, 170, 621, + /* 1420 */ 618, 119, 168, 55, 409, 423, 537, 609, 286, 285, + /* 1430 */ 405, 570, 560, 556, 5, 52, 458, 554, 147, 267, + /* 1440 */ 519, 504, 518, 406, 262, 239, 260, 512, 343, 511, + /* 1450 */ 258, 353, 565, 256, 224, 251, 359, 277, 275, 476, + /* 1460 */ 475, 246, 352, 244, 467, 455, 236, 233, 232, 307, + /* 1470 */ 441, 281, 205, 163, 397, 280, 535, 505, 330, 617, + /* 1480 */ 971, 971, 971, 971, 367, 971, 971, 971, 971, 971, + /* 1490 */ 971, 971, 971, 971, 971, 971, 338, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 144, 145, 146, 147, 24, 1, 2, 27, 80, + /* 0 */ 19, 22, 22, 23, 1, 24, 26, 15, 27, 80, /* 10 */ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 20 */ 91, 92, 93, 94, 95, 91, 92, 93, 94, 95, - /* 30 */ 19, 50, 51, 80, 81, 82, 83, 27, 85, 86, - /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 137, - /* 50 */ 177, 139, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 81, 82, 83, 95, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 93, 94, 95, 19, 97, 85, - /* 80 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - /* 90 */ 152, 33, 212, 173, 27, 28, 223, 224, 225, 152, - /* 100 */ 42, 181, 152, 223, 224, 225, 95, 97, 50, 51, - /* 110 */ 99, 100, 101, 102, 103, 104, 105, 27, 28, 59, - /* 120 */ 223, 224, 225, 112, 174, 175, 66, 94, 95, 71, + /* 20 */ 91, 92, 93, 94, 95, 108, 109, 110, 27, 28, + /* 30 */ 23, 50, 51, 80, 81, 82, 83, 122, 85, 86, + /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 22, + /* 50 */ 70, 23, 71, 72, 73, 74, 75, 76, 77, 78, + /* 60 */ 79, 80, 81, 82, 83, 122, 85, 86, 87, 88, + /* 70 */ 89, 90, 91, 92, 93, 94, 95, 19, 97, 91, + /* 80 */ 92, 93, 94, 95, 26, 85, 86, 87, 88, 89, + /* 90 */ 90, 91, 92, 93, 94, 95, 27, 28, 97, 98, + /* 100 */ 99, 122, 211, 102, 103, 104, 79, 19, 50, 51, + /* 110 */ 19, 122, 59, 55, 113, 224, 225, 226, 89, 90, + /* 120 */ 91, 92, 93, 94, 95, 23, 27, 28, 26, 71, /* 130 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 140 */ 82, 83, 195, 85, 86, 87, 88, 89, 90, 91, - /* 150 */ 92, 93, 94, 95, 19, 197, 89, 90, 220, 209, - /* 160 */ 210, 26, 119, 120, 97, 98, 208, 100, 108, 109, - /* 170 */ 110, 152, 157, 152, 107, 152, 109, 89, 90, 91, - /* 180 */ 92, 93, 94, 95, 163, 50, 51, 97, 98, 99, - /* 190 */ 55, 66, 102, 103, 104, 174, 175, 174, 175, 132, - /* 200 */ 133, 192, 193, 113, 66, 19, 71, 72, 73, 74, - /* 210 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 198, + /* 140 */ 82, 83, 51, 85, 86, 87, 88, 89, 90, 91, + /* 150 */ 92, 93, 94, 95, 19, 132, 133, 58, 89, 90, + /* 160 */ 21, 108, 109, 110, 27, 28, 97, 98, 33, 100, + /* 170 */ 7, 8, 119, 120, 22, 19, 107, 42, 109, 27, + /* 180 */ 28, 27, 28, 95, 28, 50, 51, 99, 100, 101, + /* 190 */ 102, 103, 104, 105, 27, 28, 97, 98, 107, 152, + /* 200 */ 112, 132, 133, 112, 65, 69, 71, 72, 73, 74, + /* 210 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 11, /* 220 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - /* 230 */ 95, 152, 209, 210, 148, 149, 50, 51, 100, 53, - /* 240 */ 154, 59, 156, 174, 229, 27, 28, 232, 163, 163, - /* 250 */ 22, 192, 193, 174, 175, 27, 28, 71, 72, 73, - /* 260 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 270 */ 251, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 280 */ 94, 95, 19, 198, 198, 152, 152, 24, 209, 210, - /* 290 */ 108, 109, 110, 196, 197, 27, 28, 69, 164, 165, - /* 300 */ 152, 119, 120, 27, 28, 208, 99, 27, 28, 102, - /* 310 */ 103, 104, 152, 50, 51, 97, 98, 89, 90, 185, - /* 320 */ 113, 187, 22, 177, 174, 97, 58, 27, 28, 101, - /* 330 */ 115, 245, 117, 118, 71, 72, 73, 74, 75, 76, - /* 340 */ 77, 78, 79, 80, 81, 82, 83, 11, 85, 86, + /* 230 */ 95, 19, 101, 97, 97, 98, 24, 101, 122, 157, + /* 240 */ 12, 99, 103, 112, 102, 103, 104, 152, 22, 97, + /* 250 */ 98, 97, 98, 27, 28, 113, 27, 29, 91, 164, + /* 260 */ 165, 124, 50, 51, 97, 98, 219, 59, 132, 133, + /* 270 */ 134, 22, 23, 45, 66, 47, 212, 213, 124, 140, + /* 280 */ 132, 133, 19, 71, 72, 73, 74, 75, 76, 77, + /* 290 */ 78, 79, 80, 81, 82, 83, 152, 85, 86, 87, + /* 300 */ 88, 89, 90, 91, 92, 93, 94, 95, 164, 165, + /* 310 */ 27, 28, 230, 50, 51, 233, 108, 109, 110, 70, + /* 320 */ 16, 59, 23, 97, 98, 26, 97, 22, 66, 185, + /* 330 */ 12, 187, 27, 28, 71, 72, 73, 74, 75, 76, + /* 340 */ 77, 78, 79, 80, 81, 82, 83, 29, 85, 86, /* 350 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 19, - /* 360 */ 132, 133, 134, 23, 152, 97, 98, 91, 174, 223, - /* 370 */ 224, 225, 239, 97, 98, 187, 22, 97, 98, 27, - /* 380 */ 28, 27, 28, 152, 223, 224, 225, 239, 152, 163, - /* 390 */ 50, 51, 170, 171, 172, 59, 160, 97, 98, 239, - /* 400 */ 164, 165, 66, 242, 124, 174, 175, 195, 22, 23, - /* 410 */ 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 420 */ 80, 81, 82, 83, 198, 85, 86, 87, 88, 89, - /* 430 */ 90, 91, 92, 93, 94, 95, 19, 12, 97, 21, - /* 440 */ 23, 152, 101, 152, 108, 109, 110, 221, 152, 97, - /* 450 */ 98, 97, 98, 152, 29, 243, 70, 226, 23, 233, - /* 460 */ 26, 26, 152, 152, 238, 174, 175, 50, 51, 22, - /* 470 */ 45, 24, 47, 132, 133, 134, 124, 22, 23, 188, - /* 480 */ 163, 26, 152, 65, 59, 174, 175, 163, 71, 72, + /* 360 */ 22, 148, 149, 45, 23, 47, 62, 154, 64, 156, + /* 370 */ 108, 109, 110, 37, 69, 23, 163, 59, 26, 26, + /* 380 */ 97, 98, 144, 145, 146, 147, 152, 200, 52, 23, + /* 390 */ 50, 51, 26, 22, 89, 90, 60, 210, 7, 8, + /* 400 */ 9, 138, 97, 22, 23, 26, 101, 26, 174, 175, + /* 410 */ 197, 71, 72, 73, 74, 75, 76, 77, 78, 79, + /* 420 */ 80, 81, 82, 83, 16, 85, 86, 87, 88, 89, + /* 430 */ 90, 91, 92, 93, 94, 95, 19, 132, 133, 134, + /* 440 */ 23, 152, 208, 209, 140, 152, 152, 111, 195, 196, + /* 450 */ 98, 70, 163, 160, 152, 23, 22, 164, 165, 246, + /* 460 */ 207, 27, 152, 174, 175, 171, 172, 50, 51, 137, + /* 470 */ 62, 139, 64, 171, 172, 222, 124, 27, 138, 24, + /* 480 */ 163, 89, 90, 130, 174, 175, 197, 163, 71, 72, /* 490 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 500 */ 83, 152, 85, 86, 87, 88, 89, 90, 91, 92, - /* 510 */ 93, 94, 95, 19, 19, 198, 152, 23, 152, 152, - /* 520 */ 209, 103, 198, 174, 175, 70, 152, 50, 51, 219, - /* 530 */ 213, 214, 152, 98, 152, 171, 172, 188, 171, 172, - /* 540 */ 174, 175, 248, 249, 50, 51, 51, 251, 174, 175, - /* 550 */ 220, 74, 75, 152, 188, 152, 174, 175, 140, 124, - /* 560 */ 26, 163, 188, 16, 130, 71, 72, 73, 74, 75, - /* 570 */ 76, 77, 78, 79, 80, 81, 82, 83, 101, 85, + /* 500 */ 83, 22, 85, 86, 87, 88, 89, 90, 91, 92, + /* 510 */ 93, 94, 95, 19, 197, 181, 182, 23, 208, 209, + /* 520 */ 152, 197, 26, 189, 132, 133, 232, 224, 225, 226, + /* 530 */ 152, 97, 91, 26, 232, 116, 212, 213, 152, 222, + /* 540 */ 121, 152, 174, 175, 50, 51, 243, 97, 22, 23, + /* 550 */ 22, 234, 174, 175, 177, 23, 239, 116, 163, 177, + /* 560 */ 174, 175, 121, 174, 175, 71, 72, 73, 74, 75, + /* 570 */ 76, 77, 78, 79, 80, 81, 82, 83, 24, 85, /* 580 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - /* 590 */ 19, 209, 196, 197, 23, 231, 198, 12, 231, 219, - /* 600 */ 37, 22, 107, 24, 208, 116, 27, 112, 201, 62, - /* 610 */ 121, 64, 152, 152, 29, 52, 66, 221, 211, 221, - /* 620 */ 219, 50, 51, 60, 89, 90, 152, 22, 23, 183, - /* 630 */ 45, 26, 47, 22, 174, 175, 238, 152, 164, 165, - /* 640 */ 106, 19, 71, 72, 73, 74, 75, 76, 77, 78, + /* 590 */ 19, 23, 197, 11, 23, 227, 70, 208, 220, 152, + /* 600 */ 31, 224, 225, 226, 35, 98, 224, 225, 226, 108, + /* 610 */ 109, 110, 115, 152, 117, 118, 27, 222, 49, 123, + /* 620 */ 24, 50, 51, 27, 0, 1, 2, 224, 225, 226, + /* 630 */ 166, 124, 168, 169, 239, 174, 175, 170, 171, 172, + /* 640 */ 22, 194, 71, 72, 73, 74, 75, 76, 77, 78, /* 650 */ 79, 80, 81, 82, 83, 152, 85, 86, 87, 88, - /* 660 */ 89, 90, 91, 92, 93, 94, 95, 132, 133, 119, - /* 670 */ 120, 163, 50, 51, 111, 70, 97, 174, 175, 181, - /* 680 */ 182, 170, 171, 172, 0, 1, 2, 140, 190, 108, - /* 690 */ 109, 110, 51, 71, 72, 73, 74, 75, 76, 77, - /* 700 */ 78, 79, 80, 81, 82, 83, 198, 85, 86, 87, - /* 710 */ 88, 89, 90, 91, 92, 93, 94, 95, 19, 152, - /* 720 */ 152, 152, 22, 166, 152, 168, 169, 27, 19, 152, - /* 730 */ 26, 19, 152, 122, 152, 24, 152, 28, 27, 152, - /* 740 */ 28, 174, 175, 174, 175, 152, 174, 175, 107, 50, - /* 750 */ 51, 174, 175, 22, 174, 175, 174, 175, 174, 175, - /* 760 */ 138, 174, 175, 7, 8, 9, 16, 174, 175, 152, - /* 770 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 780 */ 81, 82, 83, 152, 85, 86, 87, 88, 89, 90, - /* 790 */ 91, 92, 93, 94, 95, 19, 152, 97, 152, 31, - /* 800 */ 24, 152, 98, 35, 101, 174, 175, 152, 97, 152, - /* 810 */ 79, 152, 62, 152, 64, 112, 152, 49, 174, 175, - /* 820 */ 174, 175, 152, 174, 175, 152, 50, 51, 124, 174, - /* 830 */ 175, 174, 175, 174, 175, 174, 175, 138, 174, 175, - /* 840 */ 22, 23, 152, 152, 174, 175, 19, 71, 72, 73, + /* 660 */ 89, 90, 91, 92, 93, 94, 95, 19, 22, 208, + /* 670 */ 24, 23, 195, 196, 170, 171, 172, 174, 175, 152, + /* 680 */ 26, 152, 152, 152, 207, 152, 97, 152, 23, 152, + /* 690 */ 51, 244, 152, 97, 152, 247, 248, 23, 50, 51, + /* 700 */ 26, 174, 175, 174, 175, 174, 175, 174, 175, 174, + /* 710 */ 175, 174, 175, 23, 174, 175, 174, 175, 188, 71, + /* 720 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 730 */ 82, 83, 152, 85, 86, 87, 88, 89, 90, 91, + /* 740 */ 92, 93, 94, 95, 19, 152, 107, 152, 33, 24, + /* 750 */ 152, 100, 101, 27, 174, 175, 152, 42, 152, 23, + /* 760 */ 152, 26, 152, 23, 152, 26, 152, 174, 175, 174, + /* 770 */ 175, 152, 174, 175, 23, 50, 51, 26, 174, 175, + /* 780 */ 174, 175, 174, 175, 174, 175, 174, 175, 174, 175, + /* 790 */ 163, 119, 120, 174, 175, 19, 71, 72, 73, 74, + /* 800 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 152, + /* 810 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 820 */ 95, 66, 152, 97, 197, 23, 50, 51, 26, 53, + /* 830 */ 23, 174, 175, 26, 23, 23, 23, 26, 26, 26, + /* 840 */ 36, 106, 146, 147, 174, 175, 19, 71, 72, 73, /* 850 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, /* 860 */ 152, 85, 86, 87, 88, 89, 90, 91, 92, 93, - /* 870 */ 94, 95, 152, 108, 109, 110, 152, 50, 51, 146, - /* 880 */ 147, 23, 174, 175, 26, 195, 195, 152, 70, 152, - /* 890 */ 168, 169, 152, 26, 174, 175, 152, 19, 71, 72, + /* 870 */ 94, 95, 152, 196, 119, 120, 19, 50, 51, 168, + /* 880 */ 169, 26, 174, 175, 207, 28, 152, 249, 250, 152, + /* 890 */ 163, 163, 163, 163, 174, 175, 163, 19, 71, 72, /* 900 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, /* 910 */ 83, 152, 85, 86, 87, 88, 89, 90, 91, 92, - /* 920 */ 93, 94, 95, 152, 246, 247, 213, 214, 50, 51, - /* 930 */ 195, 152, 195, 174, 175, 195, 100, 101, 152, 195, - /* 940 */ 152, 152, 7, 8, 152, 174, 175, 163, 19, 71, + /* 920 */ 93, 94, 95, 152, 197, 197, 197, 197, 50, 51, + /* 930 */ 197, 194, 36, 174, 175, 191, 192, 152, 191, 192, + /* 940 */ 163, 152, 66, 124, 152, 174, 175, 152, 19, 71, /* 950 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /* 960 */ 82, 83, 152, 85, 86, 87, 88, 89, 90, 91, - /* 970 */ 92, 93, 94, 95, 152, 27, 152, 189, 189, 50, - /* 980 */ 51, 195, 198, 152, 174, 175, 33, 132, 133, 152, - /* 990 */ 123, 163, 163, 163, 152, 42, 174, 175, 152, 19, + /* 970 */ 92, 93, 94, 95, 197, 152, 100, 188, 152, 50, + /* 980 */ 51, 152, 152, 188, 174, 175, 252, 152, 94, 95, + /* 990 */ 152, 152, 152, 1, 2, 152, 152, 174, 175, 19, /* 1000 */ 152, 72, 73, 74, 75, 76, 77, 78, 79, 80, /* 1010 */ 81, 82, 83, 152, 85, 86, 87, 88, 89, 90, - /* 1020 */ 91, 92, 93, 94, 95, 152, 198, 198, 198, 23, - /* 1030 */ 50, 51, 26, 152, 23, 174, 175, 26, 23, 23, - /* 1040 */ 23, 26, 26, 26, 152, 97, 23, 174, 175, 26, - /* 1050 */ 132, 133, 152, 73, 74, 75, 76, 77, 78, 79, + /* 1020 */ 91, 92, 93, 94, 95, 152, 188, 188, 22, 194, + /* 1030 */ 50, 51, 240, 173, 194, 174, 175, 252, 194, 152, + /* 1040 */ 36, 181, 28, 152, 23, 219, 122, 174, 175, 219, + /* 1050 */ 221, 152, 152, 73, 74, 75, 76, 77, 78, 79, /* 1060 */ 80, 81, 82, 83, 152, 85, 86, 87, 88, 89, - /* 1070 */ 90, 91, 92, 93, 94, 95, 19, 20, 23, 22, - /* 1080 */ 23, 26, 152, 152, 27, 28, 174, 175, 152, 19, - /* 1090 */ 20, 27, 22, 183, 183, 38, 152, 27, 28, 152, - /* 1100 */ 23, 152, 152, 26, 174, 175, 152, 152, 38, 152, - /* 1110 */ 23, 152, 27, 26, 57, 152, 215, 163, 152, 152, - /* 1120 */ 152, 174, 175, 66, 174, 175, 69, 57, 174, 175, - /* 1130 */ 152, 174, 175, 174, 175, 212, 66, 174, 175, 69, - /* 1140 */ 174, 175, 174, 175, 152, 152, 89, 90, 152, 193, - /* 1150 */ 152, 152, 198, 96, 97, 98, 91, 152, 101, 89, - /* 1160 */ 90, 97, 152, 209, 210, 152, 96, 97, 98, 235, - /* 1170 */ 152, 101, 174, 175, 152, 19, 20, 152, 22, 174, - /* 1180 */ 175, 116, 97, 27, 28, 152, 121, 174, 175, 132, - /* 1190 */ 133, 134, 135, 136, 38, 152, 174, 175, 152, 174, - /* 1200 */ 175, 152, 132, 133, 134, 135, 136, 234, 152, 212, - /* 1210 */ 150, 199, 212, 57, 212, 240, 240, 203, 178, 200, - /* 1220 */ 216, 186, 177, 19, 20, 69, 22, 203, 177, 182, - /* 1230 */ 177, 27, 28, 202, 200, 228, 216, 216, 155, 39, - /* 1240 */ 122, 159, 38, 159, 41, 89, 90, 91, 159, 241, - /* 1250 */ 241, 22, 96, 97, 98, 71, 130, 101, 222, 191, - /* 1260 */ 18, 57, 203, 194, 159, 194, 194, 194, 18, 158, - /* 1270 */ 244, 191, 222, 69, 159, 158, 137, 19, 20, 203, - /* 1280 */ 22, 191, 203, 46, 236, 27, 28, 159, 132, 133, - /* 1290 */ 134, 135, 136, 89, 90, 237, 38, 159, 158, 22, - /* 1300 */ 96, 97, 98, 179, 159, 101, 158, 48, 159, 158, - /* 1310 */ 179, 176, 107, 176, 184, 57, 106, 176, 184, 176, - /* 1320 */ 125, 179, 178, 176, 218, 107, 176, 69, 176, 217, - /* 1330 */ 159, 218, 218, 217, 159, 137, 132, 133, 134, 135, - /* 1340 */ 136, 218, 217, 179, 217, 179, 227, 89, 90, 95, - /* 1350 */ 230, 230, 129, 207, 96, 97, 98, 126, 128, 101, - /* 1360 */ 5, 206, 205, 127, 204, 10, 11, 12, 13, 14, - /* 1370 */ 203, 25, 17, 162, 26, 161, 13, 153, 153, 6, - /* 1380 */ 247, 180, 250, 151, 151, 151, 151, 32, 180, 34, - /* 1390 */ 132, 133, 134, 135, 136, 167, 4, 3, 43, 22, - /* 1400 */ 15, 68, 142, 250, 16, 23, 23, 120, 111, 131, - /* 1410 */ 20, 56, 123, 125, 16, 1, 123, 131, 63, 79, - /* 1420 */ 79, 66, 67, 111, 28, 36, 122, 1, 5, 22, - /* 1430 */ 107, 140, 54, 54, 26, 61, 107, 44, 20, 24, - /* 1440 */ 19, 105, 112, 23, 22, 40, 22, 22, 53, 22, - /* 1450 */ 53, 22, 53, 23, 23, 23, 22, 22, 30, 116, - /* 1460 */ 23, 122, 26, 23, 23, 22, 28, 11, 124, 114, - /* 1470 */ 26, 26, 23, 23, 23, 36, 24, 23, 36, 26, - /* 1480 */ 22, 22, 36, 23, 122, 23, 22, 26, 22, 24, - /* 1490 */ 23, 23, 23, 22, 122, 23, 141, 122, 122, 15, - /* 1500 */ 1, + /* 1070 */ 90, 91, 92, 93, 94, 95, 19, 20, 152, 22, + /* 1080 */ 23, 194, 152, 240, 27, 28, 174, 175, 240, 19, + /* 1090 */ 20, 26, 22, 194, 194, 38, 22, 27, 28, 152, + /* 1100 */ 23, 22, 152, 116, 174, 175, 152, 23, 38, 152, + /* 1110 */ 23, 152, 221, 152, 57, 152, 23, 163, 50, 51, + /* 1120 */ 194, 174, 175, 66, 174, 175, 69, 57, 174, 175, + /* 1130 */ 40, 174, 175, 174, 175, 174, 175, 174, 175, 69, + /* 1140 */ 22, 53, 74, 75, 30, 53, 89, 90, 22, 22, + /* 1150 */ 152, 197, 23, 96, 97, 98, 22, 152, 101, 89, + /* 1160 */ 90, 91, 208, 209, 152, 53, 96, 97, 98, 101, + /* 1170 */ 22, 101, 174, 175, 152, 19, 20, 105, 22, 174, + /* 1180 */ 175, 112, 19, 27, 28, 20, 174, 175, 24, 132, + /* 1190 */ 133, 134, 135, 136, 38, 44, 174, 175, 107, 61, + /* 1200 */ 54, 26, 132, 133, 134, 135, 136, 54, 107, 22, + /* 1210 */ 5, 140, 1, 57, 36, 111, 122, 28, 79, 79, + /* 1220 */ 131, 123, 66, 19, 20, 69, 22, 1, 16, 20, + /* 1230 */ 125, 27, 28, 123, 111, 120, 23, 131, 23, 16, + /* 1240 */ 68, 142, 38, 15, 22, 89, 90, 3, 167, 4, + /* 1250 */ 248, 251, 96, 97, 98, 180, 180, 101, 251, 151, + /* 1260 */ 6, 57, 151, 13, 151, 26, 25, 151, 161, 202, + /* 1270 */ 153, 162, 153, 69, 130, 128, 203, 19, 20, 127, + /* 1280 */ 22, 126, 204, 129, 22, 27, 28, 205, 132, 133, + /* 1290 */ 134, 135, 136, 89, 90, 231, 38, 95, 137, 179, + /* 1300 */ 96, 97, 98, 206, 179, 101, 122, 107, 159, 159, + /* 1310 */ 125, 231, 216, 228, 107, 57, 184, 217, 216, 176, + /* 1320 */ 217, 176, 48, 106, 18, 184, 158, 69, 159, 158, + /* 1330 */ 46, 71, 237, 176, 176, 176, 132, 133, 134, 135, + /* 1340 */ 136, 217, 176, 137, 216, 178, 158, 89, 90, 179, + /* 1350 */ 176, 159, 179, 159, 96, 97, 98, 159, 159, 101, + /* 1360 */ 5, 158, 202, 22, 18, 10, 11, 12, 13, 14, + /* 1370 */ 190, 238, 17, 190, 158, 193, 41, 159, 202, 193, + /* 1380 */ 159, 202, 245, 193, 193, 223, 190, 32, 159, 34, + /* 1390 */ 132, 133, 134, 135, 136, 159, 39, 155, 43, 150, + /* 1400 */ 223, 177, 201, 178, 177, 186, 66, 199, 177, 152, + /* 1410 */ 253, 56, 215, 152, 182, 152, 202, 152, 63, 152, + /* 1420 */ 152, 66, 67, 242, 229, 152, 174, 152, 152, 152, + /* 1430 */ 152, 152, 152, 152, 199, 242, 202, 152, 198, 152, + /* 1440 */ 152, 152, 183, 192, 152, 215, 152, 183, 215, 183, + /* 1450 */ 152, 241, 214, 152, 211, 152, 152, 211, 211, 152, + /* 1460 */ 152, 241, 152, 152, 152, 152, 152, 152, 152, 114, + /* 1470 */ 152, 152, 235, 152, 152, 152, 174, 187, 95, 174, + /* 1480 */ 253, 253, 253, 253, 236, 253, 253, 253, 253, 253, + /* 1490 */ 253, 253, 253, 253, 253, 253, 141, }; -#define YY_SHIFT_USE_DFLT (-89) -#define YY_SHIFT_COUNT (435) -#define YY_SHIFT_MIN (-88) -#define YY_SHIFT_MAX (1499) +#define YY_SHIFT_USE_DFLT (-86) +#define YY_SHIFT_COUNT (429) +#define YY_SHIFT_MIN (-85) +#define YY_SHIFT_MAX (1383) static const short yy_shift_ofst[] = { - /* 0 */ 5, 1057, 1355, 1070, 1204, 1204, 1204, 90, 60, -19, - /* 10 */ 58, 58, 186, 1204, 1204, 1204, 1204, 1204, 1204, 1204, - /* 20 */ 67, 67, 182, 336, 218, 550, 135, 263, 340, 417, - /* 30 */ 494, 571, 622, 699, 776, 827, 827, 827, 827, 827, - /* 40 */ 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, - /* 50 */ 878, 827, 929, 980, 980, 1156, 1204, 1204, 1204, 1204, + /* 0 */ 992, 1057, 1355, 1156, 1204, 1204, 1, 262, -19, 135, + /* 10 */ 135, 776, 1204, 1204, 1204, 1204, 69, 69, 53, 208, + /* 20 */ 283, 755, 58, 725, 648, 571, 494, 417, 340, 263, + /* 30 */ 212, 827, 827, 827, 827, 827, 827, 827, 827, 827, + /* 40 */ 827, 827, 827, 827, 827, 827, 878, 827, 929, 980, + /* 50 */ 980, 1070, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, /* 60 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, /* 70 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, - /* 80 */ 1204, 1204, 1204, 1204, 1258, 1204, 1204, 1204, 1204, 1204, - /* 90 */ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, -71, -47, - /* 100 */ -47, -47, -47, -47, -6, 88, -66, 218, 218, 418, - /* 110 */ 495, 535, 535, 33, 43, 10, -30, -89, -89, -89, - /* 120 */ 11, 425, 425, 268, 455, 605, 218, 218, 218, 218, - /* 130 */ 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, - /* 140 */ 218, 218, 218, 218, 218, 684, 138, 10, 43, 125, - /* 150 */ 125, 125, 125, 125, 125, -89, -89, -89, 228, 341, - /* 160 */ 341, 207, 276, 300, 280, 352, 354, 218, 218, 218, - /* 170 */ 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, - /* 180 */ 218, 218, 218, 218, 563, 563, 563, 218, 218, 435, - /* 190 */ 218, 218, 218, 579, 218, 218, 585, 218, 218, 218, - /* 200 */ 218, 218, 218, 218, 218, 218, 218, 581, 768, 711, - /* 210 */ 711, 711, 704, 215, 1065, 756, 434, 709, 709, 712, - /* 220 */ 434, 712, 534, 858, 641, 953, 709, -88, 953, 953, - /* 230 */ 867, 489, 447, 1200, 1118, 1118, 1203, 1203, 1118, 1229, - /* 240 */ 1184, 1126, 1242, 1242, 1242, 1242, 1118, 1250, 1126, 1229, - /* 250 */ 1184, 1184, 1126, 1118, 1250, 1139, 1237, 1118, 1118, 1250, - /* 260 */ 1277, 1118, 1250, 1118, 1250, 1277, 1205, 1205, 1205, 1259, - /* 270 */ 1277, 1205, 1210, 1205, 1259, 1205, 1205, 1195, 1218, 1195, - /* 280 */ 1218, 1195, 1218, 1195, 1218, 1118, 1118, 1198, 1277, 1254, - /* 290 */ 1254, 1277, 1223, 1231, 1230, 1236, 1126, 1346, 1348, 1363, - /* 300 */ 1363, 1373, 1373, 1373, 1373, -89, -89, -89, -89, -89, - /* 310 */ -89, 477, 547, 386, 818, 750, 765, 700, 1006, 731, - /* 320 */ 1011, 1015, 1016, 1017, 948, 836, 935, 703, 1023, 1055, - /* 330 */ 1064, 1077, 855, 918, 1087, 1085, 611, 1392, 1394, 1377, - /* 340 */ 1260, 1385, 1333, 1388, 1382, 1383, 1287, 1278, 1297, 1289, - /* 350 */ 1390, 1288, 1398, 1414, 1293, 1286, 1340, 1341, 1312, 1396, - /* 360 */ 1389, 1304, 1426, 1423, 1407, 1323, 1291, 1378, 1408, 1379, - /* 370 */ 1374, 1393, 1329, 1415, 1418, 1421, 1330, 1336, 1422, 1395, - /* 380 */ 1424, 1425, 1420, 1427, 1397, 1428, 1429, 1399, 1405, 1430, - /* 390 */ 1431, 1432, 1343, 1434, 1437, 1435, 1436, 1339, 1440, 1441, - /* 400 */ 1438, 1439, 1443, 1344, 1444, 1442, 1445, 1446, 1444, 1449, - /* 410 */ 1450, 1451, 1453, 1454, 1458, 1456, 1460, 1459, 1452, 1461, - /* 420 */ 1462, 1464, 1465, 1461, 1467, 1466, 1468, 1469, 1471, 1362, - /* 430 */ 1372, 1375, 1376, 1472, 1484, 1499, + /* 80 */ 1258, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, + /* 90 */ 1204, 1204, 1204, 1204, -71, -47, -47, -47, -47, -47, + /* 100 */ 0, 29, -12, 283, 283, 139, 91, 392, 392, 894, + /* 110 */ 672, 726, 1383, -86, -86, -86, 88, 318, 318, 99, + /* 120 */ 381, -20, 283, 283, 283, 283, 283, 283, 283, 283, + /* 130 */ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + /* 140 */ 283, 283, 283, 283, 624, 876, 726, 672, 1340, 1340, + /* 150 */ 1340, 1340, 1340, 1340, -86, -86, -86, 305, 136, 136, + /* 160 */ 142, 167, 226, 154, 137, 152, 283, 283, 283, 283, + /* 170 */ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + /* 180 */ 283, 283, 283, 336, 336, 336, 283, 283, 352, 283, + /* 190 */ 283, 283, 283, 283, 228, 283, 283, 283, 283, 283, + /* 200 */ 283, 283, 283, 283, 283, 501, 569, 596, 596, 596, + /* 210 */ 507, 497, 441, 391, 353, 156, 156, 857, 353, 857, + /* 220 */ 735, 813, 639, 715, 156, 332, 715, 715, 496, 419, + /* 230 */ 646, 1357, 1184, 1184, 1335, 1335, 1184, 1341, 1260, 1144, + /* 240 */ 1346, 1346, 1346, 1346, 1184, 1306, 1144, 1341, 1260, 1260, + /* 250 */ 1144, 1184, 1306, 1206, 1284, 1184, 1184, 1306, 1184, 1306, + /* 260 */ 1184, 1306, 1262, 1207, 1207, 1207, 1274, 1262, 1207, 1217, + /* 270 */ 1207, 1274, 1207, 1207, 1185, 1200, 1185, 1200, 1185, 1200, + /* 280 */ 1184, 1184, 1161, 1262, 1202, 1202, 1262, 1154, 1155, 1147, + /* 290 */ 1152, 1144, 1241, 1239, 1250, 1250, 1254, 1254, 1254, 1254, + /* 300 */ -86, -86, -86, -86, -86, -86, 1068, 304, 526, 249, + /* 310 */ 408, -83, 434, 812, 27, 811, 807, 802, 751, 589, + /* 320 */ 651, 163, 131, 674, 366, 450, 299, 148, 23, 102, + /* 330 */ 229, -21, 1245, 1244, 1222, 1099, 1228, 1172, 1223, 1215, + /* 340 */ 1213, 1115, 1106, 1123, 1110, 1209, 1105, 1212, 1226, 1098, + /* 350 */ 1089, 1140, 1139, 1104, 1189, 1178, 1094, 1211, 1205, 1187, + /* 360 */ 1101, 1071, 1153, 1175, 1146, 1138, 1151, 1091, 1164, 1165, + /* 370 */ 1163, 1069, 1072, 1148, 1112, 1134, 1127, 1129, 1126, 1092, + /* 380 */ 1114, 1118, 1088, 1090, 1093, 1087, 1084, 987, 1079, 1077, + /* 390 */ 1074, 1065, 924, 1021, 1014, 1004, 1006, 819, 739, 896, + /* 400 */ 855, 804, 739, 740, 736, 690, 654, 665, 618, 582, + /* 410 */ 568, 528, 554, 379, 532, 479, 455, 379, 432, 371, + /* 420 */ 341, 28, 338, 116, -11, -57, -85, 7, -8, 3, }; -#define YY_REDUCE_USE_DFLT (-144) -#define YY_REDUCE_COUNT (310) -#define YY_REDUCE_MIN (-143) -#define YY_REDUCE_MAX (1235) +#define YY_REDUCE_USE_DFLT (-110) +#define YY_REDUCE_COUNT (305) +#define YY_REDUCE_MIN (-109) +#define YY_REDUCE_MAX (1323) static const short yy_reduce_ofst[] = { - /* 0 */ -143, 954, 86, 21, -50, 23, 79, 134, 226, -120, - /* 10 */ -127, 146, 161, 291, 349, 366, 311, 382, 374, 231, - /* 20 */ 364, 367, 396, 398, 236, 317, -103, -103, -103, -103, - /* 30 */ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - /* 40 */ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - /* 50 */ -103, -103, -103, -103, -103, 460, 503, 567, 569, 572, - /* 60 */ 577, 580, 582, 584, 587, 593, 631, 644, 646, 649, - /* 70 */ 655, 657, 659, 661, 664, 670, 708, 720, 759, 771, - /* 80 */ 810, 822, 861, 873, 912, 930, 947, 950, 957, 959, - /* 90 */ 963, 966, 968, 998, 1005, 1013, 1022, 1025, -103, -103, - /* 100 */ -103, -103, -103, -103, -103, -103, -103, 474, 212, 15, - /* 110 */ 498, 222, 511, -103, 97, 557, -103, -103, -103, -103, - /* 120 */ -80, 9, 59, 19, 294, 294, -53, -62, 690, 691, - /* 130 */ 735, 737, 740, 744, 133, 310, 148, 330, 160, 380, - /* 140 */ 786, 788, 401, 296, 789, 733, 85, 722, -42, 324, - /* 150 */ 508, 784, 828, 829, 830, 678, 713, 407, 69, 150, - /* 160 */ 194, 188, 289, 301, 403, 461, 485, 568, 617, 673, - /* 170 */ 724, 779, 792, 824, 831, 837, 842, 846, 848, 881, - /* 180 */ 892, 900, 931, 936, 446, 910, 911, 944, 949, 901, - /* 190 */ 955, 967, 978, 923, 992, 993, 956, 996, 999, 1010, - /* 200 */ 289, 1018, 1033, 1043, 1046, 1049, 1056, 934, 973, 997, - /* 210 */ 1000, 1002, 901, 1012, 1019, 1060, 1014, 1004, 1020, 975, - /* 220 */ 1024, 976, 1040, 1035, 1047, 1045, 1021, 1007, 1051, 1053, - /* 230 */ 1031, 1034, 1083, 1026, 1082, 1084, 1008, 1009, 1089, 1036, - /* 240 */ 1068, 1059, 1069, 1071, 1072, 1073, 1105, 1111, 1076, 1050, - /* 250 */ 1080, 1090, 1079, 1115, 1117, 1058, 1048, 1128, 1138, 1140, - /* 260 */ 1124, 1145, 1148, 1149, 1151, 1131, 1135, 1137, 1141, 1130, - /* 270 */ 1142, 1143, 1144, 1147, 1134, 1150, 1152, 1106, 1112, 1113, - /* 280 */ 1116, 1114, 1125, 1123, 1127, 1171, 1175, 1119, 1164, 1120, - /* 290 */ 1121, 1166, 1146, 1155, 1157, 1160, 1167, 1211, 1214, 1224, - /* 300 */ 1225, 1232, 1233, 1234, 1235, 1132, 1153, 1133, 1201, 1208, - /* 310 */ 1228, + /* 0 */ 238, 954, 213, 289, 310, 234, 144, 317, -109, 382, + /* 10 */ 377, 303, 461, 389, 378, 368, 302, 294, 253, 395, + /* 20 */ 293, 324, 403, 403, 403, 403, 403, 403, 403, 403, + /* 30 */ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + /* 40 */ 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + /* 50 */ 403, 1022, 1012, 1005, 998, 963, 961, 959, 957, 950, + /* 60 */ 947, 930, 912, 873, 861, 823, 810, 771, 759, 720, + /* 70 */ 708, 670, 657, 619, 614, 612, 610, 608, 606, 604, + /* 80 */ 598, 595, 593, 580, 542, 540, 537, 535, 533, 531, + /* 90 */ 529, 527, 503, 386, 403, 403, 403, 403, 403, 403, + /* 100 */ 403, 403, 403, 95, 447, 82, 334, 504, 467, 403, + /* 110 */ 477, 464, 403, 403, 403, 403, 860, 747, 744, 785, + /* 120 */ 638, 638, 926, 891, 900, 899, 887, 844, 840, 835, + /* 130 */ 848, 830, 843, 829, 792, 839, 826, 737, 838, 795, + /* 140 */ 789, 47, 734, 530, 696, 777, 711, 677, 733, 730, + /* 150 */ 729, 728, 727, 627, 448, 64, 187, 1305, 1302, 1252, + /* 160 */ 1290, 1273, 1323, 1322, 1321, 1319, 1318, 1316, 1315, 1314, + /* 170 */ 1313, 1312, 1311, 1310, 1308, 1307, 1304, 1303, 1301, 1298, + /* 180 */ 1294, 1292, 1289, 1266, 1264, 1259, 1288, 1287, 1238, 1285, + /* 190 */ 1281, 1280, 1279, 1278, 1251, 1277, 1276, 1275, 1273, 1268, + /* 200 */ 1267, 1265, 1263, 1261, 1257, 1248, 1237, 1247, 1246, 1243, + /* 210 */ 1238, 1240, 1235, 1249, 1234, 1233, 1230, 1220, 1214, 1210, + /* 220 */ 1225, 1219, 1232, 1231, 1197, 1195, 1227, 1224, 1201, 1208, + /* 230 */ 1242, 1137, 1236, 1229, 1193, 1181, 1221, 1177, 1196, 1179, + /* 240 */ 1191, 1190, 1186, 1182, 1218, 1216, 1176, 1162, 1183, 1180, + /* 250 */ 1160, 1199, 1203, 1133, 1095, 1198, 1194, 1188, 1192, 1171, + /* 260 */ 1169, 1168, 1173, 1174, 1166, 1159, 1141, 1170, 1158, 1167, + /* 270 */ 1157, 1132, 1145, 1143, 1124, 1128, 1103, 1102, 1100, 1096, + /* 280 */ 1150, 1149, 1085, 1125, 1080, 1064, 1120, 1097, 1082, 1078, + /* 290 */ 1073, 1067, 1109, 1107, 1119, 1117, 1116, 1113, 1111, 1108, + /* 300 */ 1007, 1000, 1002, 1076, 1075, 1081, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 982, 1300, 1300, 1300, 1214, 1214, 1214, 1305, 1300, 1109, - /* 10 */ 1138, 1138, 1274, 1305, 1305, 1305, 1305, 1305, 1305, 1212, - /* 20 */ 1305, 1305, 1305, 1300, 1305, 1113, 1144, 1305, 1305, 1305, - /* 30 */ 1305, 1305, 1305, 1305, 1305, 1273, 1275, 1152, 1151, 1254, - /* 40 */ 1125, 1149, 1142, 1146, 1215, 1208, 1209, 1207, 1211, 1216, - /* 50 */ 1305, 1145, 1177, 1192, 1176, 1305, 1305, 1305, 1305, 1305, - /* 60 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 70 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 80 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 90 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1186, 1191, - /* 100 */ 1198, 1190, 1187, 1179, 1178, 1180, 1181, 1305, 1305, 1008, - /* 110 */ 1074, 1305, 1305, 1182, 1305, 1020, 1183, 1195, 1194, 1193, - /* 120 */ 1015, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 130 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 140 */ 1305, 1305, 1305, 1305, 1305, 982, 1300, 1305, 1305, 1300, - /* 150 */ 1300, 1300, 1300, 1300, 1300, 1292, 1113, 1103, 1305, 1305, - /* 160 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1280, 1278, - /* 170 */ 1305, 1227, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 180 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 190 */ 1305, 1305, 1305, 1109, 1305, 1305, 1305, 1305, 1305, 1305, - /* 200 */ 1305, 1305, 1305, 1305, 1305, 1305, 988, 1305, 1247, 1109, - /* 210 */ 1109, 1109, 1111, 1089, 1101, 990, 1148, 1127, 1127, 1259, - /* 220 */ 1148, 1259, 1045, 1068, 1042, 1138, 1127, 1210, 1138, 1138, - /* 230 */ 1110, 1101, 1305, 1285, 1118, 1118, 1277, 1277, 1118, 1157, - /* 240 */ 1078, 1148, 1085, 1085, 1085, 1085, 1118, 1005, 1148, 1157, - /* 250 */ 1078, 1078, 1148, 1118, 1005, 1253, 1251, 1118, 1118, 1005, - /* 260 */ 1220, 1118, 1005, 1118, 1005, 1220, 1076, 1076, 1076, 1060, - /* 270 */ 1220, 1076, 1045, 1076, 1060, 1076, 1076, 1131, 1126, 1131, - /* 280 */ 1126, 1131, 1126, 1131, 1126, 1118, 1118, 1305, 1220, 1224, - /* 290 */ 1224, 1220, 1143, 1132, 1141, 1139, 1148, 1011, 1063, 998, - /* 300 */ 998, 987, 987, 987, 987, 1297, 1297, 1292, 1047, 1047, - /* 310 */ 1030, 1305, 1305, 1305, 1305, 1305, 1305, 1022, 1305, 1229, - /* 320 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 330 */ 1305, 1305, 1305, 1305, 1305, 1305, 1164, 1305, 983, 1287, - /* 340 */ 1305, 1305, 1284, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 350 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 360 */ 1305, 1257, 1305, 1305, 1305, 1305, 1305, 1305, 1250, 1249, - /* 370 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 380 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, - /* 390 */ 1305, 1305, 1092, 1305, 1305, 1305, 1096, 1305, 1305, 1305, - /* 400 */ 1305, 1305, 1305, 1305, 1140, 1305, 1133, 1305, 1213, 1305, - /* 410 */ 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1305, 1302, - /* 420 */ 1305, 1305, 1305, 1301, 1305, 1305, 1305, 1305, 1305, 1166, - /* 430 */ 1305, 1165, 1169, 1305, 996, 1305, + /* 0 */ 647, 964, 964, 964, 878, 878, 969, 964, 774, 802, + /* 10 */ 802, 938, 969, 969, 969, 876, 969, 969, 969, 964, + /* 20 */ 969, 778, 808, 969, 969, 969, 969, 969, 969, 969, + /* 30 */ 969, 937, 939, 816, 815, 918, 789, 813, 806, 810, + /* 40 */ 879, 872, 873, 871, 875, 880, 969, 809, 841, 856, + /* 50 */ 840, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 60 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 70 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 80 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 90 */ 969, 969, 969, 969, 850, 855, 862, 854, 851, 843, + /* 100 */ 842, 844, 845, 969, 969, 673, 739, 969, 969, 846, + /* 110 */ 969, 685, 847, 859, 858, 857, 680, 969, 969, 969, + /* 120 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 130 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 140 */ 969, 969, 969, 969, 647, 964, 969, 969, 964, 964, + /* 150 */ 964, 964, 964, 964, 956, 778, 768, 969, 969, 969, + /* 160 */ 969, 969, 969, 969, 969, 969, 969, 944, 942, 969, + /* 170 */ 891, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 180 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 190 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 200 */ 969, 969, 969, 969, 653, 969, 911, 774, 774, 774, + /* 210 */ 776, 754, 766, 655, 812, 791, 791, 923, 812, 923, + /* 220 */ 710, 733, 707, 802, 791, 874, 802, 802, 775, 766, + /* 230 */ 969, 949, 782, 782, 941, 941, 782, 821, 743, 812, + /* 240 */ 750, 750, 750, 750, 782, 670, 812, 821, 743, 743, + /* 250 */ 812, 782, 670, 917, 915, 782, 782, 670, 782, 670, + /* 260 */ 782, 670, 884, 741, 741, 741, 725, 884, 741, 710, + /* 270 */ 741, 725, 741, 741, 795, 790, 795, 790, 795, 790, + /* 280 */ 782, 782, 969, 884, 888, 888, 884, 807, 796, 805, + /* 290 */ 803, 812, 676, 728, 663, 663, 652, 652, 652, 652, + /* 300 */ 961, 961, 956, 712, 712, 695, 969, 969, 969, 969, + /* 310 */ 969, 969, 687, 969, 893, 969, 969, 969, 969, 969, + /* 320 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 330 */ 969, 828, 969, 648, 951, 969, 969, 948, 969, 969, + /* 340 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 350 */ 969, 969, 969, 969, 969, 969, 921, 969, 969, 969, + /* 360 */ 969, 969, 969, 914, 913, 969, 969, 969, 969, 969, + /* 370 */ 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, + /* 380 */ 969, 969, 969, 969, 969, 969, 969, 757, 969, 969, + /* 390 */ 969, 761, 969, 969, 969, 969, 969, 969, 804, 969, + /* 400 */ 797, 969, 877, 969, 969, 969, 969, 969, 969, 969, + /* 410 */ 969, 969, 969, 966, 969, 969, 969, 965, 969, 969, + /* 420 */ 969, 969, 969, 830, 969, 829, 833, 969, 661, 969, + /* 430 */ 644, 649, 960, 963, 962, 959, 958, 957, 952, 950, + /* 440 */ 947, 946, 945, 943, 940, 936, 897, 895, 902, 901, + /* 450 */ 900, 899, 898, 896, 894, 892, 818, 817, 814, 811, + /* 460 */ 753, 935, 890, 752, 749, 748, 669, 953, 920, 929, + /* 470 */ 928, 927, 822, 926, 925, 924, 922, 919, 906, 820, + /* 480 */ 819, 744, 882, 881, 672, 910, 909, 908, 912, 916, + /* 490 */ 907, 784, 751, 671, 668, 675, 679, 731, 732, 740, + /* 500 */ 738, 737, 736, 735, 734, 730, 681, 686, 724, 709, + /* 510 */ 708, 717, 716, 722, 721, 720, 719, 718, 715, 714, + /* 520 */ 713, 706, 705, 711, 704, 727, 726, 723, 703, 747, + /* 530 */ 746, 745, 742, 702, 701, 700, 833, 699, 698, 838, + /* 540 */ 837, 866, 826, 755, 759, 758, 762, 763, 771, 770, + /* 550 */ 769, 780, 781, 793, 792, 824, 823, 794, 779, 773, + /* 560 */ 772, 788, 787, 786, 785, 777, 767, 799, 798, 868, + /* 570 */ 783, 867, 865, 934, 933, 932, 931, 930, 870, 967, + /* 580 */ 968, 887, 889, 886, 801, 800, 885, 869, 839, 836, + /* 590 */ 690, 691, 905, 904, 903, 693, 692, 689, 688, 863, + /* 600 */ 860, 852, 864, 861, 853, 849, 848, 834, 832, 831, + /* 610 */ 827, 835, 760, 756, 825, 765, 764, 697, 696, 694, + /* 620 */ 678, 677, 674, 667, 665, 664, 666, 662, 660, 659, + /* 630 */ 658, 657, 656, 684, 683, 682, 654, 651, 650, 646, + /* 640 */ 645, 643, }; -/********** End of lemon-generated parsing tables *****************************/ -/* The next table maps tokens (terminal symbols) into fallback tokens. -** If a construct like the following: +/* The next table maps tokens into fallback tokens. If a construct +** like the following: ** ** %fallback ID X Y Z. ** @@ -128050,10 +117121,6 @@ static const YYACTIONTYPE yy_default[] = { ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. -** -** This feature can be used, for example, to cause some keywords in a language -** to revert to identifiers if they keyword does not apply in the context where -** it appears. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { @@ -128141,13 +117208,9 @@ static const YYCODETYPE yyFallback[] = { ** + The semantic value stored at this level of the stack. This is ** the information used by the action routines in the grammar. ** It is sometimes called the "minor" token. -** -** After the "shift" half of a SHIFTREDUCE action, the stateno field -** actually contains the reduce action for the second half of the -** SHIFTREDUCE. */ struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ + YYACTIONTYPE stateno; /* The state-number */ YYCODETYPE major; /* The major token value. This is the code ** number for the token at this stack level */ YYMINORTYPE minor; /* The user-supplied minor token value. This @@ -128253,25 +117316,26 @@ static const char *const yyTokenName[] = { "column", "columnid", "type", "carglist", "typetoken", "typename", "signed", "plus_num", "minus_num", "ccons", "term", "expr", - "onconf", "sortorder", "autoinc", "eidlist_opt", + "onconf", "sortorder", "autoinc", "idxlist_opt", "refargs", "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", "conslist", "tconscomma", "tcons", - "sortlist", "eidlist", "defer_subclause_opt", "orconf", - "resolvetype", "raisetype", "ifexists", "fullname", - "selectnowith", "oneselect", "with", "multiselect_op", - "distinct", "selcollist", "from", "where_opt", - "groupby_opt", "having_opt", "orderby_opt", "limit_opt", - "values", "nexprlist", "exprlist", "sclp", - "as", "seltablist", "stl_prefix", "joinop", - "indexed_opt", "on_opt", "using_opt", "idlist", - "setlist", "insert_cmd", "idlist_opt", "likeop", - "between_op", "in_op", "case_operand", "case_exprlist", - "case_else", "uniqueflag", "collate", "nmnum", - "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event", - "foreach_clause", "when_clause", "trigger_cmd", "trnm", - "tridxby", "database_kw_opt", "key_opt", "add_column_fullname", - "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", - "vtabargtoken", "lp", "anylist", "wqlist", + "idxlist", "defer_subclause_opt", "orconf", "resolvetype", + "raisetype", "ifexists", "fullname", "selectnowith", + "oneselect", "with", "multiselect_op", "distinct", + "selcollist", "from", "where_opt", "groupby_opt", + "having_opt", "orderby_opt", "limit_opt", "values", + "nexprlist", "exprlist", "sclp", "as", + "seltablist", "stl_prefix", "joinop", "indexed_opt", + "on_opt", "using_opt", "joinop2", "idlist", + "sortlist", "setlist", "insert_cmd", "inscollist_opt", + "likeop", "between_op", "in_op", "case_operand", + "case_exprlist", "case_else", "uniqueflag", "collate", + "nmnum", "trigger_decl", "trigger_cmd_list", "trigger_time", + "trigger_event", "foreach_clause", "when_clause", "trigger_cmd", + "trnm", "tridxby", "database_kw_opt", "key_opt", + "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist", + "vtabarg", "vtabargtoken", "lp", "anylist", + "wqlist", }; #endif /* NDEBUG */ @@ -128344,7 +117408,7 @@ static const char *const yyRuleName[] = { /* 62 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", /* 63 */ "ccons ::= UNIQUE onconf", /* 64 */ "ccons ::= CHECK LP expr RP", - /* 65 */ "ccons ::= REFERENCES nm eidlist_opt refargs", + /* 65 */ "ccons ::= REFERENCES nm idxlist_opt refargs", /* 66 */ "ccons ::= defer_subclause", /* 67 */ "ccons ::= COLLATE ID|STRING", /* 68 */ "autoinc ::=", @@ -128372,10 +117436,10 @@ static const char *const yyRuleName[] = { /* 90 */ "tconscomma ::= COMMA", /* 91 */ "tconscomma ::=", /* 92 */ "tcons ::= CONSTRAINT nm", - /* 93 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", - /* 94 */ "tcons ::= UNIQUE LP sortlist RP onconf", + /* 93 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", + /* 94 */ "tcons ::= UNIQUE LP idxlist RP onconf", /* 95 */ "tcons ::= CHECK LP expr RP onconf", - /* 96 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", + /* 96 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", /* 97 */ "defer_subclause_opt ::=", /* 98 */ "defer_subclause_opt ::= defer_subclause", /* 99 */ "onconf ::=", @@ -128388,7 +117452,7 @@ static const char *const yyRuleName[] = { /* 106 */ "cmd ::= DROP TABLE ifexists fullname", /* 107 */ "ifexists ::= IF EXISTS", /* 108 */ "ifexists ::=", - /* 109 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", + /* 109 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select", /* 110 */ "cmd ::= DROP VIEW ifexists fullname", /* 111 */ "cmd ::= select", /* 112 */ "select ::= with selectnowith", @@ -128417,196 +117481,195 @@ static const char *const yyRuleName[] = { /* 135 */ "stl_prefix ::= seltablist joinop", /* 136 */ "stl_prefix ::=", /* 137 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 138 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", - /* 139 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 140 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 141 */ "dbnm ::=", - /* 142 */ "dbnm ::= DOT nm", - /* 143 */ "fullname ::= nm dbnm", - /* 144 */ "joinop ::= COMMA|JOIN", - /* 145 */ "joinop ::= JOIN_KW JOIN", - /* 146 */ "joinop ::= JOIN_KW nm JOIN", - /* 147 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 148 */ "on_opt ::= ON expr", - /* 149 */ "on_opt ::=", - /* 150 */ "indexed_opt ::=", - /* 151 */ "indexed_opt ::= INDEXED BY nm", - /* 152 */ "indexed_opt ::= NOT INDEXED", - /* 153 */ "using_opt ::= USING LP idlist RP", - /* 154 */ "using_opt ::=", - /* 155 */ "orderby_opt ::=", - /* 156 */ "orderby_opt ::= ORDER BY sortlist", - /* 157 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 158 */ "sortlist ::= expr sortorder", - /* 159 */ "sortorder ::= ASC", - /* 160 */ "sortorder ::= DESC", - /* 161 */ "sortorder ::=", - /* 162 */ "groupby_opt ::=", - /* 163 */ "groupby_opt ::= GROUP BY nexprlist", - /* 164 */ "having_opt ::=", - /* 165 */ "having_opt ::= HAVING expr", - /* 166 */ "limit_opt ::=", - /* 167 */ "limit_opt ::= LIMIT expr", - /* 168 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 169 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 170 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", - /* 171 */ "where_opt ::=", - /* 172 */ "where_opt ::= WHERE expr", - /* 173 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 174 */ "setlist ::= setlist COMMA nm EQ expr", - /* 175 */ "setlist ::= nm EQ expr", - /* 176 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 177 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 178 */ "insert_cmd ::= INSERT orconf", - /* 179 */ "insert_cmd ::= REPLACE", - /* 180 */ "idlist_opt ::=", - /* 181 */ "idlist_opt ::= LP idlist RP", - /* 182 */ "idlist ::= idlist COMMA nm", - /* 183 */ "idlist ::= nm", - /* 184 */ "expr ::= term", - /* 185 */ "expr ::= LP expr RP", - /* 186 */ "term ::= NULL", - /* 187 */ "expr ::= ID|INDEXED", - /* 188 */ "expr ::= JOIN_KW", - /* 189 */ "expr ::= nm DOT nm", - /* 190 */ "expr ::= nm DOT nm DOT nm", - /* 191 */ "term ::= INTEGER|FLOAT|BLOB", - /* 192 */ "term ::= STRING", - /* 193 */ "expr ::= VARIABLE", - /* 194 */ "expr ::= expr COLLATE ID|STRING", - /* 195 */ "expr ::= CAST LP expr AS typetoken RP", - /* 196 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 197 */ "expr ::= ID|INDEXED LP STAR RP", - /* 198 */ "term ::= CTIME_KW", - /* 199 */ "expr ::= expr AND expr", - /* 200 */ "expr ::= expr OR expr", - /* 201 */ "expr ::= expr LT|GT|GE|LE expr", - /* 202 */ "expr ::= expr EQ|NE expr", - /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 204 */ "expr ::= expr PLUS|MINUS expr", - /* 205 */ "expr ::= expr STAR|SLASH|REM expr", - /* 206 */ "expr ::= expr CONCAT expr", - /* 207 */ "likeop ::= LIKE_KW|MATCH", - /* 208 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 209 */ "expr ::= expr likeop expr", - /* 210 */ "expr ::= expr likeop expr ESCAPE expr", - /* 211 */ "expr ::= expr ISNULL|NOTNULL", - /* 212 */ "expr ::= expr NOT NULL", - /* 213 */ "expr ::= expr IS expr", - /* 214 */ "expr ::= expr IS NOT expr", - /* 215 */ "expr ::= NOT expr", - /* 216 */ "expr ::= BITNOT expr", - /* 217 */ "expr ::= MINUS expr", - /* 218 */ "expr ::= PLUS expr", - /* 219 */ "between_op ::= BETWEEN", - /* 220 */ "between_op ::= NOT BETWEEN", - /* 221 */ "expr ::= expr between_op expr AND expr", - /* 222 */ "in_op ::= IN", - /* 223 */ "in_op ::= NOT IN", - /* 224 */ "expr ::= expr in_op LP exprlist RP", - /* 225 */ "expr ::= LP select RP", - /* 226 */ "expr ::= expr in_op LP select RP", - /* 227 */ "expr ::= expr in_op nm dbnm", - /* 228 */ "expr ::= EXISTS LP select RP", - /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 231 */ "case_exprlist ::= WHEN expr THEN expr", - /* 232 */ "case_else ::= ELSE expr", - /* 233 */ "case_else ::=", - /* 234 */ "case_operand ::= expr", - /* 235 */ "case_operand ::=", - /* 236 */ "exprlist ::= nexprlist", - /* 237 */ "exprlist ::=", - /* 238 */ "nexprlist ::= nexprlist COMMA expr", - /* 239 */ "nexprlist ::= expr", - /* 240 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 241 */ "uniqueflag ::= UNIQUE", - /* 242 */ "uniqueflag ::=", - /* 243 */ "eidlist_opt ::=", - /* 244 */ "eidlist_opt ::= LP eidlist RP", - /* 245 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 246 */ "eidlist ::= nm collate sortorder", - /* 247 */ "collate ::=", - /* 248 */ "collate ::= COLLATE ID|STRING", - /* 249 */ "cmd ::= DROP INDEX ifexists fullname", - /* 250 */ "cmd ::= VACUUM", - /* 251 */ "cmd ::= VACUUM nm", - /* 252 */ "cmd ::= PRAGMA nm dbnm", - /* 253 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 254 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 255 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 256 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 257 */ "nmnum ::= plus_num", - /* 258 */ "nmnum ::= nm", - /* 259 */ "nmnum ::= ON", - /* 260 */ "nmnum ::= DELETE", - /* 261 */ "nmnum ::= DEFAULT", - /* 262 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 263 */ "plus_num ::= INTEGER|FLOAT", - /* 264 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 265 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 266 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 267 */ "trigger_time ::= BEFORE", - /* 268 */ "trigger_time ::= AFTER", - /* 269 */ "trigger_time ::= INSTEAD OF", - /* 270 */ "trigger_time ::=", - /* 271 */ "trigger_event ::= DELETE|INSERT", - /* 272 */ "trigger_event ::= UPDATE", - /* 273 */ "trigger_event ::= UPDATE OF idlist", - /* 274 */ "foreach_clause ::=", - /* 275 */ "foreach_clause ::= FOR EACH ROW", - /* 276 */ "when_clause ::=", - /* 277 */ "when_clause ::= WHEN expr", - /* 278 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 279 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 280 */ "trnm ::= nm", - /* 281 */ "trnm ::= nm DOT nm", - /* 282 */ "tridxby ::=", - /* 283 */ "tridxby ::= INDEXED BY nm", - /* 284 */ "tridxby ::= NOT INDEXED", - /* 285 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 286 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 287 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 288 */ "trigger_cmd ::= select", - /* 289 */ "expr ::= RAISE LP IGNORE RP", - /* 290 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 291 */ "raisetype ::= ROLLBACK", - /* 292 */ "raisetype ::= ABORT", - /* 293 */ "raisetype ::= FAIL", - /* 294 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 295 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 296 */ "cmd ::= DETACH database_kw_opt expr", - /* 297 */ "key_opt ::=", - /* 298 */ "key_opt ::= KEY expr", - /* 299 */ "database_kw_opt ::= DATABASE", - /* 300 */ "database_kw_opt ::=", - /* 301 */ "cmd ::= REINDEX", - /* 302 */ "cmd ::= REINDEX nm dbnm", - /* 303 */ "cmd ::= ANALYZE", - /* 304 */ "cmd ::= ANALYZE nm dbnm", - /* 305 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 306 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 307 */ "add_column_fullname ::= fullname", - /* 308 */ "kwcolumn_opt ::=", - /* 309 */ "kwcolumn_opt ::= COLUMNKW", - /* 310 */ "cmd ::= create_vtab", - /* 311 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 312 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 313 */ "vtabarglist ::= vtabarg", - /* 314 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 315 */ "vtabarg ::=", - /* 316 */ "vtabarg ::= vtabarg vtabargtoken", - /* 317 */ "vtabargtoken ::= ANY", - /* 318 */ "vtabargtoken ::= lp anylist RP", - /* 319 */ "lp ::= LP", - /* 320 */ "anylist ::=", - /* 321 */ "anylist ::= anylist LP anylist RP", - /* 322 */ "anylist ::= anylist ANY", - /* 323 */ "with ::=", - /* 324 */ "with ::= WITH wqlist", - /* 325 */ "with ::= WITH RECURSIVE wqlist", - /* 326 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 327 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 138 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 139 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 140 */ "dbnm ::=", + /* 141 */ "dbnm ::= DOT nm", + /* 142 */ "fullname ::= nm dbnm", + /* 143 */ "joinop ::= COMMA|JOIN", + /* 144 */ "joinop ::= JOIN_KW JOIN", + /* 145 */ "joinop ::= JOIN_KW nm JOIN", + /* 146 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 147 */ "on_opt ::= ON expr", + /* 148 */ "on_opt ::=", + /* 149 */ "indexed_opt ::=", + /* 150 */ "indexed_opt ::= INDEXED BY nm", + /* 151 */ "indexed_opt ::= NOT INDEXED", + /* 152 */ "using_opt ::= USING LP idlist RP", + /* 153 */ "using_opt ::=", + /* 154 */ "orderby_opt ::=", + /* 155 */ "orderby_opt ::= ORDER BY sortlist", + /* 156 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 157 */ "sortlist ::= expr sortorder", + /* 158 */ "sortorder ::= ASC", + /* 159 */ "sortorder ::= DESC", + /* 160 */ "sortorder ::=", + /* 161 */ "groupby_opt ::=", + /* 162 */ "groupby_opt ::= GROUP BY nexprlist", + /* 163 */ "having_opt ::=", + /* 164 */ "having_opt ::= HAVING expr", + /* 165 */ "limit_opt ::=", + /* 166 */ "limit_opt ::= LIMIT expr", + /* 167 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 168 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 169 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", + /* 170 */ "where_opt ::=", + /* 171 */ "where_opt ::= WHERE expr", + /* 172 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 173 */ "setlist ::= setlist COMMA nm EQ expr", + /* 174 */ "setlist ::= nm EQ expr", + /* 175 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt select", + /* 176 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", + /* 177 */ "insert_cmd ::= INSERT orconf", + /* 178 */ "insert_cmd ::= REPLACE", + /* 179 */ "inscollist_opt ::=", + /* 180 */ "inscollist_opt ::= LP idlist RP", + /* 181 */ "idlist ::= idlist COMMA nm", + /* 182 */ "idlist ::= nm", + /* 183 */ "expr ::= term", + /* 184 */ "expr ::= LP expr RP", + /* 185 */ "term ::= NULL", + /* 186 */ "expr ::= ID|INDEXED", + /* 187 */ "expr ::= JOIN_KW", + /* 188 */ "expr ::= nm DOT nm", + /* 189 */ "expr ::= nm DOT nm DOT nm", + /* 190 */ "term ::= INTEGER|FLOAT|BLOB", + /* 191 */ "term ::= STRING", + /* 192 */ "expr ::= VARIABLE", + /* 193 */ "expr ::= expr COLLATE ID|STRING", + /* 194 */ "expr ::= CAST LP expr AS typetoken RP", + /* 195 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 196 */ "expr ::= ID|INDEXED LP STAR RP", + /* 197 */ "term ::= CTIME_KW", + /* 198 */ "expr ::= expr AND expr", + /* 199 */ "expr ::= expr OR expr", + /* 200 */ "expr ::= expr LT|GT|GE|LE expr", + /* 201 */ "expr ::= expr EQ|NE expr", + /* 202 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 203 */ "expr ::= expr PLUS|MINUS expr", + /* 204 */ "expr ::= expr STAR|SLASH|REM expr", + /* 205 */ "expr ::= expr CONCAT expr", + /* 206 */ "likeop ::= LIKE_KW|MATCH", + /* 207 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 208 */ "expr ::= expr likeop expr", + /* 209 */ "expr ::= expr likeop expr ESCAPE expr", + /* 210 */ "expr ::= expr ISNULL|NOTNULL", + /* 211 */ "expr ::= expr NOT NULL", + /* 212 */ "expr ::= expr IS expr", + /* 213 */ "expr ::= expr IS NOT expr", + /* 214 */ "expr ::= NOT expr", + /* 215 */ "expr ::= BITNOT expr", + /* 216 */ "expr ::= MINUS expr", + /* 217 */ "expr ::= PLUS expr", + /* 218 */ "between_op ::= BETWEEN", + /* 219 */ "between_op ::= NOT BETWEEN", + /* 220 */ "expr ::= expr between_op expr AND expr", + /* 221 */ "in_op ::= IN", + /* 222 */ "in_op ::= NOT IN", + /* 223 */ "expr ::= expr in_op LP exprlist RP", + /* 224 */ "expr ::= LP select RP", + /* 225 */ "expr ::= expr in_op LP select RP", + /* 226 */ "expr ::= expr in_op nm dbnm", + /* 227 */ "expr ::= EXISTS LP select RP", + /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 230 */ "case_exprlist ::= WHEN expr THEN expr", + /* 231 */ "case_else ::= ELSE expr", + /* 232 */ "case_else ::=", + /* 233 */ "case_operand ::= expr", + /* 234 */ "case_operand ::=", + /* 235 */ "exprlist ::= nexprlist", + /* 236 */ "exprlist ::=", + /* 237 */ "nexprlist ::= nexprlist COMMA expr", + /* 238 */ "nexprlist ::= expr", + /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt", + /* 240 */ "uniqueflag ::= UNIQUE", + /* 241 */ "uniqueflag ::=", + /* 242 */ "idxlist_opt ::=", + /* 243 */ "idxlist_opt ::= LP idxlist RP", + /* 244 */ "idxlist ::= idxlist COMMA nm collate sortorder", + /* 245 */ "idxlist ::= nm collate sortorder", + /* 246 */ "collate ::=", + /* 247 */ "collate ::= COLLATE ID|STRING", + /* 248 */ "cmd ::= DROP INDEX ifexists fullname", + /* 249 */ "cmd ::= VACUUM", + /* 250 */ "cmd ::= VACUUM nm", + /* 251 */ "cmd ::= PRAGMA nm dbnm", + /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 256 */ "nmnum ::= plus_num", + /* 257 */ "nmnum ::= nm", + /* 258 */ "nmnum ::= ON", + /* 259 */ "nmnum ::= DELETE", + /* 260 */ "nmnum ::= DEFAULT", + /* 261 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 262 */ "plus_num ::= INTEGER|FLOAT", + /* 263 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 264 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 265 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 266 */ "trigger_time ::= BEFORE", + /* 267 */ "trigger_time ::= AFTER", + /* 268 */ "trigger_time ::= INSTEAD OF", + /* 269 */ "trigger_time ::=", + /* 270 */ "trigger_event ::= DELETE|INSERT", + /* 271 */ "trigger_event ::= UPDATE", + /* 272 */ "trigger_event ::= UPDATE OF idlist", + /* 273 */ "foreach_clause ::=", + /* 274 */ "foreach_clause ::= FOR EACH ROW", + /* 275 */ "when_clause ::=", + /* 276 */ "when_clause ::= WHEN expr", + /* 277 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 278 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 279 */ "trnm ::= nm", + /* 280 */ "trnm ::= nm DOT nm", + /* 281 */ "tridxby ::=", + /* 282 */ "tridxby ::= INDEXED BY nm", + /* 283 */ "tridxby ::= NOT INDEXED", + /* 284 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 285 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", + /* 286 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 287 */ "trigger_cmd ::= select", + /* 288 */ "expr ::= RAISE LP IGNORE RP", + /* 289 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 290 */ "raisetype ::= ROLLBACK", + /* 291 */ "raisetype ::= ABORT", + /* 292 */ "raisetype ::= FAIL", + /* 293 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 294 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 295 */ "cmd ::= DETACH database_kw_opt expr", + /* 296 */ "key_opt ::=", + /* 297 */ "key_opt ::= KEY expr", + /* 298 */ "database_kw_opt ::= DATABASE", + /* 299 */ "database_kw_opt ::=", + /* 300 */ "cmd ::= REINDEX", + /* 301 */ "cmd ::= REINDEX nm dbnm", + /* 302 */ "cmd ::= ANALYZE", + /* 303 */ "cmd ::= ANALYZE nm dbnm", + /* 304 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 305 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 306 */ "add_column_fullname ::= fullname", + /* 307 */ "kwcolumn_opt ::=", + /* 308 */ "kwcolumn_opt ::= COLUMNKW", + /* 309 */ "cmd ::= create_vtab", + /* 310 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 311 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 312 */ "vtabarglist ::= vtabarg", + /* 313 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 314 */ "vtabarg ::=", + /* 315 */ "vtabarg ::= vtabarg vtabargtoken", + /* 316 */ "vtabargtoken ::= ANY", + /* 317 */ "vtabargtoken ::= lp anylist RP", + /* 318 */ "lp ::= LP", + /* 319 */ "anylist ::=", + /* 320 */ "anylist ::= anylist LP anylist RP", + /* 321 */ "anylist ::= anylist ANY", + /* 322 */ "with ::=", + /* 323 */ "with ::= WITH wqlist", + /* 324 */ "with ::= WITH RECURSIVE wqlist", + /* 325 */ "wqlist ::= nm idxlist_opt AS LP select RP", + /* 326 */ "wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP", }; #endif /* NDEBUG */ @@ -128634,15 +117697,6 @@ static void yyGrowStack(yyParser *p){ } #endif -/* Datatype of the argument to the memory allocated passed as the -** second argument to sqlite3ParserAlloc() below. This can be changed by -** putting an appropriate #define in the %include section of the input -** grammar. -*/ -#ifndef YYMALLOCARGTYPE -# define YYMALLOCARGTYPE size_t -#endif - /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like @@ -128655,9 +117709,9 @@ static void yyGrowStack(yyParser *p){ ** A pointer to a parser. This pointer is used in subsequent calls ** to sqlite3Parser and sqlite3ParserFree. */ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ +SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){ yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH @@ -128672,12 +117726,10 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ return pParser; } -/* The following function deletes the "minor type" or semantic value -** associated with a symbol. The symbol can be either a terminal -** or nonterminal. "yymajor" is the symbol code, and "yypminor" is -** a pointer to the value to be deleted. The code used to do the -** deletions is derived from the %destructor and/or %token_destructor -** directives of the input grammar. +/* The following function deletes the value associated with a +** symbol. The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. */ static void yy_destructor( yyParser *yypParser, /* The parser */ @@ -128693,83 +117745,81 @@ static void yy_destructor( ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are *not* used + ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ -/********* Begin destructor definitions ***************************************/ case 163: /* select */ - case 196: /* selectnowith */ - case 197: /* oneselect */ - case 208: /* values */ + case 195: /* selectnowith */ + case 196: /* oneselect */ + case 207: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy387)); +sqlite3SelectDelete(pParse->db, (yypminor->yy3)); } break; case 174: /* term */ case 175: /* expr */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy118).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy346).pExpr); } break; - case 179: /* eidlist_opt */ - case 188: /* sortlist */ - case 189: /* eidlist */ - case 201: /* selcollist */ - case 204: /* groupby_opt */ - case 206: /* orderby_opt */ - case 209: /* nexprlist */ - case 210: /* exprlist */ - case 211: /* sclp */ - case 220: /* setlist */ - case 227: /* case_exprlist */ + case 179: /* idxlist_opt */ + case 188: /* idxlist */ + case 200: /* selcollist */ + case 203: /* groupby_opt */ + case 205: /* orderby_opt */ + case 208: /* nexprlist */ + case 209: /* exprlist */ + case 210: /* sclp */ + case 220: /* sortlist */ + case 221: /* setlist */ + case 228: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); } break; - case 195: /* fullname */ - case 202: /* from */ - case 213: /* seltablist */ - case 214: /* stl_prefix */ + case 194: /* fullname */ + case 201: /* from */ + case 212: /* seltablist */ + case 213: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy259)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy65)); } break; - case 198: /* with */ - case 251: /* wqlist */ + case 197: /* with */ + case 252: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy451)); +sqlite3WithDelete(pParse->db, (yypminor->yy59)); } break; - case 203: /* where_opt */ - case 205: /* having_opt */ - case 217: /* on_opt */ - case 226: /* case_operand */ - case 228: /* case_else */ - case 237: /* when_clause */ - case 242: /* key_opt */ + case 202: /* where_opt */ + case 204: /* having_opt */ + case 216: /* on_opt */ + case 227: /* case_operand */ + case 229: /* case_else */ + case 238: /* when_clause */ + case 243: /* key_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy314)); +sqlite3ExprDelete(pParse->db, (yypminor->yy132)); } break; - case 218: /* using_opt */ + case 217: /* using_opt */ case 219: /* idlist */ - case 222: /* idlist_opt */ + case 223: /* inscollist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy384)); +sqlite3IdListDelete(pParse->db, (yypminor->yy408)); } break; - case 233: /* trigger_cmd_list */ - case 238: /* trigger_cmd */ + case 234: /* trigger_cmd_list */ + case 239: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy473)); } break; - case 235: /* trigger_event */ + case 236: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy378).b); } break; -/********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } } @@ -128779,37 +117829,49 @@ sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. */ -static void yy_pop_parser_stack(yyParser *pParser){ - yyStackEntry *yytos; - assert( pParser->yyidx>=0 ); - yytos = &pParser->yystack[pParser->yyidx--]; +static int yy_pop_parser_stack(yyParser *pParser){ + YYCODETYPE yymajor; + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + + /* There is no mechanism by which the parser stack can be popped below + ** empty in SQLite. */ + if( NEVER(pParser->yyidx<0) ) return 0; #ifndef NDEBUG - if( yyTraceFILE ){ + if( yyTraceFILE && pParser->yyidx>=0 ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif - yy_destructor(pParser, yytos->major, &yytos->minor); + yymajor = yytos->major; + yy_destructor(pParser, yymajor, &yytos->minor); + pParser->yyidx--; + return yymajor; } /* -** Deallocate and destroy a parser. Destructors are called for +** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** -** If the YYPARSEFREENEVERNULL macro exists (for example because it -** is defined in a %include section of the input grammar) then it is -** assumed that the input pointer is never NULL. +** Inputs: +**
      +**
    • A pointer to the parser. This should be a pointer +** obtained from sqlite3ParserAlloc. +**
    • A pointer to a function used to reclaim memory obtained +** from malloc. +**
    */ SQLITE_PRIVATE void sqlite3ParserFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; -#ifndef YYPARSEFREENEVERNULL - if( pParser==0 ) return; -#endif + /* In SQLite, we never try to destroy a parser that was not successfully + ** created in the first place. */ + if( NEVER(pParser==0) ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 free(pParser->yystack); @@ -128830,6 +117892,10 @@ SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){ /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ @@ -128838,64 +117904,63 @@ static int yy_find_shift_action( int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - if( stateno>=YY_MIN_REDUCE ) return stateno; - assert( stateno <= YY_SHIFT_COUNT ); - do{ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ + if( stateno>YY_SHIFT_COUNT + || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ + return yy_default[stateno]; + } + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } +#endif + return yy_find_shift_action(pParser, iFallback); + } #endif #ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( + { + int j = i - iLookAhead + YYWILDCARD; + if( #if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* YYWILDCARD */ } - return yy_default[stateno]; - }else{ - return yy_action[i]; +#endif /* YYWILDCARD */ } - }while(1); + return yy_default[stateno]; + }else{ + return yy_action[i]; + } } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. */ static int yy_find_reduce_action( int stateno, /* Current state number */ @@ -128938,34 +118003,12 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ -/******** Begin %stack_overflow code ******************************************/ UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */ sqlite3ErrorMsg(pParse, "parser stack overflow"); -/******** End %stack_overflow code ********************************************/ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ } -/* -** Print tracing information for a SHIFT action -*/ -#ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState){ - if( yyTraceFILE ){ - if( yyNewStateyystack[yypParser->yyidx].major], - yyNewState); - }else{ - fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); - } - } -} -#else -# define yyTraceShift(X,Y) -#endif - /* ** Perform a shift action. */ @@ -129000,7 +118043,16 @@ static void yy_shift( yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor = *yypMinor; - yyTraceShift(yypParser, yyNewState); +#ifndef NDEBUG + if( yyTraceFILE && yypParser->yyidx>0 ){ + int i; + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); + for(i=1; i<=yypParser->yyidx; i++) + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); + fprintf(yyTraceFILE,"\n"); + } +#endif } /* The following table contains information about every rule that @@ -129107,91 +118159,90 @@ static const struct { { 187, 5 }, { 187, 5 }, { 187, 10 }, - { 190, 0 }, - { 190, 1 }, + { 189, 0 }, + { 189, 1 }, { 176, 0 }, { 176, 3 }, - { 191, 0 }, - { 191, 2 }, - { 192, 1 }, - { 192, 1 }, - { 192, 1 }, + { 190, 0 }, + { 190, 2 }, + { 191, 1 }, + { 191, 1 }, + { 191, 1 }, { 149, 4 }, - { 194, 2 }, - { 194, 0 }, - { 149, 9 }, + { 193, 2 }, + { 193, 0 }, + { 149, 8 }, { 149, 4 }, { 149, 1 }, { 163, 2 }, + { 195, 1 }, + { 195, 3 }, + { 198, 1 }, + { 198, 2 }, + { 198, 1 }, + { 196, 9 }, { 196, 1 }, - { 196, 3 }, + { 207, 4 }, + { 207, 5 }, { 199, 1 }, - { 199, 2 }, { 199, 1 }, - { 197, 9 }, - { 197, 1 }, - { 208, 4 }, - { 208, 5 }, - { 200, 1 }, - { 200, 1 }, - { 200, 0 }, + { 199, 0 }, + { 210, 2 }, + { 210, 0 }, + { 200, 3 }, + { 200, 2 }, + { 200, 4 }, { 211, 2 }, + { 211, 1 }, { 211, 0 }, - { 201, 3 }, + { 201, 0 }, { 201, 2 }, - { 201, 4 }, - { 212, 2 }, - { 212, 1 }, - { 212, 0 }, - { 202, 0 }, - { 202, 2 }, - { 214, 2 }, - { 214, 0 }, - { 213, 7 }, - { 213, 9 }, - { 213, 7 }, - { 213, 7 }, + { 213, 2 }, + { 213, 0 }, + { 212, 7 }, + { 212, 7 }, + { 212, 7 }, { 159, 0 }, { 159, 2 }, - { 195, 2 }, - { 215, 1 }, - { 215, 2 }, - { 215, 3 }, - { 215, 4 }, - { 217, 2 }, - { 217, 0 }, - { 216, 0 }, - { 216, 3 }, + { 194, 2 }, + { 214, 1 }, + { 214, 2 }, + { 214, 3 }, + { 214, 4 }, { 216, 2 }, - { 218, 4 }, - { 218, 0 }, - { 206, 0 }, - { 206, 3 }, - { 188, 4 }, - { 188, 2 }, + { 216, 0 }, + { 215, 0 }, + { 215, 3 }, + { 215, 2 }, + { 217, 4 }, + { 217, 0 }, + { 205, 0 }, + { 205, 3 }, + { 220, 4 }, + { 220, 2 }, { 177, 1 }, { 177, 1 }, { 177, 0 }, - { 204, 0 }, - { 204, 3 }, - { 205, 0 }, - { 205, 2 }, - { 207, 0 }, - { 207, 2 }, - { 207, 4 }, - { 207, 4 }, - { 149, 6 }, { 203, 0 }, - { 203, 2 }, + { 203, 3 }, + { 204, 0 }, + { 204, 2 }, + { 206, 0 }, + { 206, 2 }, + { 206, 4 }, + { 206, 4 }, + { 149, 6 }, + { 202, 0 }, + { 202, 2 }, { 149, 8 }, - { 220, 5 }, - { 220, 3 }, + { 221, 5 }, + { 221, 3 }, { 149, 6 }, { 149, 7 }, - { 221, 2 }, - { 221, 1 }, - { 222, 0 }, - { 222, 3 }, + { 222, 2 }, + { 222, 1 }, + { 223, 0 }, + { 223, 3 }, { 219, 3 }, { 219, 1 }, { 175, 1 }, @@ -129217,8 +118268,8 @@ static const struct { { 175, 3 }, { 175, 3 }, { 175, 3 }, - { 223, 1 }, - { 223, 2 }, + { 224, 1 }, + { 224, 2 }, { 175, 3 }, { 175, 5 }, { 175, 2 }, @@ -129229,36 +118280,36 @@ static const struct { { 175, 2 }, { 175, 2 }, { 175, 2 }, - { 224, 1 }, - { 224, 2 }, - { 175, 5 }, { 225, 1 }, { 225, 2 }, { 175, 5 }, + { 226, 1 }, + { 226, 2 }, + { 175, 5 }, { 175, 3 }, { 175, 5 }, { 175, 4 }, { 175, 4 }, { 175, 5 }, - { 227, 5 }, - { 227, 4 }, - { 228, 2 }, - { 228, 0 }, - { 226, 1 }, - { 226, 0 }, - { 210, 1 }, - { 210, 0 }, - { 209, 3 }, - { 209, 1 }, - { 149, 12 }, - { 229, 1 }, + { 228, 5 }, + { 228, 4 }, + { 229, 2 }, { 229, 0 }, + { 227, 1 }, + { 227, 0 }, + { 209, 1 }, + { 209, 0 }, + { 208, 3 }, + { 208, 1 }, + { 149, 12 }, + { 230, 1 }, + { 230, 0 }, { 179, 0 }, { 179, 3 }, - { 189, 5 }, - { 189, 3 }, - { 230, 0 }, - { 230, 2 }, + { 188, 5 }, + { 188, 3 }, + { 231, 0 }, + { 231, 2 }, { 149, 4 }, { 149, 1 }, { 149, 2 }, @@ -129267,77 +118318,77 @@ static const struct { { 149, 6 }, { 149, 5 }, { 149, 6 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, - { 231, 1 }, + { 232, 1 }, + { 232, 1 }, + { 232, 1 }, + { 232, 1 }, + { 232, 1 }, { 171, 2 }, { 171, 1 }, { 172, 2 }, { 149, 5 }, - { 232, 11 }, - { 234, 1 }, - { 234, 1 }, - { 234, 2 }, - { 234, 0 }, + { 233, 11 }, { 235, 1 }, { 235, 1 }, - { 235, 3 }, - { 236, 0 }, + { 235, 2 }, + { 235, 0 }, + { 236, 1 }, + { 236, 1 }, { 236, 3 }, { 237, 0 }, - { 237, 2 }, - { 233, 3 }, - { 233, 2 }, - { 239, 1 }, - { 239, 3 }, - { 240, 0 }, + { 237, 3 }, + { 238, 0 }, + { 238, 2 }, + { 234, 3 }, + { 234, 2 }, + { 240, 1 }, { 240, 3 }, - { 240, 2 }, - { 238, 7 }, - { 238, 5 }, - { 238, 5 }, - { 238, 1 }, + { 241, 0 }, + { 241, 3 }, + { 241, 2 }, + { 239, 7 }, + { 239, 5 }, + { 239, 5 }, + { 239, 1 }, { 175, 4 }, { 175, 6 }, - { 193, 1 }, - { 193, 1 }, - { 193, 1 }, + { 192, 1 }, + { 192, 1 }, + { 192, 1 }, { 149, 4 }, { 149, 6 }, { 149, 3 }, + { 243, 0 }, + { 243, 2 }, + { 242, 1 }, { 242, 0 }, - { 242, 2 }, - { 241, 1 }, - { 241, 0 }, { 149, 1 }, { 149, 3 }, { 149, 1 }, { 149, 3 }, { 149, 6 }, { 149, 6 }, - { 243, 1 }, - { 244, 0 }, { 244, 1 }, + { 245, 0 }, + { 245, 1 }, { 149, 1 }, { 149, 4 }, - { 245, 8 }, - { 246, 1 }, - { 246, 3 }, - { 247, 0 }, - { 247, 2 }, - { 248, 1 }, - { 248, 3 }, + { 246, 8 }, + { 247, 1 }, + { 247, 3 }, + { 248, 0 }, + { 248, 2 }, { 249, 1 }, - { 250, 0 }, - { 250, 4 }, - { 250, 2 }, - { 198, 0 }, - { 198, 2 }, - { 198, 3 }, - { 251, 6 }, - { 251, 8 }, + { 249, 3 }, + { 250, 1 }, + { 251, 0 }, + { 251, 4 }, + { 251, 2 }, + { 197, 0 }, + { 197, 2 }, + { 197, 3 }, + { 252, 6 }, + { 252, 8 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -129360,13 +118411,29 @@ static void yy_reduce( #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[-yysize].stateno); + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, + yyRuleName[yyruleno]); } #endif /* NDEBUG */ + + /* Silence complaints from purify about yygotominor being uninitialized + ** in some cases when it is copied into the stack after the following + ** switch. yygotominor is uninitialized when a rule reduces that does + ** not set the value of its left-hand side nonterminal. Leaving the + ** value of the nonterminal uninitialized is utterly harmless as long + ** as the value is never used. So really the only thing this code + ** accomplishes is to quieten purify. + ** + ** 2007-01-16: The wireshark project (www.wireshark.org) reports that + ** without this code, their parser segfaults. I'm not sure what there + ** parser is doing to make this happen. This is the second bug report + ** from wireshark this week. Clearly they are stressing Lemon in ways + ** that it has not been previously stressed... (SQLite ticket #2172) + */ + /*memset(&yygotominor, 0, sizeof(yygotominor));*/ yygotominor = yyzerominor; + switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: @@ -129376,7 +118443,6 @@ static void yy_reduce( ** #line ** break; */ -/********** Begin reduce actions **********************************************/ case 5: /* explain ::= */ { sqlite3BeginParse(pParse, 0); } break; @@ -129390,17 +118456,17 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy328);} break; case 13: /* transtype ::= */ -{yygotominor.yy4 = TK_DEFERRED;} +{yygotominor.yy328 = TK_DEFERRED;} break; case 14: /* transtype ::= DEFERRED */ case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15); case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16); case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115); case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117); -{yygotominor.yy4 = yymsp[0].major;} +{yygotominor.yy328 = yymsp[0].major;} break; case 17: /* cmd ::= COMMIT trans_opt */ case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18); @@ -129426,7 +118492,7 @@ static void yy_reduce( break; case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy328,0,0,yymsp[-2].minor.yy328); } break; case 27: /* createkw ::= CREATE */ @@ -129437,46 +118503,45 @@ static void yy_reduce( break; case 28: /* ifnotexists ::= */ case 31: /* temp ::= */ yytestcase(yyruleno==31); - case 34: /* table_options ::= */ yytestcase(yyruleno==34); case 68: /* autoinc ::= */ yytestcase(yyruleno==68); case 81: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==81); case 83: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==83); case 85: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==85); case 97: /* defer_subclause_opt ::= */ yytestcase(yyruleno==97); case 108: /* ifexists ::= */ yytestcase(yyruleno==108); - case 124: /* distinct ::= */ yytestcase(yyruleno==124); - case 219: /* between_op ::= BETWEEN */ yytestcase(yyruleno==219); - case 222: /* in_op ::= IN */ yytestcase(yyruleno==222); - case 247: /* collate ::= */ yytestcase(yyruleno==247); -{yygotominor.yy4 = 0;} + case 218: /* between_op ::= BETWEEN */ yytestcase(yyruleno==218); + case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); +{yygotominor.yy328 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); case 69: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==69); case 84: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==84); case 107: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==107); - case 220: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==220); - case 223: /* in_op ::= NOT IN */ yytestcase(yyruleno==223); - case 248: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==248); -{yygotominor.yy4 = 1;} + case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); + case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); +{yygotominor.yy328 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy4,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy186,0); } break; case 33: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy387); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy3); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; + case 34: /* table_options ::= */ +{yygotominor.yy186 = 0;} + break; case 35: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yygotominor.yy4 = TF_WithoutRowid | TF_NoVisibleRowid; + yygotominor.yy186 = TF_WithoutRowid; }else{ - yygotominor.yy4 = 0; + yygotominor.yy186 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -129501,17 +118566,18 @@ static void yy_reduce( case 48: /* typename ::= ID|STRING */ yytestcase(yyruleno==48); case 130: /* as ::= AS nm */ yytestcase(yyruleno==130); case 131: /* as ::= ID|STRING */ yytestcase(yyruleno==131); - case 142: /* dbnm ::= DOT nm */ yytestcase(yyruleno==142); - case 151: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==151); - case 257: /* nmnum ::= plus_num */ yytestcase(yyruleno==257); - case 258: /* nmnum ::= nm */ yytestcase(yyruleno==258); - case 259: /* nmnum ::= ON */ yytestcase(yyruleno==259); - case 260: /* nmnum ::= DELETE */ yytestcase(yyruleno==260); - case 261: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==261); - case 262: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==262); - case 263: /* plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==263); - case 264: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==264); - case 280: /* trnm ::= nm */ yytestcase(yyruleno==280); + case 141: /* dbnm ::= DOT nm */ yytestcase(yyruleno==141); + case 150: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==150); + case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); + case 256: /* nmnum ::= plus_num */ yytestcase(yyruleno==256); + case 257: /* nmnum ::= nm */ yytestcase(yyruleno==257); + case 258: /* nmnum ::= ON */ yytestcase(yyruleno==258); + case 259: /* nmnum ::= DELETE */ yytestcase(yyruleno==259); + case 260: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==260); + case 261: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==261); + case 262: /* plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==262); + case 263: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==263); + case 279: /* trnm ::= nm */ yytestcase(yyruleno==279); {yygotominor.yy0 = yymsp[0].minor.yy0;} break; case 44: /* type ::= typetoken */ @@ -129538,17 +118604,17 @@ static void yy_reduce( break; case 55: /* ccons ::= DEFAULT term */ case 57: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==57); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy118);} +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy346);} break; case 56: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy118);} +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy346);} break; case 58: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy118.pExpr, 0, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy346.pExpr, 0, 0); v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy118.zEnd; + v.zEnd = yymsp[0].minor.yy346.zEnd; sqlite3AddDefaultValue(pParse,&v); } break; @@ -129560,64 +118626,62 @@ static void yy_reduce( } break; case 61: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy328);} break; case 62: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy328,yymsp[0].minor.yy328,yymsp[-2].minor.yy328);} break; case 63: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy328,0,0,0,0);} break; case 64: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy118.pExpr);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy346.pExpr);} break; - case 65: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);} + case 65: /* ccons ::= REFERENCES nm idxlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy328);} break; case 66: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy328);} break; case 67: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 70: /* refargs ::= */ -{ yygotominor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yygotominor.yy328 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 71: /* refargs ::= refargs refarg */ -{ yygotominor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; } +{ yygotominor.yy328 = (yymsp[-1].minor.yy328 & ~yymsp[0].minor.yy429.mask) | yymsp[0].minor.yy429.value; } break; case 72: /* refarg ::= MATCH nm */ case 73: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==73); -{ yygotominor.yy215.value = 0; yygotominor.yy215.mask = 0x000000; } +{ yygotominor.yy429.value = 0; yygotominor.yy429.mask = 0x000000; } break; case 74: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4; yygotominor.yy215.mask = 0x0000ff; } +{ yygotominor.yy429.value = yymsp[0].minor.yy328; yygotominor.yy429.mask = 0x0000ff; } break; case 75: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4<<8; yygotominor.yy215.mask = 0x00ff00; } +{ yygotominor.yy429.value = yymsp[0].minor.yy328<<8; yygotominor.yy429.mask = 0x00ff00; } break; case 76: /* refact ::= SET NULL */ -{ yygotominor.yy4 = OE_SetNull; /* EV: R-33326-45252 */} +{ yygotominor.yy328 = OE_SetNull; /* EV: R-33326-45252 */} break; case 77: /* refact ::= SET DEFAULT */ -{ yygotominor.yy4 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yygotominor.yy328 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 78: /* refact ::= CASCADE */ -{ yygotominor.yy4 = OE_Cascade; /* EV: R-33326-45252 */} +{ yygotominor.yy328 = OE_Cascade; /* EV: R-33326-45252 */} break; case 79: /* refact ::= RESTRICT */ -{ yygotominor.yy4 = OE_Restrict; /* EV: R-33326-45252 */} +{ yygotominor.yy328 = OE_Restrict; /* EV: R-33326-45252 */} break; case 80: /* refact ::= NO ACTION */ -{ yygotominor.yy4 = OE_None; /* EV: R-33326-45252 */} +{ yygotominor.yy328 = OE_None; /* EV: R-33326-45252 */} break; case 82: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 98: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==98); case 100: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==100); - case 102: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==102); case 103: /* resolvetype ::= raisetype */ yytestcase(yyruleno==103); - case 178: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==178); -{yygotominor.yy4 = yymsp[0].minor.yy4;} +{yygotominor.yy328 = yymsp[0].minor.yy328;} break; case 86: /* conslist_opt ::= */ {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} @@ -129628,407 +118692,393 @@ static void yy_reduce( case 90: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 93: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);} + case 93: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy328,yymsp[-2].minor.yy328,0);} break; - case 94: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0);} + case 94: /* tcons ::= UNIQUE LP idxlist RP onconf */ +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy328,0,0,0,0);} break; case 95: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy118.pExpr);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy346.pExpr);} break; - case 96: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + case 96: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy328); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy328); } break; case 99: /* onconf ::= */ - case 101: /* orconf ::= */ yytestcase(yyruleno==101); -{yygotominor.yy4 = OE_Default;} +{yygotominor.yy328 = OE_Default;} + break; + case 101: /* orconf ::= */ +{yygotominor.yy186 = OE_Default;} + break; + case 102: /* orconf ::= OR resolvetype */ +{yygotominor.yy186 = (u8)yymsp[0].minor.yy328;} break; case 104: /* resolvetype ::= IGNORE */ -{yygotominor.yy4 = OE_Ignore;} +{yygotominor.yy328 = OE_Ignore;} break; case 105: /* resolvetype ::= REPLACE */ - case 179: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==179); -{yygotominor.yy4 = OE_Replace;} +{yygotominor.yy328 = OE_Replace;} break; case 106: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 0, yymsp[-1].minor.yy328); } break; - case 109: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + case 109: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[0].minor.yy387, yymsp[-7].minor.yy4, yymsp[-5].minor.yy4); + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy3, yymsp[-6].minor.yy328, yymsp[-4].minor.yy328); } break; case 110: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328); } break; case 111: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy387, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3Select(pParse, yymsp[0].minor.yy3, &dest); + sqlite3ExplainBegin(pParse->pVdbe); + sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy3); + sqlite3ExplainFinish(pParse->pVdbe); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3); } break; case 112: /* select ::= with selectnowith */ { - Select *p = yymsp[0].minor.yy387; + Select *p = yymsp[0].minor.yy3, *pNext, *pLoop; if( p ){ - p->pWith = yymsp[-1].minor.yy451; - parserDoubleLinkSelect(pParse, p); + int cnt = 0, mxSelect; + p->pWith = yymsp[-1].minor.yy59; + if( p->pPrior ){ + pNext = 0; + for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ + pLoop->pNext = pNext; + pLoop->selFlags |= SF_Compound; + } + mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; + if( mxSelect && cnt>mxSelect ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + } + } }else{ - sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451); + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59); } - yygotominor.yy387 = p; + yygotominor.yy3 = p; } break; case 113: /* selectnowith ::= oneselect */ case 119: /* oneselect ::= values */ yytestcase(yyruleno==119); -{yygotominor.yy387 = yymsp[0].minor.yy387;} +{yygotominor.yy3 = yymsp[0].minor.yy3;} break; case 114: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy387; - Select *pLhs = yymsp[-2].minor.yy387; + Select *pRhs = yymsp[0].minor.yy3; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; - parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy4; - pRhs->pPrior = pLhs; - if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; - pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy4!=TK_ALL ) pParse->hasCompound = 1; + pRhs->op = (u8)yymsp[-1].minor.yy328; + pRhs->pPrior = yymsp[-2].minor.yy3; + if( yymsp[-1].minor.yy328!=TK_ALL ) pParse->hasCompound = 1; }else{ - sqlite3SelectDelete(pParse->db, pLhs); + sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3); } - yygotominor.yy387 = pRhs; + yygotominor.yy3 = pRhs; } break; case 116: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy4 = TK_ALL;} +{yygotominor.yy328 = TK_ALL;} break; case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy4,yymsp[0].minor.yy292.pLimit,yymsp[0].minor.yy292.pOffset); -#if SELECTTRACE_ENABLED - /* Populate the Select.zSelName[] string that is used to help with - ** query planner debugging, to differentiate between multiple Select - ** objects in a complex query. - ** - ** If the SELECT keyword is immediately followed by a C-style comment - ** then extract the first few alphanumeric characters from within that - ** comment to be the zSelName value. Otherwise, the label is #N where - ** is an integer that is incremented with each SELECT statement seen. - */ - if( yygotominor.yy387!=0 ){ - const char *z = yymsp[-8].minor.yy0.z+6; - int i; - sqlite3_snprintf(sizeof(yygotominor.yy387->zSelName), yygotominor.yy387->zSelName, "#%d", - ++pParse->nSelect); - while( z[0]==' ' ) z++; - if( z[0]=='/' && z[1]=='*' ){ - z += 2; - while( z[0]==' ' ) z++; - for(i=0; sqlite3Isalnum(z[i]); i++){} - sqlite3_snprintf(sizeof(yygotominor.yy387->zSelName), yygotominor.yy387->zSelName, "%.*s", i, z); - } - } -#endif /* SELECTRACE_ENABLED */ + yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy381,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset); } break; case 120: /* values ::= VALUES LP nexprlist RP */ { - yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0,0); + yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0); } break; case 121: /* values ::= values COMMA LP exprlist RP */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy387; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); - if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; + Select *pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0); if( pRight ){ pRight->op = TK_ALL; - pLeft = yymsp[-4].minor.yy387; - pRight->pPrior = pLeft; - yygotominor.yy387 = pRight; + pRight->pPrior = yymsp[-4].minor.yy3; + yygotominor.yy3 = pRight; }else{ - yygotominor.yy387 = pLeft; + yygotominor.yy3 = yymsp[-4].minor.yy3; } } break; case 122: /* distinct ::= DISTINCT */ -{yygotominor.yy4 = SF_Distinct;} +{yygotominor.yy381 = SF_Distinct;} break; case 123: /* distinct ::= ALL */ -{yygotominor.yy4 = SF_All;} + case 124: /* distinct ::= */ yytestcase(yyruleno==124); +{yygotominor.yy381 = 0;} break; case 125: /* sclp ::= selcollist COMMA */ - case 244: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==244); -{yygotominor.yy322 = yymsp[-1].minor.yy322;} + case 243: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==243); +{yygotominor.yy14 = yymsp[-1].minor.yy14;} break; case 126: /* sclp ::= */ - case 155: /* orderby_opt ::= */ yytestcase(yyruleno==155); - case 162: /* groupby_opt ::= */ yytestcase(yyruleno==162); - case 237: /* exprlist ::= */ yytestcase(yyruleno==237); - case 243: /* eidlist_opt ::= */ yytestcase(yyruleno==243); -{yygotominor.yy322 = 0;} + case 154: /* orderby_opt ::= */ yytestcase(yyruleno==154); + case 161: /* groupby_opt ::= */ yytestcase(yyruleno==161); + case 236: /* exprlist ::= */ yytestcase(yyruleno==236); + case 242: /* idxlist_opt ::= */ yytestcase(yyruleno==242); +{yygotominor.yy14 = 0;} break; case 127: /* selcollist ::= sclp expr as */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, yymsp[-1].minor.yy118.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yygotominor.yy322,&yymsp[-1].minor.yy118); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, yymsp[-1].minor.yy346.pExpr); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yygotominor.yy14,&yymsp[-1].minor.yy346); } break; case 128: /* selcollist ::= sclp STAR */ { - Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy322, p); + Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy14, p); } break; case 129: /* selcollist ::= sclp nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &yymsp[0].minor.yy0); + Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, pDot); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, pDot); } break; case 132: /* as ::= */ {yygotominor.yy0.n = 0;} break; case 133: /* from ::= */ -{yygotominor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy259));} +{yygotominor.yy65 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy65));} break; case 134: /* from ::= FROM seltablist */ { - yygotominor.yy259 = yymsp[0].minor.yy259; - sqlite3SrcListShiftJoinType(yygotominor.yy259); + yygotominor.yy65 = yymsp[0].minor.yy65; + sqlite3SrcListShiftJoinType(yygotominor.yy65); } break; case 135: /* stl_prefix ::= seltablist joinop */ { - yygotominor.yy259 = yymsp[-1].minor.yy259; - if( ALWAYS(yygotominor.yy259 && yygotominor.yy259->nSrc>0) ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy4; + yygotominor.yy65 = yymsp[-1].minor.yy65; + if( ALWAYS(yygotominor.yy65 && yygotominor.yy65->nSrc>0) ) yygotominor.yy65->a[yygotominor.yy65->nSrc-1].jointype = (u8)yymsp[0].minor.yy328; } break; case 136: /* stl_prefix ::= */ -{yygotominor.yy259 = 0;} +{yygotominor.yy65 = 0;} break; case 137: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - sqlite3SrcListIndexedBy(pParse, yygotominor.yy259, &yymsp[-2].minor.yy0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); + sqlite3SrcListIndexedBy(pParse, yygotominor.yy65, &yymsp[-2].minor.yy0); } break; - case 138: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + case 138: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy259,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - sqlite3SrcListFuncArgs(pParse, yygotominor.yy259, yymsp[-4].minor.yy322); -} - break; - case 139: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ -{ - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy3,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } break; - case 140: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 139: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){ - yygotominor.yy259 = yymsp[-4].minor.yy259; - }else if( yymsp[-4].minor.yy259->nSrc==1 ){ - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - if( yygotominor.yy259 ){ - struct SrcList_item *pNew = &yygotominor.yy259->a[yygotominor.yy259->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy259->a; + if( yymsp[-6].minor.yy65==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy132==0 && yymsp[0].minor.yy408==0 ){ + yygotominor.yy65 = yymsp[-4].minor.yy65; + }else if( yymsp[-4].minor.yy65->nSrc==1 ){ + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); + if( yygotominor.yy65 ){ + struct SrcList_item *pNew = &yygotominor.yy65->a[yygotominor.yy65->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy65->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy259); + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy65); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,SF_NestedFrom,0,0); - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy65); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy65,0,0,0,0,SF_NestedFrom,0,0); + yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy132,yymsp[0].minor.yy408); } } break; - case 141: /* dbnm ::= */ - case 150: /* indexed_opt ::= */ yytestcase(yyruleno==150); + case 140: /* dbnm ::= */ + case 149: /* indexed_opt ::= */ yytestcase(yyruleno==149); {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} break; - case 143: /* fullname ::= nm dbnm */ -{yygotominor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} + case 142: /* fullname ::= nm dbnm */ +{yygotominor.yy65 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; - case 144: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy4 = JT_INNER; } + case 143: /* joinop ::= COMMA|JOIN */ +{ yygotominor.yy328 = JT_INNER; } break; - case 145: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } + case 144: /* joinop ::= JOIN_KW JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } break; - case 146: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } + case 145: /* joinop ::= JOIN_KW nm JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } break; - case 147: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } + case 146: /* joinop ::= JOIN_KW nm nm JOIN */ +{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } break; - case 148: /* on_opt ::= ON expr */ - case 165: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==165); - case 172: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==172); - case 232: /* case_else ::= ELSE expr */ yytestcase(yyruleno==232); - case 234: /* case_operand ::= expr */ yytestcase(yyruleno==234); -{yygotominor.yy314 = yymsp[0].minor.yy118.pExpr;} + case 147: /* on_opt ::= ON expr */ + case 164: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==164); + case 171: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==171); + case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); + case 233: /* case_operand ::= expr */ yytestcase(yyruleno==233); +{yygotominor.yy132 = yymsp[0].minor.yy346.pExpr;} break; - case 149: /* on_opt ::= */ - case 164: /* having_opt ::= */ yytestcase(yyruleno==164); - case 171: /* where_opt ::= */ yytestcase(yyruleno==171); - case 233: /* case_else ::= */ yytestcase(yyruleno==233); - case 235: /* case_operand ::= */ yytestcase(yyruleno==235); -{yygotominor.yy314 = 0;} + case 148: /* on_opt ::= */ + case 163: /* having_opt ::= */ yytestcase(yyruleno==163); + case 170: /* where_opt ::= */ yytestcase(yyruleno==170); + case 232: /* case_else ::= */ yytestcase(yyruleno==232); + case 234: /* case_operand ::= */ yytestcase(yyruleno==234); +{yygotominor.yy132 = 0;} break; - case 152: /* indexed_opt ::= NOT INDEXED */ + case 151: /* indexed_opt ::= NOT INDEXED */ {yygotominor.yy0.z=0; yygotominor.yy0.n=1;} break; - case 153: /* using_opt ::= USING LP idlist RP */ - case 181: /* idlist_opt ::= LP idlist RP */ yytestcase(yyruleno==181); -{yygotominor.yy384 = yymsp[-1].minor.yy384;} + case 152: /* using_opt ::= USING LP idlist RP */ + case 180: /* inscollist_opt ::= LP idlist RP */ yytestcase(yyruleno==180); +{yygotominor.yy408 = yymsp[-1].minor.yy408;} break; - case 154: /* using_opt ::= */ - case 180: /* idlist_opt ::= */ yytestcase(yyruleno==180); -{yygotominor.yy384 = 0;} + case 153: /* using_opt ::= */ + case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179); +{yygotominor.yy408 = 0;} break; - case 156: /* orderby_opt ::= ORDER BY sortlist */ - case 163: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==163); - case 236: /* exprlist ::= nexprlist */ yytestcase(yyruleno==236); -{yygotominor.yy322 = yymsp[0].minor.yy322;} + case 155: /* orderby_opt ::= ORDER BY sortlist */ + case 162: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==162); + case 235: /* exprlist ::= nexprlist */ yytestcase(yyruleno==235); +{yygotominor.yy14 = yymsp[0].minor.yy14;} break; - case 157: /* sortlist ::= sortlist COMMA expr sortorder */ + case 156: /* sortlist ::= sortlist COMMA expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy118.pExpr); - sqlite3ExprListSetSortOrder(yygotominor.yy322,yymsp[0].minor.yy4); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14,yymsp[-1].minor.yy346.pExpr); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 158: /* sortlist ::= expr sortorder */ + case 157: /* sortlist ::= expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy118.pExpr); - sqlite3ExprListSetSortOrder(yygotominor.yy322,yymsp[0].minor.yy4); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy346.pExpr); + if( yygotominor.yy14 && ALWAYS(yygotominor.yy14->a) ) yygotominor.yy14->a[0].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 159: /* sortorder ::= ASC */ -{yygotominor.yy4 = SQLITE_SO_ASC;} + case 158: /* sortorder ::= ASC */ + case 160: /* sortorder ::= */ yytestcase(yyruleno==160); +{yygotominor.yy328 = SQLITE_SO_ASC;} break; - case 160: /* sortorder ::= DESC */ -{yygotominor.yy4 = SQLITE_SO_DESC;} + case 159: /* sortorder ::= DESC */ +{yygotominor.yy328 = SQLITE_SO_DESC;} break; - case 161: /* sortorder ::= */ -{yygotominor.yy4 = SQLITE_SO_UNDEFINED;} + case 165: /* limit_opt ::= */ +{yygotominor.yy476.pLimit = 0; yygotominor.yy476.pOffset = 0;} break; - case 166: /* limit_opt ::= */ -{yygotominor.yy292.pLimit = 0; yygotominor.yy292.pOffset = 0;} + case 166: /* limit_opt ::= LIMIT expr */ +{yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr; yygotominor.yy476.pOffset = 0;} break; - case 167: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr; yygotominor.yy292.pOffset = 0;} + case 167: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yygotominor.yy476.pLimit = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pOffset = yymsp[0].minor.yy346.pExpr;} break; - case 168: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy292.pLimit = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pOffset = yymsp[0].minor.yy118.pExpr;} + case 168: /* limit_opt ::= LIMIT expr COMMA expr */ +{yygotominor.yy476.pOffset = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr;} break; - case 169: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy292.pOffset = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr;} - break; - case 170: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ + case 169: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314); + sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy65, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy65,yymsp[0].minor.yy132); } break; - case 173: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 172: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3WithPush(pParse, yymsp[-7].minor.yy451, 1); - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy4); + sqlite3WithPush(pParse, yymsp[-7].minor.yy59, 1); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy65, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy65,yymsp[-1].minor.yy14,yymsp[0].minor.yy132,yymsp[-5].minor.yy186); } break; - case 174: /* setlist ::= setlist COMMA nm EQ expr */ + case 173: /* setlist ::= setlist COMMA nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 175: /* setlist ::= nm EQ expr */ + case 174: /* setlist ::= nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy346.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); } break; - case 176: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 175: /* cmd ::= with insert_cmd INTO fullname inscollist_opt select */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1); - sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy4); + sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1); + sqlite3Insert(pParse, yymsp[-2].minor.yy65, yymsp[0].minor.yy3, yymsp[-1].minor.yy408, yymsp[-4].minor.yy186); } break; - case 177: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 176: /* cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ { - sqlite3WithPush(pParse, yymsp[-6].minor.yy451, 1); - sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy4); + sqlite3WithPush(pParse, yymsp[-6].minor.yy59, 1); + sqlite3Insert(pParse, yymsp[-3].minor.yy65, 0, yymsp[-2].minor.yy408, yymsp[-5].minor.yy186); } break; - case 182: /* idlist ::= idlist COMMA nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);} + case 177: /* insert_cmd ::= INSERT orconf */ +{yygotominor.yy186 = yymsp[0].minor.yy186;} break; - case 183: /* idlist ::= nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} + case 178: /* insert_cmd ::= REPLACE */ +{yygotominor.yy186 = OE_Replace;} break; - case 184: /* expr ::= term */ -{yygotominor.yy118 = yymsp[0].minor.yy118;} + case 181: /* idlist ::= idlist COMMA nm */ +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy408,&yymsp[0].minor.yy0);} break; - case 185: /* expr ::= LP expr RP */ -{yygotominor.yy118.pExpr = yymsp[-1].minor.yy118.pExpr; spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} + case 182: /* idlist ::= nm */ +{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} break; - case 186: /* term ::= NULL */ - case 191: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==191); - case 192: /* term ::= STRING */ yytestcase(yyruleno==192); -{spanExpr(&yygotominor.yy118, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} + case 183: /* expr ::= term */ +{yygotominor.yy346 = yymsp[0].minor.yy346;} break; - case 187: /* expr ::= ID|INDEXED */ - case 188: /* expr ::= JOIN_KW */ yytestcase(yyruleno==188); -{spanExpr(&yygotominor.yy118, pParse, TK_ID, &yymsp[0].minor.yy0);} + case 184: /* expr ::= LP expr RP */ +{yygotominor.yy346.pExpr = yymsp[-1].minor.yy346.pExpr; spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} break; - case 189: /* expr ::= nm DOT nm */ + case 185: /* term ::= NULL */ + case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190); + case 191: /* term ::= STRING */ yytestcase(yyruleno==191); +{spanExpr(&yygotominor.yy346, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} + break; + case 186: /* expr ::= ID|INDEXED */ + case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187); +{spanExpr(&yygotominor.yy346, pParse, TK_ID, &yymsp[0].minor.yy0);} + break; + case 188: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); - spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; - case 190: /* expr ::= nm DOT nm DOT nm */ + case 189: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); } break; - case 193: /* expr ::= VARIABLE */ + case 192: /* expr ::= VARIABLE */ { if( yymsp[0].minor.yy0.n>=2 && yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1]) ){ /* When doing a nested parse, one can include terms in an expression @@ -130036,142 +119086,142 @@ static void yy_reduce( ** in the virtual machine. #N is the N-th register. */ if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = 0; + yygotominor.yy346.pExpr = 0; }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); - if( yygotominor.yy118.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy118.pExpr->iTable); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); + if( yygotominor.yy346.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy346.pExpr->iTable); } }else{ - spanExpr(&yygotominor.yy118, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yygotominor.yy118.pExpr); + spanExpr(&yygotominor.yy346, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yygotominor.yy346.pExpr); } - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 194: /* expr ::= expr COLLATE ID|STRING */ + case 193: /* expr ::= expr COLLATE ID|STRING */ { - yygotominor.yy118.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy118.pExpr, &yymsp[0].minor.yy0, 1); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0); + yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 195: /* expr ::= CAST LP expr AS typetoken RP */ + case 194: /* expr ::= CAST LP expr AS typetoken RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy118.pExpr, 0, &yymsp[-1].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy346.pExpr, 0, &yymsp[-1].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } break; - case 196: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 195: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + if( yymsp[-1].minor.yy14 && yymsp[-1].minor.yy14->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy4==SF_Distinct && yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->flags |= EP_Distinct; + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy381 && yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->flags |= EP_Distinct; } } break; - case 197: /* expr ::= ID|INDEXED LP STAR RP */ + case 196: /* expr ::= ID|INDEXED LP STAR RP */ { - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yygotominor.yy346,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } break; - case 198: /* term ::= CTIME_KW */ + case 197: /* term ::= CTIME_KW */ { - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 199: /* expr ::= expr AND expr */ - case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200); - case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201); - case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204); - case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205); - case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206); -{spanBinaryExpr(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);} + case 198: /* expr ::= expr AND expr */ + case 199: /* expr ::= expr OR expr */ yytestcase(yyruleno==199); + case 200: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==200); + case 201: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==201); + case 202: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==204); + case 205: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==205); +{spanBinaryExpr(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346);} break; - case 207: /* likeop ::= LIKE_KW|MATCH */ -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 0;} + case 206: /* likeop ::= LIKE_KW|MATCH */ +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 0;} break; - case 208: /* likeop ::= NOT LIKE_KW|MATCH */ -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 1;} + case 207: /* likeop ::= NOT LIKE_KW|MATCH */ +{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 1;} break; - case 209: /* expr ::= expr likeop expr */ + case 208: /* expr ::= expr likeop expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy342.eOperator); - exprNot(pParse, yymsp[-1].minor.yy342.bNot, &yygotominor.yy118.pExpr); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy96.eOperator); + if( yymsp[-1].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; + if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc; } break; - case 210: /* expr ::= expr likeop expr ESCAPE expr */ + case 209: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy342.eOperator); - exprNot(pParse, yymsp[-3].minor.yy342.bNot, &yygotominor.yy118.pExpr); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy96.eOperator); + if( yymsp[-3].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; + if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc; } break; - case 211: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,yymsp[0].major,&yymsp[-1].minor.yy118,&yymsp[0].minor.yy0);} + case 210: /* expr ::= expr ISNULL|NOTNULL */ +{spanUnaryPostfix(&yygotominor.yy346,pParse,yymsp[0].major,&yymsp[-1].minor.yy346,&yymsp[0].minor.yy0);} break; - case 212: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,TK_NOTNULL,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy0);} + case 211: /* expr ::= expr NOT NULL */ +{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_NOTNULL,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy0);} break; - case 213: /* expr ::= expr IS expr */ + case 212: /* expr ::= expr IS expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_IS,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_ISNULL); + spanBinaryExpr(&yygotominor.yy346,pParse,TK_IS,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_ISNULL); } break; - case 214: /* expr ::= expr IS NOT expr */ + case 213: /* expr ::= expr IS NOT expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_ISNOT,&yymsp[-3].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_NOTNULL); + spanBinaryExpr(&yygotominor.yy346,pParse,TK_ISNOT,&yymsp[-3].minor.yy346,&yymsp[0].minor.yy346); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_NOTNULL); } break; - case 215: /* expr ::= NOT expr */ - case 216: /* expr ::= BITNOT expr */ yytestcase(yyruleno==216); -{spanUnaryPrefix(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 214: /* expr ::= NOT expr */ + case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); +{spanUnaryPrefix(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 217: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UMINUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 216: /* expr ::= MINUS expr */ +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UMINUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 218: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UPLUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 217: /* expr ::= PLUS expr */ +{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UPLUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);} break; - case 221: /* expr ::= expr between_op expr AND expr */ + case 220: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - exprNot(pParse, yymsp[-3].minor.yy4, &yygotominor.yy118.pExpr); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd; } break; - case 224: /* expr ::= expr in_op LP exprlist RP */ + case 223: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy322==0 ){ + if( yymsp[-1].minor.yy14==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -130180,9 +119230,9 @@ static void yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy4]); - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy118.pExpr); - }else if( yymsp[-1].minor.yy322->nExpr==1 ){ + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy328]); + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy346.pExpr); + }else if( yymsp[-1].minor.yy14->nExpr==1 ){ /* Expressions of the form: ** ** expr1 IN (?1) @@ -130199,222 +119249,233 @@ static void yy_reduce( ** affinity or the collating sequence to use for comparison. Otherwise, ** the semantics would be subtly different from IN or NOT IN. */ - Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr; - yymsp[-1].minor.yy322->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr; + yymsp[-1].minor.yy14->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); /* pRHS cannot be NULL because a malloc error would have been detected ** before now and control would have never reached this point */ if( ALWAYS(pRHS) ){ pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy4 ? TK_NE : TK_EQ, yymsp[-4].minor.yy118.pExpr, pRHS, 0); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy328 ? TK_NE : TK_EQ, yymsp[-4].minor.yy346.pExpr, pRHS, 0); }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy322; - sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); } - exprNot(pParse, yymsp[-3].minor.yy4, &yygotominor.yy118.pExpr); + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 225: /* expr ::= LP select RP */ + case 224: /* expr ::= LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - yygotominor.yy118.zStart = yymsp[-2].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-2].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 226: /* expr ::= expr in_op LP select RP */ + case 225: /* expr ::= expr in_op LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - exprNot(pParse, yymsp[-3].minor.yy4, &yygotominor.yy118.pExpr); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 227: /* expr ::= expr in_op nm dbnm */ + case 226: /* expr ::= expr in_op nm dbnm */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - exprNot(pParse, yymsp[-2].minor.yy4, &yygotominor.yy118.pExpr); - yygotominor.yy118.zStart = yymsp[-3].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; + if( yymsp[-2].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0); + yygotominor.yy346.zStart = yymsp[-3].minor.yy346.zStart; + yygotominor.yy346.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; } break; - case 228: /* expr ::= EXISTS LP select RP */ + case 227: /* expr ::= EXISTS LP select RP */ { - Expr *p = yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ - p->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(p, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeightAndFlags(pParse, p); + p->x.pSelect = yymsp[-1].minor.yy3; + ExprSetProperty(p, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, p); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3); } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 229: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy314 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy314) : yymsp[-2].minor.yy322; - sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy118.pExpr); + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy132 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy132) : yymsp[-2].minor.yy14; + sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy314); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy132); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-4].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 230: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; - case 231: /* case_exprlist ::= WHEN expr THEN expr */ + case 230: /* case_exprlist ::= WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr); } break; - case 238: /* nexprlist ::= nexprlist COMMA expr */ -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy118.pExpr);} + case 237: /* nexprlist ::= nexprlist COMMA expr */ +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy346.pExpr);} break; - case 239: /* nexprlist ::= expr */ -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy118.pExpr);} + case 238: /* nexprlist ::= expr */ +{yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy346.pExpr);} break; - case 240: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4); + sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy328, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy132, SQLITE_SO_ASC, yymsp[-8].minor.yy328); } break; - case 241: /* uniqueflag ::= UNIQUE */ - case 292: /* raisetype ::= ABORT */ yytestcase(yyruleno==292); -{yygotominor.yy4 = OE_Abort;} + case 240: /* uniqueflag ::= UNIQUE */ + case 291: /* raisetype ::= ABORT */ yytestcase(yyruleno==291); +{yygotominor.yy328 = OE_Abort;} break; - case 242: /* uniqueflag ::= */ -{yygotominor.yy4 = OE_None;} + case 241: /* uniqueflag ::= */ +{yygotominor.yy328 = OE_None;} break; - case 245: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 244: /* idxlist ::= idxlist COMMA nm collate sortorder */ { - yygotominor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p); + sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 246: /* eidlist ::= nm collate sortorder */ + case 245: /* idxlist ::= nm collate sortorder */ { - yygotominor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); + yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p); + sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index"); + if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328; } break; - case 249: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);} + case 246: /* collate ::= */ +{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} break; - case 250: /* cmd ::= VACUUM */ - case 251: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==251); + case 248: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy65, yymsp[-1].minor.yy328);} + break; + case 249: /* cmd ::= VACUUM */ + case 250: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==250); {sqlite3Vacuum(pParse);} break; - case 252: /* cmd ::= PRAGMA nm dbnm */ + case 251: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 253: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 254: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 255: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 256: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 265: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 264: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy473, &all); } break; - case 266: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 265: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy328, yymsp[-4].minor.yy378.a, yymsp[-4].minor.yy378.b, yymsp[-2].minor.yy65, yymsp[0].minor.yy132, yymsp[-10].minor.yy328, yymsp[-8].minor.yy328); yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); } break; - case 267: /* trigger_time ::= BEFORE */ - case 270: /* trigger_time ::= */ yytestcase(yyruleno==270); -{ yygotominor.yy4 = TK_BEFORE; } + case 266: /* trigger_time ::= BEFORE */ + case 269: /* trigger_time ::= */ yytestcase(yyruleno==269); +{ yygotominor.yy328 = TK_BEFORE; } break; - case 268: /* trigger_time ::= AFTER */ -{ yygotominor.yy4 = TK_AFTER; } + case 267: /* trigger_time ::= AFTER */ +{ yygotominor.yy328 = TK_AFTER; } break; - case 269: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy4 = TK_INSTEAD;} + case 268: /* trigger_time ::= INSTEAD OF */ +{ yygotominor.yy328 = TK_INSTEAD;} break; - case 271: /* trigger_event ::= DELETE|INSERT */ - case 272: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==272); -{yygotominor.yy90.a = yymsp[0].major; yygotominor.yy90.b = 0;} + case 270: /* trigger_event ::= DELETE|INSERT */ + case 271: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==271); +{yygotominor.yy378.a = yymsp[0].major; yygotominor.yy378.b = 0;} break; - case 273: /* trigger_event ::= UPDATE OF idlist */ -{yygotominor.yy90.a = TK_UPDATE; yygotominor.yy90.b = yymsp[0].minor.yy384;} + case 272: /* trigger_event ::= UPDATE OF idlist */ +{yygotominor.yy378.a = TK_UPDATE; yygotominor.yy378.b = yymsp[0].minor.yy408;} break; - case 276: /* when_clause ::= */ - case 297: /* key_opt ::= */ yytestcase(yyruleno==297); -{ yygotominor.yy314 = 0; } + case 275: /* when_clause ::= */ + case 296: /* key_opt ::= */ yytestcase(yyruleno==296); +{ yygotominor.yy132 = 0; } break; - case 277: /* when_clause ::= WHEN expr */ - case 298: /* key_opt ::= KEY expr */ yytestcase(yyruleno==298); -{ yygotominor.yy314 = yymsp[0].minor.yy118.pExpr; } + case 276: /* when_clause ::= WHEN expr */ + case 297: /* key_opt ::= KEY expr */ yytestcase(yyruleno==297); +{ yygotominor.yy132 = yymsp[0].minor.yy346.pExpr; } break; - case 278: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 277: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy203!=0 ); - yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203; - yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-2].minor.yy203; + assert( yymsp[-2].minor.yy473!=0 ); + yymsp[-2].minor.yy473->pLast->pNext = yymsp[-1].minor.yy473; + yymsp[-2].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-2].minor.yy473; } break; - case 279: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 278: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy203!=0 ); - yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-1].minor.yy203; + assert( yymsp[-1].minor.yy473!=0 ); + yymsp[-1].minor.yy473->pLast = yymsp[-1].minor.yy473; + yygotominor.yy473 = yymsp[-1].minor.yy473; } break; - case 281: /* trnm ::= nm DOT nm */ + case 280: /* trnm ::= nm DOT nm */ { yygotominor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -130422,135 +119483,135 @@ static void yy_reduce( "statements within triggers"); } break; - case 283: /* tridxby ::= INDEXED BY nm */ + case 282: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 284: /* tridxby ::= NOT INDEXED */ + case 283: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 285: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{ yygotominor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy314, yymsp[-5].minor.yy4); } + case 284: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +{ yygotominor.yy473 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy14, yymsp[0].minor.yy132, yymsp[-5].minor.yy186); } break; - case 286: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ -{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, yymsp[0].minor.yy387, yymsp[-4].minor.yy4);} + case 285: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ +{yygotominor.yy473 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy408, yymsp[0].minor.yy3, yymsp[-4].minor.yy186);} break; - case 287: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yygotominor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy314);} + case 286: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +{yygotominor.yy473 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy132);} break; - case 288: /* trigger_cmd ::= select */ -{yygotominor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy387); } + case 287: /* trigger_cmd ::= select */ +{yygotominor.yy473 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy3); } break; - case 289: /* expr ::= RAISE LP IGNORE RP */ + case 288: /* expr ::= RAISE LP IGNORE RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->affinity = OE_Ignore; + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( yygotominor.yy346.pExpr ){ + yygotominor.yy346.pExpr->affinity = OE_Ignore; } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 290: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 289: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy118.pExpr ) { - yygotominor.yy118.pExpr->affinity = (char)yymsp[-3].minor.yy4; + yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); + if( yygotominor.yy346.pExpr ) { + yygotominor.yy346.pExpr->affinity = (char)yymsp[-3].minor.yy328; } - yygotominor.yy118.zStart = yymsp[-5].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy346.zStart = yymsp[-5].minor.yy0.z; + yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 291: /* raisetype ::= ROLLBACK */ -{yygotominor.yy4 = OE_Rollback;} + case 290: /* raisetype ::= ROLLBACK */ +{yygotominor.yy328 = OE_Rollback;} break; - case 293: /* raisetype ::= FAIL */ -{yygotominor.yy4 = OE_Fail;} + case 292: /* raisetype ::= FAIL */ +{yygotominor.yy328 = OE_Fail;} break; - case 294: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 293: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy65,yymsp[-1].minor.yy328); } break; - case 295: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 294: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy118.pExpr, yymsp[-1].minor.yy118.pExpr, yymsp[0].minor.yy314); + sqlite3Attach(pParse, yymsp[-3].minor.yy346.pExpr, yymsp[-1].minor.yy346.pExpr, yymsp[0].minor.yy132); } break; - case 296: /* cmd ::= DETACH database_kw_opt expr */ + case 295: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy118.pExpr); + sqlite3Detach(pParse, yymsp[0].minor.yy346.pExpr); } break; - case 301: /* cmd ::= REINDEX */ + case 300: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 302: /* cmd ::= REINDEX nm dbnm */ + case 301: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 303: /* cmd ::= ANALYZE */ + case 302: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 304: /* cmd ::= ANALYZE nm dbnm */ + case 303: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 305: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 304: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy65,&yymsp[0].minor.yy0); } break; - case 306: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + case 305: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); } break; - case 307: /* add_column_fullname ::= fullname */ + case 306: /* add_column_fullname ::= fullname */ { pParse->db->lookaside.bEnabled = 0; - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy65); } break; - case 310: /* cmd ::= create_vtab */ + case 309: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 311: /* cmd ::= create_vtab LP vtabarglist RP */ + case 310: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 312: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 311: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy328); } break; - case 315: /* vtabarg ::= */ + case 314: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 317: /* vtabargtoken ::= ANY */ - case 318: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==318); - case 319: /* lp ::= LP */ yytestcase(yyruleno==319); + case 316: /* vtabargtoken ::= ANY */ + case 317: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==317); + case 318: /* lp ::= LP */ yytestcase(yyruleno==318); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 323: /* with ::= */ -{yygotominor.yy451 = 0;} + case 322: /* with ::= */ +{yygotominor.yy59 = 0;} break; - case 324: /* with ::= WITH wqlist */ - case 325: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==325); -{ yygotominor.yy451 = yymsp[0].minor.yy451; } + case 323: /* with ::= WITH wqlist */ + case 324: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==324); +{ yygotominor.yy59 = yymsp[0].minor.yy59; } break; - case 326: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 325: /* wqlist ::= nm idxlist_opt AS LP select RP */ { - yygotominor.yy451 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); + yygotominor.yy59 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3); } break; - case 327: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 326: /* wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP */ { - yygotominor.yy451 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy451, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); + yygotominor.yy59 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy59, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3); } break; default: @@ -130576,30 +119637,29 @@ static void yy_reduce( /* (88) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==88); /* (89) conslist ::= tcons */ yytestcase(yyruleno==89); /* (91) tconscomma ::= */ yytestcase(yyruleno==91); - /* (274) foreach_clause ::= */ yytestcase(yyruleno==274); - /* (275) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==275); - /* (282) tridxby ::= */ yytestcase(yyruleno==282); - /* (299) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==299); - /* (300) database_kw_opt ::= */ yytestcase(yyruleno==300); - /* (308) kwcolumn_opt ::= */ yytestcase(yyruleno==308); - /* (309) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==309); - /* (313) vtabarglist ::= vtabarg */ yytestcase(yyruleno==313); - /* (314) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==314); - /* (316) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==316); - /* (320) anylist ::= */ yytestcase(yyruleno==320); - /* (321) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==321); - /* (322) anylist ::= anylist ANY */ yytestcase(yyruleno==322); + /* (273) foreach_clause ::= */ yytestcase(yyruleno==273); + /* (274) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==274); + /* (281) tridxby ::= */ yytestcase(yyruleno==281); + /* (298) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==298); + /* (299) database_kw_opt ::= */ yytestcase(yyruleno==299); + /* (307) kwcolumn_opt ::= */ yytestcase(yyruleno==307); + /* (308) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==308); + /* (312) vtabarglist ::= vtabarg */ yytestcase(yyruleno==312); + /* (313) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==313); + /* (315) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==315); + /* (319) anylist ::= */ yytestcase(yyruleno==319); + /* (320) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==320); + /* (321) anylist ::= anylist ANY */ yytestcase(yyruleno==321); break; -/********** End reduce actions ************************************************/ }; assert( yyruleno>=0 && yyrulenoyyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - /* If the reduce action popped at least + if( yyact < YYNSTATE ){ +#ifdef NDEBUG + /* If we are not debugging and the reduce action popped at least ** one element off the stack, then we can push the new element back ** onto the stack here, and skip the stack overflow test in yy_shift(). ** That gives a significant speed improvement. */ @@ -130609,12 +119669,13 @@ static void yy_reduce( yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yymsp->minor = yygotominor; - yyTraceShift(yypParser, yyact); - }else{ + }else +#endif + { yy_shift(yypParser,yyact,yygoto,&yygotominor); } }else{ - assert( yyact == YY_ACCEPT_ACTION ); + assert( yyact == YYNSTATE + YYNRULE + 1 ); yy_accept(yypParser); } } @@ -130635,8 +119696,6 @@ static void yy_parse_failed( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ -/************ Begin %parse_failure code ***************************************/ -/************ End %parse_failure code *****************************************/ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ @@ -130651,12 +119710,10 @@ static void yy_syntax_error( ){ sqlite3ParserARG_FETCH; #define TOKEN (yyminor.yy0) -/************ Begin %syntax_error code ****************************************/ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); -/************ End %syntax_error code ******************************************/ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -130675,8 +119732,6 @@ static void yy_accept( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser accepts */ -/*********** Begin %parse_accept code *****************************************/ -/*********** End %parse_accept code *******************************************/ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -130730,12 +119785,6 @@ SQLITE_PRIVATE void sqlite3Parser( yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n", - yyTracePrompt); - } -#endif } yyminorunion.yy0 = yyminor; #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) @@ -130745,19 +119794,18 @@ SQLITE_PRIVATE void sqlite3Parser( #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); } #endif do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + if( yyactyyerrcnt--; yymajor = YYNOCODE; - }else if( yyact <= YY_MAX_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE); + }else if( yyact < YYNSTATE + YYNRULE ){ + yy_reduce(yypParser,yyact-YYNSTATE); }else{ assert( yyact == YY_ERROR_ACTION ); #ifdef YYERRORSYMBOL @@ -130807,7 +119855,7 @@ SQLITE_PRIVATE void sqlite3Parser( yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yystack[yypParser->yyidx].stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) >= YYNSTATE ){ yy_pop_parser_stack(yypParser); } @@ -130857,16 +119905,6 @@ SQLITE_PRIVATE void sqlite3Parser( #endif } }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); -#ifndef NDEBUG - if( yyTraceFILE ){ - int i; - fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', - yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"]\n"); - } -#endif return; } @@ -130889,7 +119927,6 @@ SQLITE_PRIVATE void sqlite3Parser( ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. */ -/* #include "sqliteInt.h" */ /* #include */ /* @@ -130952,7 +119989,7 @@ const unsigned char ebcdicToAscii[] = { ** on platforms with limited memory. */ /* Hash score: 182 */ -static int keywordCode(const char *z, int n, int *pType){ +static int keywordCode(const char *z, int n){ /* zText[] encodes 834 bytes of keywords in 554 bytes */ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ @@ -131073,145 +120110,143 @@ static int keywordCode(const char *z, int n, int *pType){ TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, }; int h, i; - if( n>=2 ){ - h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; - for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ - if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ - testcase( i==0 ); /* REINDEX */ - testcase( i==1 ); /* INDEXED */ - testcase( i==2 ); /* INDEX */ - testcase( i==3 ); /* DESC */ - testcase( i==4 ); /* ESCAPE */ - testcase( i==5 ); /* EACH */ - testcase( i==6 ); /* CHECK */ - testcase( i==7 ); /* KEY */ - testcase( i==8 ); /* BEFORE */ - testcase( i==9 ); /* FOREIGN */ - testcase( i==10 ); /* FOR */ - testcase( i==11 ); /* IGNORE */ - testcase( i==12 ); /* REGEXP */ - testcase( i==13 ); /* EXPLAIN */ - testcase( i==14 ); /* INSTEAD */ - testcase( i==15 ); /* ADD */ - testcase( i==16 ); /* DATABASE */ - testcase( i==17 ); /* AS */ - testcase( i==18 ); /* SELECT */ - testcase( i==19 ); /* TABLE */ - testcase( i==20 ); /* LEFT */ - testcase( i==21 ); /* THEN */ - testcase( i==22 ); /* END */ - testcase( i==23 ); /* DEFERRABLE */ - testcase( i==24 ); /* ELSE */ - testcase( i==25 ); /* EXCEPT */ - testcase( i==26 ); /* TRANSACTION */ - testcase( i==27 ); /* ACTION */ - testcase( i==28 ); /* ON */ - testcase( i==29 ); /* NATURAL */ - testcase( i==30 ); /* ALTER */ - testcase( i==31 ); /* RAISE */ - testcase( i==32 ); /* EXCLUSIVE */ - testcase( i==33 ); /* EXISTS */ - testcase( i==34 ); /* SAVEPOINT */ - testcase( i==35 ); /* INTERSECT */ - testcase( i==36 ); /* TRIGGER */ - testcase( i==37 ); /* REFERENCES */ - testcase( i==38 ); /* CONSTRAINT */ - testcase( i==39 ); /* INTO */ - testcase( i==40 ); /* OFFSET */ - testcase( i==41 ); /* OF */ - testcase( i==42 ); /* SET */ - testcase( i==43 ); /* TEMPORARY */ - testcase( i==44 ); /* TEMP */ - testcase( i==45 ); /* OR */ - testcase( i==46 ); /* UNIQUE */ - testcase( i==47 ); /* QUERY */ - testcase( i==48 ); /* WITHOUT */ - testcase( i==49 ); /* WITH */ - testcase( i==50 ); /* OUTER */ - testcase( i==51 ); /* RELEASE */ - testcase( i==52 ); /* ATTACH */ - testcase( i==53 ); /* HAVING */ - testcase( i==54 ); /* GROUP */ - testcase( i==55 ); /* UPDATE */ - testcase( i==56 ); /* BEGIN */ - testcase( i==57 ); /* INNER */ - testcase( i==58 ); /* RECURSIVE */ - testcase( i==59 ); /* BETWEEN */ - testcase( i==60 ); /* NOTNULL */ - testcase( i==61 ); /* NOT */ - testcase( i==62 ); /* NO */ - testcase( i==63 ); /* NULL */ - testcase( i==64 ); /* LIKE */ - testcase( i==65 ); /* CASCADE */ - testcase( i==66 ); /* ASC */ - testcase( i==67 ); /* DELETE */ - testcase( i==68 ); /* CASE */ - testcase( i==69 ); /* COLLATE */ - testcase( i==70 ); /* CREATE */ - testcase( i==71 ); /* CURRENT_DATE */ - testcase( i==72 ); /* DETACH */ - testcase( i==73 ); /* IMMEDIATE */ - testcase( i==74 ); /* JOIN */ - testcase( i==75 ); /* INSERT */ - testcase( i==76 ); /* MATCH */ - testcase( i==77 ); /* PLAN */ - testcase( i==78 ); /* ANALYZE */ - testcase( i==79 ); /* PRAGMA */ - testcase( i==80 ); /* ABORT */ - testcase( i==81 ); /* VALUES */ - testcase( i==82 ); /* VIRTUAL */ - testcase( i==83 ); /* LIMIT */ - testcase( i==84 ); /* WHEN */ - testcase( i==85 ); /* WHERE */ - testcase( i==86 ); /* RENAME */ - testcase( i==87 ); /* AFTER */ - testcase( i==88 ); /* REPLACE */ - testcase( i==89 ); /* AND */ - testcase( i==90 ); /* DEFAULT */ - testcase( i==91 ); /* AUTOINCREMENT */ - testcase( i==92 ); /* TO */ - testcase( i==93 ); /* IN */ - testcase( i==94 ); /* CAST */ - testcase( i==95 ); /* COLUMN */ - testcase( i==96 ); /* COMMIT */ - testcase( i==97 ); /* CONFLICT */ - testcase( i==98 ); /* CROSS */ - testcase( i==99 ); /* CURRENT_TIMESTAMP */ - testcase( i==100 ); /* CURRENT_TIME */ - testcase( i==101 ); /* PRIMARY */ - testcase( i==102 ); /* DEFERRED */ - testcase( i==103 ); /* DISTINCT */ - testcase( i==104 ); /* IS */ - testcase( i==105 ); /* DROP */ - testcase( i==106 ); /* FAIL */ - testcase( i==107 ); /* FROM */ - testcase( i==108 ); /* FULL */ - testcase( i==109 ); /* GLOB */ - testcase( i==110 ); /* BY */ - testcase( i==111 ); /* IF */ - testcase( i==112 ); /* ISNULL */ - testcase( i==113 ); /* ORDER */ - testcase( i==114 ); /* RESTRICT */ - testcase( i==115 ); /* RIGHT */ - testcase( i==116 ); /* ROLLBACK */ - testcase( i==117 ); /* ROW */ - testcase( i==118 ); /* UNION */ - testcase( i==119 ); /* USING */ - testcase( i==120 ); /* VACUUM */ - testcase( i==121 ); /* VIEW */ - testcase( i==122 ); /* INITIALLY */ - testcase( i==123 ); /* ALL */ - *pType = aCode[i]; - break; - } + if( n<2 ) return TK_ID; + h = ((charMap(z[0])*4) ^ + (charMap(z[n-1])*3) ^ + n) % 127; + for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ + if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ + testcase( i==0 ); /* REINDEX */ + testcase( i==1 ); /* INDEXED */ + testcase( i==2 ); /* INDEX */ + testcase( i==3 ); /* DESC */ + testcase( i==4 ); /* ESCAPE */ + testcase( i==5 ); /* EACH */ + testcase( i==6 ); /* CHECK */ + testcase( i==7 ); /* KEY */ + testcase( i==8 ); /* BEFORE */ + testcase( i==9 ); /* FOREIGN */ + testcase( i==10 ); /* FOR */ + testcase( i==11 ); /* IGNORE */ + testcase( i==12 ); /* REGEXP */ + testcase( i==13 ); /* EXPLAIN */ + testcase( i==14 ); /* INSTEAD */ + testcase( i==15 ); /* ADD */ + testcase( i==16 ); /* DATABASE */ + testcase( i==17 ); /* AS */ + testcase( i==18 ); /* SELECT */ + testcase( i==19 ); /* TABLE */ + testcase( i==20 ); /* LEFT */ + testcase( i==21 ); /* THEN */ + testcase( i==22 ); /* END */ + testcase( i==23 ); /* DEFERRABLE */ + testcase( i==24 ); /* ELSE */ + testcase( i==25 ); /* EXCEPT */ + testcase( i==26 ); /* TRANSACTION */ + testcase( i==27 ); /* ACTION */ + testcase( i==28 ); /* ON */ + testcase( i==29 ); /* NATURAL */ + testcase( i==30 ); /* ALTER */ + testcase( i==31 ); /* RAISE */ + testcase( i==32 ); /* EXCLUSIVE */ + testcase( i==33 ); /* EXISTS */ + testcase( i==34 ); /* SAVEPOINT */ + testcase( i==35 ); /* INTERSECT */ + testcase( i==36 ); /* TRIGGER */ + testcase( i==37 ); /* REFERENCES */ + testcase( i==38 ); /* CONSTRAINT */ + testcase( i==39 ); /* INTO */ + testcase( i==40 ); /* OFFSET */ + testcase( i==41 ); /* OF */ + testcase( i==42 ); /* SET */ + testcase( i==43 ); /* TEMPORARY */ + testcase( i==44 ); /* TEMP */ + testcase( i==45 ); /* OR */ + testcase( i==46 ); /* UNIQUE */ + testcase( i==47 ); /* QUERY */ + testcase( i==48 ); /* WITHOUT */ + testcase( i==49 ); /* WITH */ + testcase( i==50 ); /* OUTER */ + testcase( i==51 ); /* RELEASE */ + testcase( i==52 ); /* ATTACH */ + testcase( i==53 ); /* HAVING */ + testcase( i==54 ); /* GROUP */ + testcase( i==55 ); /* UPDATE */ + testcase( i==56 ); /* BEGIN */ + testcase( i==57 ); /* INNER */ + testcase( i==58 ); /* RECURSIVE */ + testcase( i==59 ); /* BETWEEN */ + testcase( i==60 ); /* NOTNULL */ + testcase( i==61 ); /* NOT */ + testcase( i==62 ); /* NO */ + testcase( i==63 ); /* NULL */ + testcase( i==64 ); /* LIKE */ + testcase( i==65 ); /* CASCADE */ + testcase( i==66 ); /* ASC */ + testcase( i==67 ); /* DELETE */ + testcase( i==68 ); /* CASE */ + testcase( i==69 ); /* COLLATE */ + testcase( i==70 ); /* CREATE */ + testcase( i==71 ); /* CURRENT_DATE */ + testcase( i==72 ); /* DETACH */ + testcase( i==73 ); /* IMMEDIATE */ + testcase( i==74 ); /* JOIN */ + testcase( i==75 ); /* INSERT */ + testcase( i==76 ); /* MATCH */ + testcase( i==77 ); /* PLAN */ + testcase( i==78 ); /* ANALYZE */ + testcase( i==79 ); /* PRAGMA */ + testcase( i==80 ); /* ABORT */ + testcase( i==81 ); /* VALUES */ + testcase( i==82 ); /* VIRTUAL */ + testcase( i==83 ); /* LIMIT */ + testcase( i==84 ); /* WHEN */ + testcase( i==85 ); /* WHERE */ + testcase( i==86 ); /* RENAME */ + testcase( i==87 ); /* AFTER */ + testcase( i==88 ); /* REPLACE */ + testcase( i==89 ); /* AND */ + testcase( i==90 ); /* DEFAULT */ + testcase( i==91 ); /* AUTOINCREMENT */ + testcase( i==92 ); /* TO */ + testcase( i==93 ); /* IN */ + testcase( i==94 ); /* CAST */ + testcase( i==95 ); /* COLUMN */ + testcase( i==96 ); /* COMMIT */ + testcase( i==97 ); /* CONFLICT */ + testcase( i==98 ); /* CROSS */ + testcase( i==99 ); /* CURRENT_TIMESTAMP */ + testcase( i==100 ); /* CURRENT_TIME */ + testcase( i==101 ); /* PRIMARY */ + testcase( i==102 ); /* DEFERRED */ + testcase( i==103 ); /* DISTINCT */ + testcase( i==104 ); /* IS */ + testcase( i==105 ); /* DROP */ + testcase( i==106 ); /* FAIL */ + testcase( i==107 ); /* FROM */ + testcase( i==108 ); /* FULL */ + testcase( i==109 ); /* GLOB */ + testcase( i==110 ); /* BY */ + testcase( i==111 ); /* IF */ + testcase( i==112 ); /* ISNULL */ + testcase( i==113 ); /* ORDER */ + testcase( i==114 ); /* RESTRICT */ + testcase( i==115 ); /* RIGHT */ + testcase( i==116 ); /* ROLLBACK */ + testcase( i==117 ); /* ROW */ + testcase( i==118 ); /* UNION */ + testcase( i==119 ); /* USING */ + testcase( i==120 ); /* VACUUM */ + testcase( i==121 ); /* VIEW */ + testcase( i==122 ); /* INITIALLY */ + testcase( i==123 ); /* ALL */ + return aCode[i]; } } - return n; + return TK_ID; } SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ - int id = TK_ID; - keywordCode((char*)z, n, &id); - return id; + return keywordCode((char*)z, n); } #define SQLITE_N_KEYWORD 124 @@ -131231,7 +120266,7 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ ** end result. ** ** Ticket #1066. the SQL standard does not allow '$' in the -** middle of identifiers. But many SQL implementations do. +** middle of identfiers. But many SQL implementations do. ** SQLite will allow '$' in identifiers for compatibility. ** But the feature is undocumented. */ @@ -131257,11 +120292,6 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = { #define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) #endif -/* Make the IdChar function accessible from ctime.c */ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } -#endif - /* ** Return the length of the token that begins at z[0]. @@ -131429,12 +120459,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); testcase( z[0]=='9' ); *tokenType = TK_INTEGER; -#ifndef SQLITE_OMIT_HEX_INTEGER - if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ - for(i=3; sqlite3Isxdigit(z[i]); i++){} - return i; - } -#endif for(i=0; sqlite3Isdigit(z[i]); i++){} #ifndef SQLITE_OMIT_FLOATING_POINT if( z[i]=='.' ){ @@ -131523,8 +120547,8 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ break; } for(i=1; IdChar(z[i]); i++){} - *tokenType = TK_ID; - return keywordCode((char*)z, i, tokenType); + *tokenType = keywordCode((char*)z, i); + return i; } } *tokenType = TK_ILLEGAL; @@ -131548,7 +120572,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ - assert( zSql!=0 ); + mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; @@ -131557,8 +120581,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr pParse->zTail = zSql; i = 0; assert( pzErrMsg!=0 ); - /* sqlite3ParserTrace(stdout, "parser: "); */ - pEngine = sqlite3ParserAlloc(sqlite3Malloc); + pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); if( pEngine==0 ){ db->mallocFailed = 1; return SQLITE_NOMEM; @@ -131570,7 +120593,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->azVar==0 ); enableLookaside = db->lookaside.bEnabled; if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; - while( zSql[i]!=0 ){ + while( !db->mallocFailed && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); @@ -131579,42 +120602,48 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr pParse->rc = SQLITE_TOOBIG; break; } - if( tokenType>=TK_SPACE ){ - assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); - if( db->u1.isInterrupted ){ - sqlite3ErrorMsg(pParse, "interrupt"); - pParse->rc = SQLITE_INTERRUPT; + switch( tokenType ){ + case TK_SPACE: { + if( db->u1.isInterrupted ){ + sqlite3ErrorMsg(pParse, "interrupt"); + pParse->rc = SQLITE_INTERRUPT; + goto abort_parse; + } break; } - if( tokenType==TK_ILLEGAL ){ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", + case TK_ILLEGAL: { + sqlite3DbFree(db, *pzErrMsg); + *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", &pParse->sLastToken); + nErr++; + goto abort_parse; + } + case TK_SEMI: { + pParse->zTail = &zSql[i]; + /* Fall thru into the default case */ + } + default: { + sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); + lastTokenParsed = tokenType; + if( pParse->rc!=SQLITE_OK ){ + goto abort_parse; + } break; } - }else{ - if( tokenType==TK_SEMI ) pParse->zTail = &zSql[i]; - sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); - lastTokenParsed = tokenType; - if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; } } - assert( nErr==0 ); - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - assert( zSql[i]==0 ); +abort_parse: + if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } - if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); - } + sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); } #ifdef YYTRACKMAXSTACKDEPTH - sqlite3_mutex_enter(sqlite3MallocMutex()); - sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, + sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); - sqlite3_mutex_leave(sqlite3MallocMutex()); #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); db->lookaside.bEnabled = enableLookaside; @@ -131622,7 +120651,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr pParse->rc = SQLITE_NOMEM; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ - pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); + sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); } assert( pzErrMsg!=0 ); if( pParse->zErrMsg ){ @@ -131654,7 +120683,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr sqlite3DeleteTable(db, pParse->pNewTable); } - sqlite3WithDelete(db, pParse->pWithToFree); + if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith); sqlite3DeleteTrigger(db, pParse->pNewTrigger); for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); sqlite3DbFree(db, pParse->azVar); @@ -131668,7 +120697,9 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } - assert( nErr==0 || pParse->rc!=SQLITE_OK ); + if( nErr>0 && pParse->rc==SQLITE_OK ){ + pParse->rc = SQLITE_ERROR; + } return nErr; } @@ -131692,7 +120723,6 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr ** separating it out, the code will be automatically omitted from ** static links that do not use it. */ -/* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_COMPLETE /* @@ -131746,7 +120776,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** a statement. ** ** (4) CREATE The keyword CREATE has been seen at the beginning of a -** statement, possibly preceded by EXPLAIN and/or followed by +** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (5) TRIGGER We are in the middle of a trigger definition that must be @@ -131756,7 +120786,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** the end of a trigger definition. ** ** (7) END We've seen the ";END" of the ";END;" that occurs at the end -** of a trigger definition. +** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: @@ -131777,7 +120807,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ +SQLITE_API int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ @@ -131799,7 +120829,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ }; #else /* If triggers are not supported by this compile then the statement machine - ** used to detect the end of a statement is much simpler + ** used to detect the end of a statement is much simplier */ static const u8 trans[3][3] = { /* Token: */ @@ -131810,13 +120840,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ }; #endif /* SQLITE_OMIT_TRIGGER */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( zSql==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - while( *zSql ){ switch( *zSql ){ case ';': { /* A semicolon */ @@ -131942,10 +120965,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){ ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. */ -SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ +SQLITE_API int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; - int rc; + int rc = SQLITE_NOMEM; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); @@ -131960,7 +120983,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ rc = SQLITE_NOMEM; } sqlite3ValueFree(pVal); - return rc & 0xff; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_OMIT_COMPLETE */ @@ -131983,7 +121006,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. */ -/* #include "sqliteInt.h" */ #ifdef SQLITE_ENABLE_FTS3 /************** Include fts3.h in the middle of main.c ***********************/ @@ -132003,7 +121025,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){ ** This header file is used by programs that want to link against the ** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. */ -/* #include "sqlite3.h" */ #if 0 extern "C" { @@ -132036,7 +121057,6 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); ** This header file is used by programs that want to link against the ** RTREE library. All it does is declare the sqlite3RtreeInit() interface. */ -/* #include "sqlite3.h" */ #if 0 extern "C" { @@ -132069,7 +121089,6 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); ** This header file is used by programs that want to link against the ** ICU extension. All it does is declare the sqlite3IcuInit() interface. */ -/* #include "sqlite3.h" */ #if 0 extern "C" { @@ -132085,12 +121104,6 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); /************** End of sqliteicu.h *******************************************/ /************** Continuing where we left off in main.c ***********************/ #endif -#ifdef SQLITE_ENABLE_JSON1 -SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*); -#endif -#ifdef SQLITE_ENABLE_FTS5 -SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); -#endif #ifndef SQLITE_AMALGAMATION /* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant @@ -132102,36 +121115,24 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; /* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns ** a pointer to the to the sqlite3_version[] string constant. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void){ return sqlite3_version; } +SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } /* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the ** SQLITE_SOURCE_ID C preprocessor macro. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. */ -SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } /* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns ** zero if and only if SQLite was compiled with mutexing code omitted due to ** the SQLITE_THREADSAFE compile-time option being set to 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } - -/* -** When compiling the test fixture or with debugging enabled (on Win32), -** this variable being set to non-zero will cause OSTRACE macros to emit -** extra diagnostic information. -*/ -#ifdef SQLITE_HAVE_OS_TRACE -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -#endif +SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) /* @@ -132140,7 +121141,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE ** I/O active are written using this function. These messages ** are intended for debugging activity only. */ -SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0; +SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; #endif /* @@ -132192,7 +121193,7 @@ SQLITE_API char *sqlite3_data_directory = 0; ** * Recursive calls to this routine from thread X return immediately ** without blocking. */ -SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ +SQLITE_API int sqlite3_initialize(void){ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ int rc; /* Result code */ #ifdef SQLITE_EXTRA_INIT @@ -132206,11 +121207,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ } #endif - /* If the following assert() fails on some obscure processor/compiler - ** combination, the work-around is to set the correct pointer - ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ - assert( SQLITE_PTRSIZE==sizeof(char*) ); - /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end @@ -132280,12 +121276,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); sqlite3GlobalConfig.inProgress = 1; -#ifdef SQLITE_ENABLE_SQLLOG - { - extern void sqlite3_init_sqllog(void); - sqlite3_init_sqllog(); - } -#endif memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); sqlite3RegisterGlobalFunctions(); if( sqlite3GlobalConfig.isPCacheInit==0 ){ @@ -132359,14 +121349,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){ ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ -SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ -#ifdef SQLITE_OMIT_WSD - int rc = sqlite3_wsd_init(4096, 24); - if( rc!=SQLITE_OK ){ - return rc; - } -#endif - +SQLITE_API int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ #ifdef SQLITE_EXTRA_SHUTDOWN void SQLITE_EXTRA_SHUTDOWN(void); @@ -132413,7 +121396,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){ ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ -SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ +SQLITE_API int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; @@ -132425,43 +121408,33 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ switch( op ){ /* Mutex configuration options are only available in a threadsafe - ** compile. + ** compile. */ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ +#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 case SQLITE_CONFIG_SINGLETHREAD: { - /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to - ** Single-thread. */ - sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ + /* Disable all mutexing */ + sqlite3GlobalConfig.bCoreMutex = 0; + sqlite3GlobalConfig.bFullMutex = 0; break; } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ case SQLITE_CONFIG_MULTITHREAD: { - /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to - ** Multi-thread. */ - sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ + /* Disable mutexing of database connections */ + /* Enable mutexing of core data structures */ + sqlite3GlobalConfig.bCoreMutex = 1; + sqlite3GlobalConfig.bFullMutex = 0; break; } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ case SQLITE_CONFIG_SERIALIZED: { - /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to - ** Serialized. */ - sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ - sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ + /* Enable all mutexing */ + sqlite3GlobalConfig.bCoreMutex = 1; + sqlite3GlobalConfig.bFullMutex = 1; break; } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ case SQLITE_CONFIG_MUTEX: { /* Specify an alternative mutex implementation */ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); break; } -#endif -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */ case SQLITE_CONFIG_GETMUTEX: { /* Retrieve the current mutex implementation */ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; @@ -132469,62 +121442,37 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ } #endif + case SQLITE_CONFIG_MALLOC: { - /* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a - ** single argument which is a pointer to an instance of the - ** sqlite3_mem_methods structure. The argument specifies alternative - ** low-level memory allocation routines to be used in place of the memory - ** allocation routines built into SQLite. */ + /* Specify an alternative malloc implementation */ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); break; } case SQLITE_CONFIG_GETMALLOC: { - /* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a - ** single argument which is a pointer to an instance of the - ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is - ** filled with the currently defined memory allocation routines. */ + /* Retrieve the current malloc() implementation */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { - /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes - ** single argument of type int, interpreted as a boolean, which enables - ** or disables the collection of memory allocation statistics. */ + /* Enable or disable the malloc status collection */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } case SQLITE_CONFIG_SCRATCH: { - /* EVIDENCE-OF: R-08404-60887 There are three arguments to - ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from - ** which the scratch allocations will be drawn, the size of each scratch - ** allocation (sz), and the maximum number of scratch allocations (N). */ + /* Designate a buffer for scratch memory space */ sqlite3GlobalConfig.pScratch = va_arg(ap, void*); sqlite3GlobalConfig.szScratch = va_arg(ap, int); sqlite3GlobalConfig.nScratch = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { - /* EVIDENCE-OF: R-18761-36601 There are three arguments to - ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem), - ** the size of each page cache line (sz), and the number of cache lines - ** (N). */ + /* Designate a buffer for page cache memory space */ sqlite3GlobalConfig.pPage = va_arg(ap, void*); sqlite3GlobalConfig.szPage = va_arg(ap, int); sqlite3GlobalConfig.nPage = va_arg(ap, int); break; } - case SQLITE_CONFIG_PCACHE_HDRSZ: { - /* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes - ** a single parameter which is a pointer to an integer and writes into - ** that integer the number of extra bytes per page required for each page - ** in SQLITE_CONFIG_PAGECACHE. */ - *va_arg(ap, int*) = - sqlite3HeaderSizeBtree() + - sqlite3HeaderSizePcache() + - sqlite3HeaderSizePcache1(); - break; - } case SQLITE_CONFIG_PCACHE: { /* no-op */ @@ -132537,18 +121485,11 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ } case SQLITE_CONFIG_PCACHE2: { - /* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a - ** single argument which is a pointer to an sqlite3_pcache_methods2 - ** object. This object specifies the interface to a custom page cache - ** implementation. */ + /* Specify an alternative page cache implementation */ sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); break; } case SQLITE_CONFIG_GETPCACHE2: { - /* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a - ** single argument which is a pointer to an sqlite3_pcache_methods2 - ** object. SQLite copies of the current page cache implementation into - ** that object. */ if( sqlite3GlobalConfig.pcache2.xInit==0 ){ sqlite3PCacheSetDefault(); } @@ -132556,15 +121497,9 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ break; } -/* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only -** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or -** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) case SQLITE_CONFIG_HEAP: { - /* EVIDENCE-OF: R-19854-42126 There are three arguments to - ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the - ** number of bytes in the memory buffer, and the minimum allocation size. - */ + /* Designate a buffer for heap memory space */ sqlite3GlobalConfig.pHeap = va_arg(ap, void*); sqlite3GlobalConfig.nHeap = va_arg(ap, int); sqlite3GlobalConfig.mnReq = va_arg(ap, int); @@ -132577,19 +121512,17 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ } if( sqlite3GlobalConfig.pHeap==0 ){ - /* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer) - ** is NULL, then SQLite reverts to using its default memory allocator - ** (the system malloc() implementation), undoing any prior invocation of - ** SQLITE_CONFIG_MALLOC. - ** - ** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to - ** revert to its default implementation when sqlite3_initialize() is run + /* If the heap pointer is NULL, then restore the malloc implementation + ** back to NULL pointers too. This will cause the malloc to go + ** back to its default implementation when sqlite3_initialize() is + ** run. */ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); }else{ - /* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the - ** alternative memory allocator is engaged to handle all of SQLites - ** memory allocation needs. */ + /* The heap pointer is not NULL, then install one of the + ** mem5.c/mem3.c methods. The enclosing #if guarantees at + ** least one of these methods is currently enabled. + */ #ifdef SQLITE_ENABLE_MEMSYS3 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); #endif @@ -132622,25 +121555,12 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ break; } - /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames - ** can be changed at start-time using the - ** sqlite3_config(SQLITE_CONFIG_URI,1) or - ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. - */ case SQLITE_CONFIG_URI: { - /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single - ** argument of type int. If non-zero, then URI handling is globally - ** enabled. If the parameter is zero, then URI handling is globally - ** disabled. */ sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { - /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN - ** option takes a single integer argument which is interpreted as a - ** boolean in order to enable or disable the use of covering indices for - ** full table scans in the query optimizer. */ sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } @@ -132655,45 +121575,25 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ #endif case SQLITE_CONFIG_MMAP_SIZE: { - /* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit - ** integer (sqlite3_int64) values that are the default mmap size limit - ** (the default setting for PRAGMA mmap_size) and the maximum allowed - ** mmap size limit. */ sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); - /* EVIDENCE-OF: R-53367-43190 If either argument to this option is - ** negative, then that argument is changed to its compile-time default. - ** - ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be - ** silently truncated if necessary so that it does not exceed the - ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE - ** compile-time option. - */ if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ mxMmap = SQLITE_MAX_MMAP_SIZE; } + sqlite3GlobalConfig.mxMmap = mxMmap; if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; if( szMmap>mxMmap) szMmap = mxMmap; - sqlite3GlobalConfig.mxMmap = mxMmap; sqlite3GlobalConfig.szMmap = szMmap; break; } -#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */ +#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) case SQLITE_CONFIG_WIN32_HEAPSIZE: { - /* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit - ** unsigned integer value that specifies the maximum size of the created - ** heap. */ sqlite3GlobalConfig.nHeap = va_arg(ap, int); break; } #endif - case SQLITE_CONFIG_PMASZ: { - sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); - break; - } - default: { rc = SQLITE_ERROR; break; @@ -132715,7 +121615,6 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){ ** the lookaside memory. */ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ -#ifndef SQLITE_OMIT_LOOKASIDE void *pStart; if( db->lookaside.nOut ){ return SQLITE_BUSY; @@ -132766,20 +121665,13 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; } -#endif /* SQLITE_OMIT_LOOKASIDE */ return SQLITE_OK; } /* ** Return the mutex associated with a database connection. */ -SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ return db->mutex; } @@ -132787,12 +121679,8 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ ** Free up as much memory as we can from the given database ** connection. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ +SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ int i; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); for(i=0; inDb; i++){ @@ -132807,40 +121695,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){ return SQLITE_OK; } -/* -** Flush any dirty pages in the pager-cache for any attached database -** to disk. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3 *db){ - int i; - int rc = SQLITE_OK; - int bSeenBusy = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeIsInTrans(pBt) ){ - Pager *pPager = sqlite3BtreePager(pBt); - rc = sqlite3PagerFlush(pPager); - if( rc==SQLITE_BUSY ){ - bSeenBusy = 1; - rc = SQLITE_OK; - } - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc); -} - /* ** Configuration settings for an individual database connection */ -SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){ +SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; va_start(ap, op); @@ -132912,20 +121770,13 @@ static int binCollFunc( ){ int rc, n; n = nKey1lastRowid; } /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API int sqlite3_changes(sqlite3 *db){ return db->nChange; } /* ** Return the number of changes since the database handle was opened. */ -SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API int sqlite3_total_changes(sqlite3 *db){ return db->nTotalChange; } @@ -133035,23 +121868,17 @@ static void functionDestroy(sqlite3 *db, FuncDef *p){ static void disconnectAllVtab(sqlite3 *db){ #ifndef SQLITE_OMIT_VIRTUALTABLE int i; - HashElem *p; sqlite3BtreeEnterAll(db); for(i=0; inDb; i++){ Schema *pSchema = db->aDb[i].pSchema; if( db->aDb[i].pSchema ){ + HashElem *p; for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ Table *pTab = (Table *)sqliteHashData(p); if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); } } } - for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){ - Module *pMod = (Module *)sqliteHashData(p); - if( pMod->pEpoTab ){ - sqlite3VtabDisconnect(db, pMod->pEpoTab); - } - } sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); #else @@ -133079,8 +121906,6 @@ static int connectionIsBusy(sqlite3 *db){ */ static int sqlite3Close(sqlite3 *db, int forceZombie){ if( !db ){ - /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or - ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */ return SQLITE_OK; } if( !sqlite3SafetyCheckSickOrOk(db) ){ @@ -133104,7 +121929,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** SQLITE_BUSY if the connection can not be closed immediately. */ if( !forceZombie && connectionIsBusy(db) ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to close due to unfinalized " + sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; @@ -133133,8 +121958,8 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** unclosed resources, and arranges for deallocation when the last ** prepare statement or sqlite3_backup closes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } +SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } +SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } /* @@ -133229,19 +122054,14 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ if( pMod->xDestroy ){ pMod->xDestroy(pMod->pAux); } - sqlite3VtabEponymousTableClear(db, pMod); sqlite3DbFree(db, pMod); } sqlite3HashClear(&db->aModule); #endif - sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ + sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); -#if SQLITE_USER_AUTHENTICATION - sqlite3_free(db->auth.zAuthUser); - sqlite3_free(db->auth.zAuthPW); -#endif db->magic = SQLITE_MAGIC_ERROR; @@ -133264,15 +122084,13 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ /* ** Rollback all database files. If tripCode is not SQLITE_OK, then -** any write cursors are invalidated ("tripped" - as in "tripping a circuit +** any open cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further -** attempts to use that cursor. Read cursors remain open and valid -** but are "saved" in case the table pages are moved around. +** attempts to use that cursor. */ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; - int schemaChange; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); @@ -133283,7 +122101,6 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** the database rollback and schema reset, which can cause false ** corruption reports in some cases. */ sqlite3BtreeEnterAll(db); - schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; for(i=0; inDb; i++){ Btree *p = db->aDb[i].pBt; @@ -133291,7 +122108,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } - sqlite3BtreeRollback(p, tripCode, !schemaChange); + sqlite3BtreeRollback(p, tripCode); } } sqlite3VtabRollback(db); @@ -133318,7 +122135,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** Return a static string containing the name corresponding to the error code ** specified in the argument. */ -#if defined(SQLITE_NEED_ERR_NAME) +#if defined(SQLITE_TEST) SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ const char *zName = 0; int i, origRc = rc; @@ -133353,6 +122170,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break; case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break; case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break; + case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break; case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break; case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break; case SQLITE_IOERR_CHECKRESERVEDLOCK: @@ -133484,7 +122302,7 @@ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ int count /* Number of times table has been busy */ ){ -#if SQLITE_OS_WIN || HAVE_USLEEP +#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) static const u8 delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; static const u8 totals[] = @@ -133542,14 +122360,11 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( +SQLITE_API int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; @@ -133565,18 +122380,12 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler( ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ -SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( +SQLITE_API void sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), void *pArg ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; @@ -133596,10 +122405,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler( ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ -SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif +SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; @@ -133612,13 +122418,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){ /* ** Cause any pending operation to stop at its earliest opportunity. */ -SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif +SQLITE_API void sqlite3_interrupt(sqlite3 *db){ db->u1.isInterrupted = 1; } @@ -133693,7 +122493,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, + sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE_BUSY; @@ -133729,7 +122529,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc( /* ** Create new user functions. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_function( +SQLITE_API int sqlite3_create_function( sqlite3 *db, const char *zFunc, int nArg, @@ -133743,7 +122543,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function( xFinal, 0); } -SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( +SQLITE_API int sqlite3_create_function_v2( sqlite3 *db, const char *zFunc, int nArg, @@ -133756,12 +122556,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( ){ int rc = SQLITE_ERROR; FuncDestructor *pArg = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif sqlite3_mutex_enter(db->mutex); if( xDestroy ){ pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); @@ -133786,7 +122580,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2( } #ifndef SQLITE_OMIT_UTF16 -SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( +SQLITE_API int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, @@ -133798,10 +122592,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( ){ int rc; char *zFunc8; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); @@ -133826,19 +122616,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_function16( ** A global function must exist in order for name resolution to work ** properly. */ -SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( +SQLITE_API int sqlite3_overload_function( sqlite3 *db, const char *zName, int nArg ){ int nName = sqlite3Strlen30(zName); int rc = SQLITE_OK; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ - return SQLITE_MISUSE_BKPT; - } -#endif sqlite3_mutex_enter(db->mutex); if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, @@ -133858,15 +122642,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_overload_function( ** trace is a pointer to a function that is invoked at the start of each ** SQL statement. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ +SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pOld = db->pTraceArg; db->xTrace = xTrace; @@ -133882,19 +122659,12 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*, ** profile is a pointer to a function that is invoked at the conclusion of ** each SQL statement that is run. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_profile( +SQLITE_API void *sqlite3_profile( sqlite3 *db, void (*xProfile)(void*,const char*,sqlite_uint64), void *pArg ){ void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pOld = db->pProfileArg; db->xProfile = xProfile; @@ -133909,19 +122679,12 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_profile( ** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( +SQLITE_API void *sqlite3_commit_hook( sqlite3 *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ ){ void *pOld; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pOld = db->pCommitArg; db->xCommitCallback = xCallback; @@ -133934,19 +122697,12 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( +SQLITE_API void *sqlite3_update_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ ){ void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pRet = db->pUpdateArg; db->xUpdateCallback = xCallback; @@ -133959,19 +122715,12 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( ** Register a callback to be invoked each time a transaction is rolled ** back by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook( +SQLITE_API void *sqlite3_rollback_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*), /* Callback function */ void *pArg /* Argument to the function */ ){ void *pRet; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pRet = db->pRollbackArg; db->xRollbackCallback = xCallback; @@ -134013,14 +122762,11 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook( ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism ** configured by this function. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ #ifdef SQLITE_OMIT_WAL UNUSED_PARAMETER(db); UNUSED_PARAMETER(nFrame); #else -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif if( nFrame>0 ){ sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); }else{ @@ -134034,19 +122780,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. */ -SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( +SQLITE_API void *sqlite3_wal_hook( sqlite3 *db, /* Attach the hook to this db handle */ int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ ){ #ifndef SQLITE_OMIT_WAL void *pRet; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); pRet = db->pWalArg; db->xWalCallback = xCallback; @@ -134061,7 +122801,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook( /* ** Checkpoint database zDb. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( +SQLITE_API int sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ @@ -134074,21 +122814,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( int rc; /* Return code */ int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif - /* Initialize the output variables to -1 in case an error occurs. */ if( pnLog ) *pnLog = -1; if( pnCkpt ) *pnCkpt = -1; - assert( SQLITE_CHECKPOINT_PASSIVE==0 ); - assert( SQLITE_CHECKPOINT_FULL==1 ); - assert( SQLITE_CHECKPOINT_RESTART==2 ); - assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); - if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ - /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint - ** mode: */ + assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); + assert( SQLITE_CHECKPOINT_FULLSQLITE_CHECKPOINT_RESTART ){ return SQLITE_MISUSE; } @@ -134098,11 +122831,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( } if( iDb<0 ){ rc = SQLITE_ERROR; - sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); + sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); }else{ - db->busyHandler.nBusy = 0; rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); - sqlite3Error(db, rc); + sqlite3Error(db, rc, 0); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); @@ -134116,10 +122848,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2( ** to contains a zero-length string, all attached databases are ** checkpointed. */ -SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ - /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to - ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ - return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ + return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); } #ifndef SQLITE_OMIT_WAL @@ -134194,11 +122924,9 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ return ( db->temp_store!=1 ); #endif #if SQLITE_TEMP_STORE==3 - UNUSED_PARAMETER(db); return 1; #endif #if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 - UNUSED_PARAMETER(db); return 0; #endif } @@ -134207,7 +122935,7 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ ** Return UTF-8 encoded English language explanation of the most recent ** error. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ +SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); @@ -134235,7 +122963,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){ ** Return UTF-16 encoded English language explanation of the most recent ** error. */ -SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ +SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ static const u16 outOfMem[] = { 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 }; @@ -134261,7 +122989,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3ErrorWithMsg(db, db->errCode, sqlite3ErrStr(db->errCode)); + sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode)); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() @@ -134280,7 +123008,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){ ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ -SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -134289,7 +123017,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){ } return db->errCode & db->errMask; } -SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ if( db && !sqlite3SafetyCheckSickOrOk(db) ){ return SQLITE_MISUSE_BKPT; } @@ -134304,10 +123032,36 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){ ** argument. For now, this simply calls the internal sqlite3ErrStr() ** function. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int rc){ +SQLITE_API const char *sqlite3_errstr(int rc){ return sqlite3ErrStr(rc); } +/* +** Invalidate all cached KeyInfo objects for database connection "db" +*/ +static void invalidateCachedKeyInfo(sqlite3 *db){ + Db *pDb; /* A single database */ + int iDb; /* The database index number */ + HashElem *k; /* For looping over tables in pDb */ + Table *pTab; /* A table in the database */ + Index *pIdx; /* Each index */ + + for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ + if( pDb->pBt==0 ) continue; + sqlite3BtreeEnter(pDb->pBt); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ + pTab = (Table*)sqliteHashData(k); + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ + sqlite3KeyInfoUnref(pIdx->pKeyInfo); + pIdx->pKeyInfo = 0; + } + } + } + sqlite3BtreeLeave(pDb->pBt); + } +} + /* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. @@ -134322,6 +123076,7 @@ static int createCollation( ){ CollSeq *pColl; int enc2; + int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); @@ -134346,11 +123101,12 @@ static int createCollation( pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->nVdbeActive ){ - sqlite3ErrorWithMsg(db, SQLITE_BUSY, + sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); + invalidateCachedKeyInfo(db); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), @@ -134359,7 +123115,7 @@ static int createCollation( ** to be called. */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ - CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName); + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; @@ -134379,7 +123135,7 @@ static int createCollation( pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); - sqlite3Error(db, SQLITE_OK); + sqlite3Error(db, SQLITE_OK, 0); return SQLITE_OK; } @@ -134399,9 +123155,8 @@ static const int aHardLimit[] = { SQLITE_MAX_FUNCTION_ARG, SQLITE_MAX_ATTACHED, SQLITE_MAX_LIKE_PATTERN_LENGTH, - SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */ + SQLITE_MAX_VARIABLE_NUMBER, SQLITE_MAX_TRIGGER_DEPTH, - SQLITE_MAX_WORKER_THREADS, }; /* @@ -134425,8 +123180,8 @@ static const int aHardLimit[] = { #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 #endif -#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 -# error SQLITE_MAX_ATTACHED must be between 0 and 125 +#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62 +# error SQLITE_MAX_ATTACHED must be between 0 and 62 #endif #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 @@ -134437,9 +123192,6 @@ static const int aHardLimit[] = { #if SQLITE_MAX_TRIGGER_DEPTH<1 # error SQLITE_MAX_TRIGGER_DEPTH must be at least 1 #endif -#if SQLITE_MAX_WORKER_THREADS<0 || SQLITE_MAX_WORKER_THREADS>50 -# error SQLITE_MAX_WORKER_THREADS must be between 0 and 50 -#endif /* @@ -134452,15 +123204,9 @@ static const int aHardLimit[] = { ** It merely prevents new constructs that exceed the limit ** from forming. */ -SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ +SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ int oldLimit; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME ** there is a hard upper bound set at compile-time by a C preprocessor @@ -134479,8 +123225,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLim SQLITE_MAX_LIKE_PATTERN_LENGTH ); assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS ); - assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) ); + assert( SQLITE_LIMIT_TRIGGER_DEPTH==(SQLITE_N_LIMIT-1) ); if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ @@ -134537,38 +123282,25 @@ SQLITE_PRIVATE int sqlite3ParseUri( assert( *pzErrMsg==0 ); - if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ - || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */ - && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ + if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) + && nUri>=5 && memcmp(zUri, "file:", 5)==0 ){ char *zOpt; int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ - u64 nByte = nUri+2; /* Bytes of space to allocate */ + int nByte = nUri+2; /* Bytes of space to allocate */ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen ** method that there may be extra parameters following the file-name. */ flags |= SQLITE_OPEN_URI; for(iIn=0; iInaLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); - db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; - db->nMaxSorterMmap = 0x7FFFFFFF; db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill #if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX | SQLITE_AutoIndex #endif -#if SQLITE_DEFAULT_CKPTFULLFSYNC - | SQLITE_CkptFullFSync -#endif #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt #endif @@ -134869,12 +123591,6 @@ static int openDatabase( #endif #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS | SQLITE_ForeignKeys -#endif -#if defined(SQLITE_REVERSE_UNORDERED_SELECTS) - | SQLITE_ReverseOrder -#endif -#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) - | SQLITE_CellSizeCk #endif ; sqlite3HashInit(&db->aCollSeq); @@ -134885,30 +123601,26 @@ static int openDatabase( /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. - ** - ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating - ** functions: */ - createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0); - createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0); - createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0); - createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); if( db->mallocFailed ){ goto opendb_out; } - /* EVIDENCE-OF: R-08308-17224 The default collating function for all - ** strings is BINARY. - */ - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0); + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); assert( db->pDfltColl!=0 ); + /* Also add a UTF-8 case-insensitive collation sequence. */ + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); + /* Parse the filename/URI argument. */ db->openFlags = flags; rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); + sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } @@ -134920,15 +123632,13 @@ static int openDatabase( if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; } - sqlite3Error(db, rc); + sqlite3Error(db, rc, 0); goto opendb_out; } - sqlite3BtreeEnter(db->aDb[0].pBt); db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); - if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); - sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); + /* The default safety_level for the main database is 'full'; for the temp ** database it is 'NONE'. This matches the pager layer defaults. */ @@ -134946,7 +123656,7 @@ static int openDatabase( ** database schema yet. This is delayed until the first time the database ** is accessed. */ - sqlite3Error(db, SQLITE_OK); + sqlite3Error(db, SQLITE_OK, 0); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered @@ -134975,18 +123685,12 @@ static int openDatabase( } #endif -#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */ +#ifdef SQLITE_ENABLE_FTS3 if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3Fts3Init(db); } #endif -#ifdef SQLITE_ENABLE_FTS5 - if( !db->mallocFailed && rc==SQLITE_OK ){ - rc = sqlite3Fts5Init(db); - } -#endif - #ifdef SQLITE_ENABLE_ICU if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3IcuInit(db); @@ -134999,18 +123703,6 @@ static int openDatabase( } #endif -#ifdef SQLITE_ENABLE_DBSTAT_VTAB - if( !db->mallocFailed && rc==SQLITE_OK){ - rc = sqlite3DbstatRegister(db); - } -#endif - -#ifdef SQLITE_ENABLE_JSON1 - if( !db->mallocFailed && rc==SQLITE_OK){ - rc = sqlite3Json1Init(db); - } -#endif - /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -135021,7 +123713,7 @@ static int openDatabase( SQLITE_DEFAULT_LOCKING_MODE); #endif - if( rc ) sqlite3Error(db, rc); + if( rc ) sqlite3Error(db, rc, 0); /* Enable the lookaside-malloc subsystem */ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, @@ -135030,9 +123722,9 @@ static int openDatabase( sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); opendb_out: + sqlite3_free(zOpen); if( db ){ - assert( db->mutex!=0 || isThreadsafe==0 - || sqlite3GlobalConfig.bFullMutex==0 ); + assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } rc = sqlite3_errcode(db); @@ -135051,36 +123743,20 @@ opendb_out: sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif -#if defined(SQLITE_HAS_CODEC) - if( rc==SQLITE_OK ){ - const char *zHexKey = sqlite3_uri_parameter(zOpen, "hexkey"); - if( zHexKey && zHexKey[0] ){ - u8 iByte; - int i; - char zKey[40]; - for(i=0, iByte=0; imutex); + assert( !db->mallocFailed ); + rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, 0); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( +SQLITE_API int sqlite3_create_collation_v2( sqlite3* db, const char *zName, int enc, @@ -135154,10 +123834,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( void(*xDel)(void*) ){ int rc; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel); @@ -135170,7 +123846,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2( /* ** Register a new collation sequence with the database handle db. */ -SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( +SQLITE_API int sqlite3_create_collation16( sqlite3* db, const void *zName, int enc, @@ -135179,10 +123855,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ){ int rc = SQLITE_OK; char *zName8; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); @@ -135200,14 +123872,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( +SQLITE_API int sqlite3_collation_needed( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); db->xCollNeeded = xCollNeeded; db->xCollNeeded16 = 0; @@ -135221,14 +123890,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed( ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ -SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( +SQLITE_API int sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) ){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; @@ -135243,7 +123909,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16( ** This function is now an anachronism. It used to be used to recover from a ** malloc() failure, but SQLite now does this automatically. */ -SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ +SQLITE_API int sqlite3_global_recover(void){ return SQLITE_OK; } #endif @@ -135254,20 +123920,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){ ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. */ -SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3 *db){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif +SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ return db->autoCommit; } /* -** The following routines are substitutes for constants SQLITE_CORRUPT, +** The following routines are subtitutes for constants SQLITE_CORRUPT, ** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error -** constants. They serve two purposes: +** constants. They server two purposes: ** ** 1. Serve as a convenient place to set a breakpoint in a debugger ** to detect when version error conditions occurs. @@ -135306,7 +123966,7 @@ SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ ** SQLite no longer uses thread-specific data so this routine is now a ** no-op. It is retained for historical compatibility. */ -SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ +SQLITE_API void sqlite3_thread_cleanup(void){ } #endif @@ -135314,7 +123974,8 @@ SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){ ** Return meta information about a specific column of a database table. ** See comment in sqlite3.h (sqlite.h.in) for details. */ -SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( +#ifdef SQLITE_ENABLE_COLUMN_METADATA +SQLITE_API int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ @@ -135329,20 +123990,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( char *zErrMsg = 0; Table *pTab = 0; Column *pCol = 0; - int iCol = 0; + int iCol; + char const *zDataType = 0; char const *zCollSeq = 0; int notnull = 0; int primarykey = 0; int autoinc = 0; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - /* Ensure the database schema has been loaded */ sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); @@ -135359,8 +124014,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( } /* Find the column for which info is requested */ - if( zColumnName==0 ){ - /* Query for existance of table only */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } }else{ for(iCol=0; iColnCol; iCol++){ pCol = &pTab->aCol[iCol]; @@ -135369,13 +124027,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( } } if( iCol==pTab->nCol ){ - if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ - iCol = pTab->iPKey; - pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; - }else{ - pTab = 0; - goto error_out; - } + pTab = 0; + goto error_out; } } @@ -135400,7 +124053,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata( primarykey = 1; } if( !zCollSeq ){ - zCollSeq = sqlite3StrBINARY; + zCollSeq = "BINARY"; } error_out: @@ -135422,17 +124075,18 @@ error_out: zColumnName); rc = SQLITE_ERROR; } - sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); sqlite3DbFree(db, zErrMsg); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } +#endif /* ** Sleep for a little while. Return the amount of time slept. */ -SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ +SQLITE_API int sqlite3_sleep(int ms){ sqlite3_vfs *pVfs; int rc; pVfs = sqlite3_vfs_find(0); @@ -135448,10 +124102,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){ /* ** Enable or disable the extended result codes. */ -SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int onoff){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif +SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ sqlite3_mutex_enter(db->mutex); db->errMask = onoff ? 0xffffffff : 0xff; sqlite3_mutex_leave(db->mutex); @@ -135461,13 +124112,10 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int ono /* ** Invoke the xFileControl method on a particular database. */ -SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ +SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ int rc = SQLITE_ERROR; Btree *pBtree; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; -#endif sqlite3_mutex_enter(db->mutex); pBtree = sqlite3DbNameToBtree(db, zDbName); if( pBtree ){ @@ -135481,12 +124129,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbN if( op==SQLITE_FCNTL_FILE_POINTER ){ *(sqlite3_file**)pArg = fd; rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_VFS_POINTER ){ - *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); - rc = SQLITE_OK; - }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ - *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); - rc = SQLITE_OK; }else if( fd->pMethods ){ rc = sqlite3OsFileControl(fd, op, pArg); }else{ @@ -135495,17 +124137,15 @@ SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbN sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); - return rc; + return rc; } /* ** Interface to the testing logic. */ -SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ +SQLITE_API int sqlite3_test_control(int op, ...){ int rc = 0; -#ifdef SQLITE_OMIT_BUILTIN_TEST - UNUSED_PARAMETER(op); -#else +#ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; va_start(ap, op); switch( op ){ @@ -135567,10 +124207,10 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ case SQLITE_TESTCTRL_FAULT_INSTALL: { /* MSVC is picky about pulling func ptrs from va lists. ** http://support.microsoft.com/kb/47961 - ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int)); + ** sqlite3Config.xTestCallback = va_arg(ap, int(*)(int)); */ typedef int(*TESTCALLBACKFUNC_t)(int); - sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); + sqlite3Config.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); rc = sqlite3FaultSim(0); break; } @@ -135601,7 +124241,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ ** IMPORTANT: Changing the PENDING byte from 0x40000000 results in ** an incompatible database file format. Changing the PENDING byte ** while any database connection is open results in undefined and - ** deleterious behavior. + ** dileterious behavior. */ case SQLITE_TESTCTRL_PENDING_BYTE: { rc = PENDING_BYTE; @@ -135756,6 +124396,22 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ break; } +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) + /* sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, + ** sqlite3_stmt*,const char**); + ** + ** If compiled with SQLITE_ENABLE_TREE_EXPLAIN, each sqlite3_stmt holds + ** a string that describes the optimized parse tree. This test-control + ** returns a pointer to that string. + */ + case SQLITE_TESTCTRL_EXPLAIN_STMT: { + sqlite3_stmt *pStmt = va_arg(ap, sqlite3_stmt*); + const char **pzRet = va_arg(ap, const char**); + *pzRet = sqlite3VdbeExplanation((Vdbe*)pStmt); + break; + } +#endif + /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); ** ** Set or clear a flag that indicates that the database file is always well- @@ -135784,51 +124440,6 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, nMax); */ - case SQLITE_TESTCTRL_SORTER_MMAP: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->nMaxSorterMmap = va_arg(ap, int); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_ISINIT); - ** - ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if - ** not. - */ - case SQLITE_TESTCTRL_ISINIT: { - if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); - ** - ** This test control is used to create imposter tables. "db" is a pointer - ** to the database connection. dbName is the database name (ex: "main" or - ** "temp") which will receive the imposter. "onOff" turns imposter mode on - ** or off. "tnum" is the root page of the b-tree to which the imposter - ** table should connect. - ** - ** Enable imposter mode only when the schema has already been parsed. Then - ** run a single CREATE TABLE statement to construct the imposter table in - ** the parsed schema. Then turn imposter mode back off again. - ** - ** If onOff==0 and tnum>0 then reset the schema for all databases, causing - ** the schema to be reparsed the next time it is needed. This has the - ** effect of erasing all imposter tables. - */ - case SQLITE_TESTCTRL_IMPOSTER: { - sqlite3 *db = va_arg(ap, sqlite3*); - sqlite3_mutex_enter(db->mutex); - db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); - db->init.busy = db->init.imposterTable = va_arg(ap,int); - db->init.newTnum = va_arg(ap,int); - if( db->init.busy==0 && db->init.newTnum>0 ){ - sqlite3ResetAllSchemasOfConnection(db); - } - sqlite3_mutex_leave(db->mutex); - break; - } } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ @@ -135846,8 +124457,8 @@ SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){ ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam){ - if( zFilename==0 || zParam==0 ) return 0; +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ + if( zFilename==0 ) return 0; zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ int x = strcmp(zFilename, zParam); @@ -135861,7 +124472,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilenam /* ** Return a boolean value for a query parameter. */ -SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ +SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ const char *z = sqlite3_uri_parameter(zFilename, zParam); bDflt = bDflt!=0; return z ? sqlite3GetBoolean(z, bDflt) : bDflt; @@ -135870,14 +124481,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const c /* ** Return a 64-bit integer value for a query parameter. */ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64( +SQLITE_API sqlite3_int64 sqlite3_uri_int64( const char *zFilename, /* Filename as passed to xOpen */ const char *zParam, /* URI parameter sought */ sqlite3_int64 bDflt /* return if parameter is missing */ ){ const char *z = sqlite3_uri_parameter(zFilename, zParam); sqlite3_int64 v; - if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){ + if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){ bDflt = v; } return bDflt; @@ -135902,15 +124513,8 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ ** Return the filename of the database associated with a database ** connection. */ -SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName){ - Btree *pBt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - pBt = sqlite3DbNameToBtree(db, zDbName); +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); return pBt ? sqlite3BtreeGetFilename(pBt) : 0; } @@ -135918,100 +124522,11 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha ** Return 1 if database is read-only or 0 if read/write. Return -1 if ** no such database exists. */ -SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ - Btree *pBt; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return -1; - } -#endif - pBt = sqlite3DbNameToBtree(db, zDbName); +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; } -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** Obtain a snapshot handle for the snapshot of database zDb currently -** being read by handle db. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_get( - sqlite3 *db, - const char *zDb, - sqlite3_snapshot **ppSnapshot -){ - int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL - int iDb; - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( 0==sqlite3BtreeIsInTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); - } - } - } - - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Open a read-transaction on the snapshot idendified by pSnapshot. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3_snapshot_open( - sqlite3 *db, - const char *zDb, - sqlite3_snapshot *pSnapshot -){ - int rc = SQLITE_ERROR; -#ifndef SQLITE_OMIT_WAL - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - sqlite3_mutex_enter(db->mutex); - if( db->autoCommit==0 ){ - int iDb; - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ - rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); - } - } - } - } - - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Free a snapshot handle obtained from sqlite3_snapshot_get(). -*/ -SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ - sqlite3_free(pSnapshot); -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ - /************** End of main.c ************************************************/ /************** Begin file notify.c ******************************************/ /* @@ -136029,8 +124544,6 @@ SQLITE_API void SQLITE_STDCALL sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot ** This file contains the implementation of the sqlite3_unlock_notify() ** API method and its associated functionality. */ -/* #include "sqliteInt.h" */ -/* #include "btreeInt.h" */ /* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY @@ -136161,7 +124674,7 @@ static void leaveMutex(void){ ** on the same "db". If xNotify==0 then any prior callbacks are immediately ** cancelled. */ -SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( +SQLITE_API int sqlite3_unlock_notify( sqlite3 *db, void (*xNotify)(void **, int), void *pArg @@ -136200,7 +124713,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify( leaveMutex(); assert( !db->mallocFailed ); - sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0)); + sqlite3Error(db, rc, (rc?"database is deadlocked":0)); sqlite3_mutex_leave(db->mutex); return rc; } @@ -136674,11 +125187,9 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE -/* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT3 #endif -/* #include "sqlite3.h" */ /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ /************** Begin file fts3_tokenizer.h **********************************/ /* @@ -136707,7 +125218,6 @@ SQLITE_EXTENSION_INIT3 ** If tokenizers are to be allowed to call sqlite3_*() functions, then ** we will need a way to register the API consistently. */ -/* #include "sqlite3.h" */ /* ** Structures used by the tokenizer interface. When a new tokenizer @@ -137058,11 +125568,6 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi #ifdef SQLITE_COVERAGE_TEST # define ALWAYS(x) (1) # define NEVER(X) (0) -#elif defined(SQLITE_DEBUG) -# define ALWAYS(x) sqlite3Fts3Always((x)!=0) -# define NEVER(x) sqlite3Fts3Never((x)!=0) -SQLITE_PRIVATE int sqlite3Fts3Always(int b); -SQLITE_PRIVATE int sqlite3Fts3Never(int b); #else # define ALWAYS(x) (x) # define NEVER(x) (x) @@ -137121,8 +125626,6 @@ typedef struct Fts3DeferredToken Fts3DeferredToken; typedef struct Fts3SegReader Fts3SegReader; typedef struct Fts3MultiSegReader Fts3MultiSegReader; -typedef struct MatchinfoBuffer MatchinfoBuffer; - /* ** A connection to a fulltext index is an instance of the following ** structure. The xCreate and xConnect methods create an instance @@ -137188,7 +125691,6 @@ struct Fts3Table { int nPendingData; /* Current bytes of pending data */ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ int iPrevLangid; /* Langid of recently inserted document */ - int bPrevDelete; /* True if last operation was a delete */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) /* State variables used for validating that the transaction control @@ -137233,7 +125735,9 @@ struct Fts3Cursor { i64 iMinDocid; /* Minimum docid to return */ i64 iMaxDocid; /* Maximum docid to return */ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ - MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */ + u32 *aMatchinfo; /* Information about most recent match */ + int nMatchinfo; /* Number of elements in aMatchinfo[] */ + char *zMatchinfo; /* Matchinfo specification */ }; #define FTS3_EVAL_FILTER 0 @@ -137305,11 +125809,6 @@ struct Fts3Phrase { int bIncr; /* True if doclist is loaded incrementally */ int iDoclistToken; - /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an - ** OR condition. */ - char *pOrPoslist; - i64 iOrDocid; - /* Variables below this point are populated by fts3_expr.c when parsing ** a MATCH expression. Everything above is part of the evaluation phase. */ @@ -137353,9 +125852,7 @@ struct Fts3Expr { u8 bStart; /* True if iDocid is valid */ u8 bDeferred; /* True if this expression is entirely deferred */ - /* The following are used by the fts3_snippet.c module. */ - int iPhrase; /* Index of this phrase in matchinfo() results */ - u32 *aMI; /* See above */ + u32 *aMI; }; /* @@ -137466,7 +125963,6 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); ) /* fts3.c */ -SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); @@ -137476,7 +125972,6 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,i SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*); -SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc); /* fts3_tokenizer.c */ SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); @@ -137492,7 +125987,6 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const ch const char *, const char *, int, int ); SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); -SQLITE_PRIVATE void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p); /* fts3_expr.c */ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, @@ -137525,7 +126019,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); /* fts3_unicode2.c (functions generated by parsing unicode text files) */ -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); @@ -137549,9 +126043,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); /* #include */ /* #include */ -/* #include "fts3.h" */ #ifndef SQLITE_CORE -/* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #endif @@ -137560,13 +126052,6 @@ static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); -#ifndef SQLITE_AMALGAMATION -# if defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3Fts3Always(int b) { assert( b ); return b; } -SQLITE_PRIVATE int sqlite3Fts3Never(int b) { assert( !b ); return b; } -# endif -#endif - /* ** Write a 64-bit variable-length integer to memory starting at p[0]. ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. @@ -137676,7 +126161,7 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){ /* If the first byte was a '[', then the close-quote character is a ']' */ if( quote=='[' ) quote = ']'; - while( z[iIn] ){ + while( ALWAYS(z[iIn]) ){ if( z[iIn]==quote ){ if( z[iIn+1]!=quote ) break; z[iOut++] = quote; @@ -137755,17 +126240,6 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ return SQLITE_OK; } -/* -** Write an error message into *pzErr -*/ -SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ - va_list ap; - sqlite3_free(*pzErr); - va_start(ap, zFormat); - *pzErr = sqlite3_vmprintf(zFormat, ap); - va_end(ap); -} - /* ** Construct one or more SQL statements from the format string given ** and then evaluate those statements. The success code is written @@ -138175,16 +126649,11 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ ** This function is used when parsing the "prefix=" FTS4 parameter. */ static int fts3GobbleInt(const char **pp, int *pnOut){ - const int MAX_NPREFIX = 10000000; const char *p; /* Iterator pointer */ int nInt = 0; /* Output value */ for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ nInt = nInt * 10 + (p[0] - '0'); - if( nInt>MAX_NPREFIX ){ - nInt = 0; - break; - } } if( p==*pp ) return SQLITE_ERROR; *pnOut = nInt; @@ -138227,6 +126696,7 @@ static int fts3PrefixParameter( aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); *apIndex = aIndex; + *pnIndex = nIndex; if( !aIndex ){ return SQLITE_NOMEM; } @@ -138236,20 +126706,13 @@ static int fts3PrefixParameter( const char *p = zParam; int i; for(i=1; i=0 ); - if( nPrefix==0 ){ - nIndex--; - i--; - }else{ - aIndex[i].nPrefix = nPrefix; - } + aIndex[i].nPrefix = nPrefix; p++; } } - *pnIndex = nIndex; return SQLITE_OK; } @@ -138284,8 +126747,7 @@ static int fts3ContentColumns( const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr, /* OUT: Bytes of string content */ - char **pzErr /* OUT: error message */ + int *pnStr /* OUT: Bytes of string content */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ @@ -138296,9 +126758,6 @@ static int fts3ContentColumns( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); - } } sqlite3_free(zSql); @@ -138377,7 +126836,7 @@ static int fts3InitVtab( const char **aCol; /* Array of column names */ sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - int nIndex = 0; /* Size of aIndex[] array */ + int nIndex; /* Size of aIndex[] array */ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ /* The results of parsing supported FTS4 key=value options: */ @@ -138465,13 +126924,13 @@ static int fts3InitVtab( } } if( iOpt==SizeofArray(aFts4Opt) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); + *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); rc = SQLITE_ERROR; }else{ switch( iOpt ){ case 0: /* MATCHINFO */ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); + *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); rc = SQLITE_ERROR; } bNoDocsize = 1; @@ -138499,7 +126958,7 @@ static int fts3InitVtab( if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); + *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); rc = SQLITE_ERROR; } bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); @@ -138550,7 +127009,7 @@ static int fts3InitVtab( if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); + rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); /* If a languageid= option was specified, remove the language id ** column from the aCol[] array. */ @@ -138585,7 +127044,7 @@ static int fts3InitVtab( rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); if( rc==SQLITE_ERROR ){ assert( zPrefix ); - sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix); + *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix); } if( rc!=SQLITE_OK ) goto fts3_init_out; @@ -138667,7 +127126,7 @@ static int fts3InitVtab( } for(i=0; izReadExprlist = fts3ReadExprList(p, zUncompress, &rc); p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); @@ -138764,19 +127223,6 @@ static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ #endif } -/* -** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this -** extension is currently being used by a version of SQLite too old to -** support index-info flags. In that case this function is a no-op. -*/ -static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ -#if SQLITE_VERSION_NUMBER>=3008012 - if( sqlite3_libversion_number()>=3008012 ){ - pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; - } -#endif -} - /* ** Implementation of the xBestIndex method for FTS3 tables. There ** are three possible strategies, in order of preference: @@ -138867,9 +127313,6 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } } - /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ - if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); - iIdx = 1; if( iCons>=0 ){ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; @@ -138938,7 +127381,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3Fts3FreeDeferredTokens(pCsr); sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); + sqlite3_free(pCsr->aMatchinfo); assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); sqlite3_free(pCsr); return SQLITE_OK; @@ -139149,7 +127592,7 @@ static int fts3SelectLeaf( sqlite3_int64 *piLeaf, /* Selected leaf node */ sqlite3_int64 *piLeaf2 /* Selected leaf node */ ){ - int rc = SQLITE_OK; /* Return code */ + int rc; /* Return code */ int iHeight; /* Height of this node in tree */ assert( piLeaf || piLeaf2 ); @@ -139160,7 +127603,7 @@ static int fts3SelectLeaf( if( rc==SQLITE_OK && iHeight>1 ){ char *zBlob = 0; /* Blob read from %_segments table */ - int nBlob = 0; /* Size of zBlob in bytes */ + int nBlob; /* Size of zBlob in bytes */ if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); @@ -139787,33 +128230,26 @@ static int fts3DoclistOrMerge( ** ** The right-hand input doclist is overwritten by this function. */ -static int fts3DoclistPhraseMerge( +static void fts3DoclistPhraseMerge( int bDescDoclist, /* True if arguments are desc */ int nDist, /* Distance from left to right (1=adjacent) */ char *aLeft, int nLeft, /* Left doclist */ - char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ + char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ ){ sqlite3_int64 i1 = 0; sqlite3_int64 i2 = 0; sqlite3_int64 iPrev = 0; - char *aRight = *paRight; char *pEnd1 = &aLeft[nLeft]; char *pEnd2 = &aRight[*pnRight]; char *p1 = aLeft; char *p2 = aRight; char *p; int bFirstOut = 0; - char *aOut; + char *aOut = aRight; assert( nDist>0 ); - if( bDescDoclist ){ - aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); - if( aOut==0 ) return SQLITE_NOMEM; - }else{ - aOut = aRight; - } - p = aOut; + p = aOut; fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); @@ -139842,12 +128278,6 @@ static int fts3DoclistPhraseMerge( } *pnRight = (int)(p - aOut); - if( bDescDoclist ){ - sqlite3_free(aRight); - *paRight = aOut; - } - - return SQLITE_OK; } /* @@ -139972,22 +128402,8 @@ static int fts3TermSelectMerge( ){ if( pTS->aaOutput[0]==0 ){ /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). - ** - ** Add FTS3_VARINT_MAX bytes of unused space to the end of the - ** allocation. This is so as to ensure that the buffer is big enough - ** to hold the current doclist AND'd with any other doclist. If the - ** doclists are stored in order=ASC order, this padding would not be - ** required (since the size of [doclistA AND doclistB] is always less - ** than or equal to the size of [doclistA] in that case). But this is - ** not true for order=DESC. For example, a doclist containing (1, -1) - ** may be smaller than (-1), as in the first example the -1 may be stored - ** as a single-byte delta, whereas in the second it must be stored as a - ** FTS3_VARINT_MAX byte varint. - ** - ** Similar padding is added in the fts3DoclistOrMerge() function. - */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); + ** buffer using memcpy(). */ + pTS->aaOutput[0] = sqlite3_malloc(nDoclist); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); @@ -140084,7 +128500,7 @@ static int fts3SegReaderCursor( ** calls out here. */ if( iLevel<0 && p->aIndex ){ Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); + rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); if( rc==SQLITE_OK && pSeg ){ rc = fts3SegReaderCursorAppend(pCsr, pSeg); } @@ -140409,7 +128825,7 @@ static int fts3FilterMethod( int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ - int rc = SQLITE_OK; + int rc; char *zSql; /* SQL statement used to access %_content */ int eSearch; Fts3Table *p = (Fts3Table *)pCursor->pVtab; @@ -140439,7 +128855,6 @@ static int fts3FilterMethod( /* In case the cursor has been used before, clear it now. */ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); @@ -140487,17 +128902,10 @@ static int fts3FilterMethod( ** row by docid. */ if( eSearch==FTS3_FULLSCAN_SEARCH ){ - if( pDocidGe || pDocidLe ){ - zSql = sqlite3_mprintf( - "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", - p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, - (pCsr->bDesc ? "DESC" : "ASC") - ); - }else{ - zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); - } + zSql = sqlite3_mprintf( + "SELECT %s ORDER BY rowid %s", + p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") + ); if( zSql ){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); @@ -140733,31 +129141,11 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){ char *p = &(*ppPoslist)[-2]; char c = 0; - /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ while( p>pStart && (c=*p--)==0 ); - - /* Search backwards for a varint with value zero (the end of the previous - ** poslist). This is an 0x00 byte preceded by some byte that does not - ** have the 0x80 bit set. */ while( p>pStart && (*p & 0x80) | c ){ c = *p--; } - assert( p==pStart || c==0 ); - - /* At this point p points to that preceding byte without the 0x80 bit - ** set. So to find the start of the poslist, skip forward 2 bytes then - ** over a varint. - ** - ** Normally. The other case is that p==pStart and the poslist to return - ** is the first in the doclist. In this case do not skip forward 2 bytes. - ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) - ** is required for cases where the first byte of a doclist and the - ** doclist is empty. For example, if the first docid is 10, a doclist - ** that begins with: - ** - ** 0x0A 0x00 - */ - if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } + if( p>pStart ){ p = &p[2]; } while( *p++&0x80 ); *ppPoslist = p; } @@ -140828,8 +129216,6 @@ static void fts3SnippetFunc( } if( !zEllipsis || !zEnd || !zStart ){ sqlite3_result_error_nomem(pContext); - }else if( nToken==0 ){ - sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); } @@ -141103,7 +129489,7 @@ static void hashDestroy(void *p){ */ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); #endif #ifdef SQLITE_ENABLE_ICU @@ -141121,7 +129507,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ Fts3Hash *pHash = 0; const sqlite3_tokenizer_module *pSimple = 0; const sqlite3_tokenizer_module *pPorter = 0; -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 const sqlite3_tokenizer_module *pUnicode = 0; #endif @@ -141130,7 +129516,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ sqlite3Fts3IcuTokenizerModule(&pIcu); #endif -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 sqlite3Fts3UnicodeTokenizer(&pUnicode); #endif @@ -141158,7 +129544,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) #endif #ifdef SQLITE_ENABLE_ICU @@ -141265,17 +129651,14 @@ static void fts3EvalAllocateReaders( ** This function assumes that pList points to a buffer allocated using ** sqlite3_malloc(). This function takes responsibility for eventually ** freeing the buffer. -** -** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. */ -static int fts3EvalPhraseMergeToken( +static void fts3EvalPhraseMergeToken( Fts3Table *pTab, /* FTS Table pointer */ Fts3Phrase *p, /* Phrase to merge pList/nList into */ int iToken, /* Token pList/nList corresponds to */ char *pList, /* Pointer to doclist */ int nList /* Number of bytes in pList */ ){ - int rc = SQLITE_OK; assert( iToken!=p->iDoclistToken ); if( pList==0 ){ @@ -141314,16 +129697,13 @@ static int fts3EvalPhraseMergeToken( nDiff = p->iDoclistToken - iToken; } - rc = fts3DoclistPhraseMerge( - pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight - ); + fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); sqlite3_free(pLeft); p->doclist.aAll = pRight; p->doclist.nAll = nRight; } if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; - return rc; } /* @@ -141349,7 +129729,7 @@ static int fts3EvalPhraseLoad( char *pThis = 0; rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); + fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); } } assert( pToken->pSegcsr==0 ); @@ -141494,6 +129874,7 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ int bIncrOk = (bOptOk && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 + && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 #ifdef SQLITE_TEST && pTab->bNoIncrDoclist==0 #endif @@ -141613,7 +129994,6 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistNext( p += sqlite3Fts3GetVarint(p, piDocid); }else{ fts3PoslistCopy(0, &p); - while( p<&aDoclist[nDoclist] && *p==0 ) p++; if( p>=&aDoclist[nDoclist] ){ *pbEof = 1; }else{ @@ -141785,7 +130165,7 @@ static int fts3EvalIncrPhraseNext( bMaxSet = 1; } } - assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) ); + assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 ); assert( rc!=SQLITE_OK || bMaxSet ); /* Keep advancing iterators until they all point to the same document */ @@ -141891,14 +130271,12 @@ static void fts3EvalStartReaders( ){ if( pExpr && SQLITE_OK==*pRc ){ if( pExpr->eType==FTSQUERY_PHRASE ){ + int i; int nToken = pExpr->pPhrase->nToken; - if( nToken ){ - int i; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; - } - pExpr->bDeferred = (i==nToken); + for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; } + pExpr->bDeferred = (i==nToken); *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); }else{ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); @@ -142153,13 +130531,9 @@ static int fts3EvalSelectDeferred( char *pList = 0; rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); assert( rc==SQLITE_OK || pList==0 ); - if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken( - pTab, pTC->pPhrase, pTC->iToken,pList,nList - ); - } if( rc==SQLITE_OK ){ int nCount; + fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); nCount = fts3DoclistCountDocids( pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll ); @@ -142337,7 +130711,7 @@ static int fts3EvalNearTrim( ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is ** advanced to point to the next row that matches "x AND y". ** -** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is +** See fts3EvalTestDeferredAndNear() for details on testing if a row is ** really a match, taking into account deferred tokens and NEAR operators. */ static void fts3EvalNextRow( @@ -142384,22 +130758,6 @@ static void fts3EvalNextRow( } pExpr->iDocid = pLeft->iDocid; pExpr->bEof = (pLeft->bEof || pRight->bEof); - if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ - if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pRight->pPhrase->doclist; - while( *pRc==SQLITE_OK && pRight->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pLeft->pPhrase->doclist; - while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pLeft, pRc); - } - } - } } break; } @@ -142557,7 +130915,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ } /* -** This function is a helper function for sqlite3Fts3EvalTestDeferred(). +** This function is a helper function for fts3EvalTestDeferredAndNear(). ** Assuming no error occurs or has occurred, It returns non-zero if the ** expression passed as the second argument matches the row that pCsr ** currently points to, or zero if it does not. @@ -142678,7 +131036,7 @@ static int fts3EvalTestExpr( ** Or, if no error occurs and it seems the current row does match the FTS ** query, return 0. */ -SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ +static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){ int rc = *pRc; int bMiss = 0; if( rc==SQLITE_OK ){ @@ -142725,7 +131083,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){ pCsr->isRequireSeek = 1; pCsr->isMatchinfoNeeded = 1; pCsr->iPrevId = pExpr->iDocid; - }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); + }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); } /* Check if the cursor is past the end of the docid range specified @@ -142772,7 +131130,6 @@ static void fts3EvalRestart( } pPhrase->doclist.pNextDocid = 0; pPhrase->doclist.iDocid = 0; - pPhrase->pOrPoslist = 0; } pExpr->iDocid = 0; @@ -142886,7 +131243,7 @@ static int fts3EvalGatherStats( pCsr->iPrevId = pRoot->iDocid; }while( pCsr->isEof==0 && pRoot->eType==FTSQUERY_NEAR - && sqlite3Fts3EvalTestDeferred(pCsr, &rc) + && fts3EvalTestDeferredAndNear(pCsr, &rc) ); if( rc==SQLITE_OK && pCsr->isEof==0 ){ @@ -142911,6 +131268,7 @@ static int fts3EvalGatherStats( fts3EvalNextRow(pCsr, pRoot, &rc); assert( pRoot->bEof==0 ); }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); + fts3EvalTestDeferredAndNear(pCsr, &rc); } } return rc; @@ -143017,13 +131375,13 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ - int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ + int iMul; /* +1 if csr dir matches index dir, else -1 */ int bOr = 0; + u8 bEof = 0; u8 bTreeEof = 0; Fts3Expr *p; /* Used to iterate from pExpr to root */ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ - int bMatch; /* Check if this phrase descends from an OR expression node. If not, ** return NULL. Otherwise, the entry that corresponds to docid @@ -143042,62 +131400,74 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( ** an incremental phrase. Load the entire doclist for the phrase ** into memory in this case. */ if( pPhrase->bIncr ){ - int bEofSave = pNear->bEof; - fts3EvalRestart(pCsr, pNear, &rc); - while( rc==SQLITE_OK && !pNear->bEof ){ - fts3EvalNextRow(pCsr, pNear, &rc); - if( bEofSave==0 && pNear->iDocid==iDocid ) break; + int rc = SQLITE_OK; + int bEofSave = pExpr->bEof; + fts3EvalRestart(pCsr, pExpr, &rc); + while( rc==SQLITE_OK && !pExpr->bEof ){ + fts3EvalNextRow(pCsr, pExpr, &rc); + if( bEofSave==0 && pExpr->iDocid==iDocid ) break; } + pIter = pPhrase->doclist.pList; assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); + if( rc!=SQLITE_OK ) return rc; } - if( bTreeEof ){ - while( rc==SQLITE_OK && !pNear->bEof ){ - fts3EvalNextRow(pCsr, pNear, &rc); - } + + iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1); + while( bTreeEof==1 + && pNear->bEof==0 + && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0 + ){ + int rc = SQLITE_OK; + fts3EvalNextRow(pCsr, pExpr, &rc); + if( rc!=SQLITE_OK ) return rc; + iDocid = pExpr->iDocid; + pIter = pPhrase->doclist.pList; } - if( rc!=SQLITE_OK ) return rc; - bMatch = 1; - for(p=pNear; p; p=p->pLeft){ - u8 bEof = 0; - Fts3Expr *pTest = p; - Fts3Phrase *pPh; - assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); - if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; - assert( pTest->eType==FTSQUERY_PHRASE ); - pPh = pTest->pPhrase; + bEof = (pPhrase->doclist.nAll==0); + assert( bDescDoclist==0 || bDescDoclist==1 ); + assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); - pIter = pPh->pOrPoslist; - iDocid = pPh->iOrDocid; + if( bEof==0 ){ if( pCsr->bDesc==bDescDoclist ){ - bEof = !pPh->doclist.nAll || - (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &bEof + int dummy; + if( pNear->bEof ){ + /* This expression is already at EOF. So position it to point to the + ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable + ** iDocid is already set for this entry, so all that is required is + ** to set pIter to point to the first byte of the last position-list + ** in the doclist. + ** + ** It would also be correct to set pIter and iDocid to zero. In + ** this case, the first call to sqltie3Fts4DoclistPrev() below + ** would also move the iterator to point to the last entry in the + ** doclist. However, this is expensive, as to do so it has to + ** iterate through the entire doclist from start to finish (since + ** it does not know the docid for the last entry). */ + pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1]; + fts3ReversePoslist(pPhrase->doclist.aAll, &pIter); + } + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ + sqlite3Fts3DoclistPrev( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &dummy, &bEof ); } }else{ - bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - int dummy; - sqlite3Fts3DoclistPrev( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); + if( pNear->bEof ){ + pIter = 0; + iDocid = 0; + } + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ + sqlite3Fts3DoclistNext( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &bEof + ); } } - pPh->pOrPoslist = pIter; - pPh->iOrDocid = iDocid; - if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; } - if( bMatch ){ - pIter = pPhrase->pOrPoslist; - }else{ - pIter = 0; - } + if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; } if( pIter==0 ) return SQLITE_OK; @@ -143109,13 +131479,10 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( } while( iThis */ @@ -143290,7 +131656,7 @@ static int fts3auxConnectMethod( return SQLITE_OK; bad_args: - sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor"); + *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor"); return SQLITE_ERROR; } @@ -143742,7 +132108,6 @@ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ ** syntax is relatively simple, the whole tokenizer/parser system is ** hand-coded. */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* @@ -143917,7 +132282,7 @@ static int getNextToken( /* Set variable i to the maximum number of bytes of input to tokenize. */ for(i=0; ieType==eType; p=p->pLeft){ + assert( p->pParent==0 || p->pParent->pLeft==p ); + assert( p->pLeft && p->pRight ); + } + + /* This loop runs once for each leaf in the tree of eType nodes. */ + while( 1 ){ + int iLvl; + Fts3Expr *pParent = p->pParent; /* Current parent of p */ + + assert( pParent==0 || pParent->pLeft==p ); + p->pParent = 0; + if( pParent ){ + pParent->pLeft = 0; + }else{ + pRoot = 0; + } + rc = fts3ExprBalance(&p, nMaxDepth-1); + if( rc!=SQLITE_OK ) break; + + for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; + pFree->pRight = p; + pFree->pLeft->pParent = pFree; + pFree->pRight->pParent = pFree; + + p = pFree; + pFree = pFree->pParent; + p->pParent = 0; + apLeaf[iLvl] = 0; + } + } + if( p ){ + sqlite3Fts3ExprFree(p); + rc = SQLITE_TOOBIG; + break; + } + + /* If that was the last leaf node, break out of the loop */ + if( pParent==0 ) break; + + /* Set $p to point to the next leaf in the tree of eType nodes */ + for(p=pParent->pRight; p->eType==eType; p=p->pLeft); + + /* Remove pParent from the original tree. */ + assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); + pParent->pRight->pParent = pParent->pParent; + if( pParent->pParent ){ + pParent->pParent->pLeft = pParent->pRight; + }else{ + assert( pParent==pRoot ); + pRoot = pParent->pRight; + } + + /* Link pParent into the free node list. It will be used as an + ** internal node of the new tree. */ + pParent->pParent = pFree; + pFree = pParent; } if( rc==SQLITE_OK ){ - int i; - Fts3Expr *p; - - /* Set $p to point to the left-most leaf in the tree of eType nodes. */ - for(p=pRoot; p->eType==eType; p=p->pLeft){ - assert( p->pParent==0 || p->pParent->pLeft==p ); - assert( p->pLeft && p->pRight ); - } - - /* This loop runs once for each leaf in the tree of eType nodes. */ - while( 1 ){ - int iLvl; - Fts3Expr *pParent = p->pParent; /* Current parent of p */ - - assert( pParent==0 || pParent->pLeft==p ); - p->pParent = 0; - if( pParent ){ - pParent->pLeft = 0; - }else{ - pRoot = 0; - } - rc = fts3ExprBalance(&p, nMaxDepth-1); - if( rc!=SQLITE_OK ) break; - - for(iLvl=0; p && iLvlpParent = 0; }else{ - assert( pFree ); - pFree->pLeft = apLeaf[iLvl]; + assert( pFree!=0 ); pFree->pRight = p; + pFree->pLeft = apLeaf[i]; pFree->pLeft->pParent = pFree; pFree->pRight->pParent = pFree; p = pFree; pFree = pFree->pParent; p->pParent = 0; - apLeaf[iLvl] = 0; } } - if( p ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_TOOBIG; - break; - } - - /* If that was the last leaf node, break out of the loop */ - if( pParent==0 ) break; - - /* Set $p to point to the next leaf in the tree of eType nodes */ - for(p=pParent->pRight; p->eType==eType; p=p->pLeft); - - /* Remove pParent from the original tree. */ - assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); - pParent->pRight->pParent = pParent->pParent; - if( pParent->pParent ){ - pParent->pParent->pLeft = pParent->pRight; - }else{ - assert( pParent==pRoot ); - pRoot = pParent->pRight; - } - - /* Link pParent into the free node list. It will be used as an - ** internal node of the new tree. */ - pParent->pParent = pFree; - pFree = pParent; } - - if( rc==SQLITE_OK ){ - p = 0; - for(i=0; ipParent = 0; - }else{ - assert( pFree!=0 ); - pFree->pRight = p; - pFree->pLeft = apLeaf[i]; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - } - } - } - pRoot = p; - }else{ - /* An error occurred. Delete the contents of the apLeaf[] array - ** and pFree list. Everything else is cleaned up by the call to - ** sqlite3Fts3ExprFree(pRoot) below. */ - Fts3Expr *pDel; - for(i=0; ipParent; - sqlite3_free(pDel); - } - } - - assert( pFree==0 ); - sqlite3_free( apLeaf ); - } - }else if( eType==FTSQUERY_NOT ){ - Fts3Expr *pLeft = pRoot->pLeft; - Fts3Expr *pRight = pRoot->pRight; - - pRoot->pLeft = 0; - pRoot->pRight = 0; - pLeft->pParent = 0; - pRight->pParent = 0; - - rc = fts3ExprBalance(&pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprBalance(&pRight, nMaxDepth-1); - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRight); - sqlite3Fts3ExprFree(pLeft); + pRoot = p; }else{ - assert( pLeft && pRight ); - pRoot->pLeft = pLeft; - pLeft->pParent = pRoot; - pRoot->pRight = pRight; - pRight->pParent = pRoot; + /* An error occurred. Delete the contents of the apLeaf[] array + ** and pFree list. Everything else is cleaned up by the call to + ** sqlite3Fts3ExprFree(pRoot) below. */ + Fts3Expr *pDel; + for(i=0; ipParent; + sqlite3_free(pDel); + } } + + assert( pFree==0 ); + sqlite3_free( apLeaf ); } } - + if( rc!=SQLITE_OK ){ sqlite3Fts3ExprFree(pRoot); pRoot = 0; @@ -144775,13 +133114,13 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse( sqlite3Fts3ExprFree(*ppExpr); *ppExpr = 0; if( rc==SQLITE_TOOBIG ){ - sqlite3Fts3ErrMsg(pzErr, + *pzErr = sqlite3_mprintf( "FTS expression tree is too large (maximum depth %d)", SQLITE_FTS3_MAX_EXPR_DEPTH ); rc = SQLITE_ERROR; }else if( rc==SQLITE_ERROR ){ - sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z); + *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z); } } @@ -145062,14 +133401,12 @@ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ /* #include */ /* #include */ -/* #include "fts3_hash.h" */ /* ** Malloc and Free functions @@ -145447,7 +133784,6 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert( ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -145455,7 +133791,6 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert( /* #include */ /* #include */ -/* #include "fts3_tokenizer.h" */ /* ** Class derived from sqlite3_tokenizer @@ -145608,7 +133943,7 @@ static int isVowel(const char *z){ ** by a consonant. ** ** In this routine z[] is in reverse order. So we are really looking -** for an instance of a consonant followed by a vowel. +** for an instance of of a consonant followed by a vowel. */ static int m_gt_0(const char *z){ while( isVowel(z) ){ z++; } @@ -146113,7 +134448,6 @@ SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule( ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -146159,7 +134493,7 @@ static void scalarFunc( if( argc==2 ){ void *pOld; int n = sqlite3_value_bytes(argv[1]); - if( zName==0 || n!=sizeof(pPtr) ){ + if( n!=sizeof(pPtr) ){ sqlite3_result_error(context, "argument type mismatch", -1); return; } @@ -146170,9 +134504,7 @@ static void scalarFunc( return; } }else{ - if( zName ){ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); - } + pPtr = sqlite3Fts3HashFind(pHash, zName, nName); if( !pPtr ){ char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); sqlite3_result_error(context, zErr, -1); @@ -146253,16 +134585,12 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( zEnd = &zCopy[strlen(zCopy)]; z = (char *)sqlite3Fts3NextToken(zCopy, &n); - if( z==0 ){ - assert( n==0 ); - z = zCopy; - } z[n] = '\0'; sqlite3Fts3Dequote(z); m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); if( !m ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z); + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); rc = SQLITE_ERROR; }else{ char const **aArg = 0; @@ -146285,7 +134613,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( rc = m->xCreate(iArg, aArg, ppTok); assert( rc!=SQLITE_OK || *ppTok ); if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); + *pzErr = sqlite3_mprintf("unknown tokenizer"); }else{ (*ppTok)->pModule = m; } @@ -146369,9 +134697,9 @@ static void testFunc( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr2, -1); - sqlite3_free(zErr2); + char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); return; } @@ -146609,7 +134937,6 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable( ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -146617,7 +134944,6 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable( /* #include */ /* #include */ -/* #include "fts3_tokenizer.h" */ typedef struct simple_tokenizer { sqlite3_tokenizer base; @@ -146862,7 +135188,6 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( ** pos: Token offset of token within input. ** */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -146909,7 +135234,7 @@ static int fts3tokQueryTokenizer( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName); + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName); return SQLITE_ERROR; } @@ -146987,7 +135312,7 @@ static int fts3tokConnectMethod( sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ char **pzErr /* OUT: sqlite3_malloc'd error message */ ){ - Fts3tokTable *pTab = 0; + Fts3tokTable *pTab; const sqlite3_tokenizer_module *pMod = 0; sqlite3_tokenizer *pTok = 0; int rc; @@ -147298,7 +135623,6 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ ** code in fts3.c. */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -147607,7 +135931,7 @@ static int fts3SqlStmt( /* 25 */ "", /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", +/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", /* This statement is used to determine which level to read the input from ** when performing an incremental merge. It returns the absolute level number @@ -148141,12 +136465,10 @@ static int fts3PendingTermsAdd( */ static int fts3PendingTermsDocid( Fts3Table *p, /* Full-text table handle */ - int bDelete, /* True if this op is a delete */ int iLangid, /* Language id of row being written */ sqlite_int64 iDocid /* Docid of row being written */ ){ assert( iLangid>=0 ); - assert( bDelete==1 || bDelete==0 ); /* TODO(shess) Explore whether partially flushing the buffer on ** forced-flush would provide better performance. I suspect that if @@ -148154,8 +136476,7 @@ static int fts3PendingTermsDocid( ** buffer was half empty, that would let the less frequent terms ** generate longer doclists. */ - if( iDocidiPrevDocid - || (iDocid==p->iPrevDocid && p->bPrevDelete==0) + if( iDocid<=p->iPrevDocid || p->iPrevLangid!=iLangid || p->nPendingData>p->nMaxPendingData ){ @@ -148164,7 +136485,6 @@ static int fts3PendingTermsDocid( } p->iPrevDocid = iDocid; p->iPrevLangid = iLangid; - p->bPrevDelete = bDelete; return SQLITE_OK; } @@ -148354,8 +136674,7 @@ static void fts3DeleteTerms( if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; int iLangid = langidFromSelect(p, pSelect); - i64 iDocid = sqlite3_column_int64(pSelect, 0); - rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ int iCol = i-1; if( p->abNotindexed[iCol]==0 ){ @@ -148603,19 +136922,14 @@ static int fts3SegReaderNext( if( fts3SegReaderIsPending(pReader) ){ Fts3HashElem *pElem = *(pReader->ppNextElem); - sqlite3_free(pReader->aNode); - pReader->aNode = 0; - if( pElem ){ - char *aCopy; + if( pElem==0 ){ + pReader->aNode = 0; + }else{ PendingList *pList = (PendingList *)fts3HashData(pElem); - int nCopy = pList->nData+1; pReader->zTerm = (char *)fts3HashKey(pElem); pReader->nTerm = fts3HashKeysize(pElem); - aCopy = (char*)sqlite3_malloc(nCopy); - if( !aCopy ) return SQLITE_NOMEM; - memcpy(aCopy, pList->aData, nCopy); - pReader->nNode = pReader->nDoclist = nCopy; - pReader->aNode = pReader->aDoclist = aCopy; + pReader->nNode = pReader->nDoclist = pList->nData + 1; + pReader->aNode = pReader->aDoclist = pList->aData; pReader->ppNextElem++; assert( pReader->aNode ); } @@ -148855,14 +137169,12 @@ SQLITE_PRIVATE int sqlite3Fts3MsrOvfl( ** second argument. */ SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ - if( pReader ){ - if( !fts3SegReaderIsPending(pReader) ){ - sqlite3_free(pReader->zTerm); - } + if( pReader && !fts3SegReaderIsPending(pReader) ){ + sqlite3_free(pReader->zTerm); if( !fts3SegReaderIsRootOnly(pReader) ){ sqlite3_free(pReader->aNode); + sqlite3_blob_close(pReader->pBlob); } - sqlite3_blob_close(pReader->pBlob); } sqlite3_free(pReader); } @@ -148918,10 +137230,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( ** an array of pending terms by term. This occurs as part of flushing ** the contents of the pending-terms hash table to the database. */ -static int SQLITE_CDECL fts3CompareElemByTerm( - const void *lhs, - const void *rhs -){ +static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); @@ -150378,8 +138687,8 @@ static int fts3PromoteSegments( if( bOk ){ int iIdx = 0; - sqlite3_stmt *pUpdate1 = 0; - sqlite3_stmt *pUpdate2 = 0; + sqlite3_stmt *pUpdate1; + sqlite3_stmt *pUpdate2; if( rc==SQLITE_OK ){ rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); @@ -150737,8 +139046,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->nIndex); while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ int i; int iLangid = sqlite3_column_int(pAllLangid, 0); @@ -150805,7 +139113,7 @@ static int fts3DoRebuild(Fts3Table *p){ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ if( p->abNotindexed[iCol]==0 ){ @@ -152070,7 +140378,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); - if( i!=nHint ) return FTS_CORRUPT_VTAB; + if( i!=nHint ) return SQLITE_CORRUPT_VTAB; return SQLITE_OK; } @@ -152438,8 +140746,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->nIndex); while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ int iLangid = sqlite3_column_int(pAllLangid, 0); int i; @@ -152452,6 +140759,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ } /* This block calculates the checksum according to the %_content table */ + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; sqlite3_stmt *pStmt = 0; @@ -152471,36 +140779,34 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ int iCol; for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); - int nText = sqlite3_column_bytes(pStmt, iCol+1); - sqlite3_tokenizer_cursor *pT = 0; + const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); + int nText = sqlite3_column_bytes(pStmt, iCol+1); + sqlite3_tokenizer_cursor *pT = 0; - rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ + rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); + while( rc==SQLITE_OK ){ + char const *zToken; /* Buffer containing token */ + int nToken = 0; /* Number of bytes in token */ + int iDum1 = 0, iDum2 = 0; /* Dummy variables */ + int iPos = 0; /* Position of token in zText */ - rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); - if( rc==SQLITE_OK ){ - int i; - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, nToken, iLang, 0, iDocid, iCol, iPos - ); - for(i=1; inIndex; i++){ - if( p->aIndex[i].nPrefix<=nToken ){ - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos - ); - } + rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); + if( rc==SQLITE_OK ){ + int i; + cksum2 = cksum2 ^ fts3ChecksumEntry( + zToken, nToken, iLang, 0, iDocid, iCol, iPos + ); + for(i=1; inIndex; i++){ + if( p->aIndex[i].nPrefix<=nToken ){ + cksum2 = cksum2 ^ fts3ChecksumEntry( + zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos + ); } } } - if( pT ) pModule->xClose(pT); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; } + if( pT ) pModule->xClose(pT); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; } } @@ -152548,7 +140854,7 @@ static int fts3DoIntegrityCheck( int rc; int bOk = 0; rc = fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; + if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; return rc; } @@ -152910,7 +141216,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( } } if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ - rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); + rc = fts3PendingTermsDocid(p, iLangid, *pRowid); } if( rc==SQLITE_OK ){ assert( p->iPrevDocid==*pRowid ); @@ -152971,7 +141277,6 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ ****************************************************************************** */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -152987,8 +141292,6 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ #define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ #define FTS3_MATCHINFO_LCS 's' /* nCol values */ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */ /* ** The default value for the second argument to matchinfo(). @@ -153050,22 +141353,9 @@ struct MatchInfo { int nCol; /* Number of columns in table */ int nPhrase; /* Number of matchable phrases in query */ sqlite3_int64 nDoc; /* Number of docs in database */ - char flag; u32 *aMatchinfo; /* Pre-allocated buffer */ }; -/* -** An instance of this structure is used to manage a pair of buffers, each -** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below -** for details. -*/ -struct MatchinfoBuffer { - u8 aRef[3]; - int nElem; - int bGlobal; /* Set if global data is loaded */ - char *zMatchinfo; - u32 aMatchinfo[1]; -}; /* @@ -153081,97 +141371,6 @@ struct StrBuffer { }; -/************************************************************************* -** Start of MatchinfoBuffer code. -*/ - -/* -** Allocate a two-slot MatchinfoBuffer object. -*/ -static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ - MatchinfoBuffer *pRet; - int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); - int nStr = (int)strlen(zMatchinfo); - - pRet = sqlite3_malloc(nByte + nStr+1); - if( pRet ){ - memset(pRet, 0, nByte); - pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; - pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1); - pRet->nElem = nElem; - pRet->zMatchinfo = ((char*)pRet) + nByte; - memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); - pRet->aRef[0] = 1; - } - - return pRet; -} - -static void fts3MIBufferFree(void *p){ - MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); - - assert( (u32*)p==&pBuf->aMatchinfo[1] - || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2] - ); - if( (u32*)p==&pBuf->aMatchinfo[1] ){ - pBuf->aRef[1] = 0; - }else{ - pBuf->aRef[2] = 0; - } - - if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){ - sqlite3_free(pBuf); - } -} - -static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){ - void (*xRet)(void*) = 0; - u32 *aOut = 0; - - if( p->aRef[1]==0 ){ - p->aRef[1] = 1; - aOut = &p->aMatchinfo[1]; - xRet = fts3MIBufferFree; - } - else if( p->aRef[2]==0 ){ - p->aRef[2] = 1; - aOut = &p->aMatchinfo[p->nElem+2]; - xRet = fts3MIBufferFree; - }else{ - aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32)); - if( aOut ){ - xRet = sqlite3_free; - if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32)); - } - } - - *paOut = aOut; - return xRet; -} - -static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){ - p->bGlobal = 1; - memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32)); -} - -/* -** Free a MatchinfoBuffer object allocated using fts3MIBufferNew() -*/ -SQLITE_PRIVATE void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){ - if( p ){ - assert( p->aRef[0]==1 ); - p->aRef[0] = 0; - if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){ - sqlite3_free(p); - } - } -} - -/* -** End of MatchinfoBuffer code. -*************************************************************************/ - - /* ** This function is used to help iterate through a position-list. A position ** list is a list of unique integers, sorted from smallest to largest. Each @@ -153208,7 +141407,7 @@ static int fts3ExprIterate2( void *pCtx /* Second argument to pass to callback */ ){ int rc; /* Return code */ - int eType = pExpr->eType; /* Type of expression node pExpr */ + int eType = pExpr->eType; /* Type of expression node pExpr */ if( eType!=FTSQUERY_PHRASE ){ assert( pExpr->pLeft && pExpr->pRight ); @@ -153242,7 +141441,6 @@ static int fts3ExprIterate( return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); } - /* ** This is an fts3ExprIterate() callback used while loading the doclists ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also @@ -153287,7 +141485,8 @@ static int fts3ExprLoadDoclists( static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ (*(int *)ctx)++; - pExpr->iPhrase = iPhrase; + UNUSED_PARAMETER(pExpr); + UNUSED_PARAMETER(iPhrase); return SQLITE_OK; } static int fts3ExprPhraseCount(Fts3Expr *pExpr){ @@ -153508,39 +141707,37 @@ static int fts3BestSnippet( sIter.nSnippet = nSnippet; sIter.nPhrase = nList; sIter.iCurrent = -1; - rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter); - if( rc==SQLITE_OK ){ + (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); - /* Set the *pmSeen output variable. */ - for(i=0; iiCol = iCol; - while( !fts3SnippetNextCandidate(&sIter) ){ - int iPos; - int iScore; - u64 mCover; - u64 mHighlite; - fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite); - assert( iScore>=0 ); - if( iScore>iBestScore ){ - pFragment->iPos = iPos; - pFragment->hlmask = mHighlite; - pFragment->covered = mCover; - iBestScore = iScore; - } - } - - *piScore = iBestScore; } + + /* Loop through all candidate snippets. Store the best snippet in + ** *pFragment. Store its associated 'score' in iBestScore. + */ + pFragment->iCol = iCol; + while( !fts3SnippetNextCandidate(&sIter) ){ + int iPos; + int iScore; + u64 mCover; + u64 mHighlight; + fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); + assert( iScore>=0 ); + if( iScore>iBestScore ){ + pFragment->iPos = iPos; + pFragment->hlmask = mHighlight; + pFragment->covered = mCover; + iBestScore = iScore; + } + } + sqlite3_free(sIter.aPhrase); - return rc; + *piScore = iBestScore; + return SQLITE_OK; } @@ -153748,12 +141945,8 @@ static int fts3SnippetText( ** required. They are required if (a) this is not the first fragment, ** or (b) this fragment does not begin at position 0 of its column. */ - if( rc==SQLITE_OK ){ - if( iPos>0 || iFragment>0 ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - }else if( iBegin ){ - rc = fts3StringAppend(pOut, zDoc, iBegin); - } + if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ + rc = fts3StringAppend(pOut, zEllipsis, -1); } if( rc!=SQLITE_OK || iCurrentpCursor->base.pVtab; - int iStart; - Fts3Phrase *pPhrase = pExpr->pPhrase; - char *pIter = pPhrase->doclist.pList; - int iCol = 0; - - assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS ); - if( p->flag==FTS3_MATCHINFO_LHITS ){ - iStart = pExpr->iPhrase * p->nCol; - }else{ - iStart = pExpr->iPhrase * ((p->nCol + 31) / 32); - } - - while( 1 ){ - int nHit = fts3ColumnlistCount(&pIter); - if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ - if( p->flag==FTS3_MATCHINFO_LHITS ){ - p->aMatchinfo[iStart + iCol] = (u32)nHit; - }else if( nHit ){ - p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F)); - } - } - assert( *pIter==0x00 || *pIter==0x01 ); - if( *pIter!=0x01 ) break; - pIter++; - pIter += fts3GetVarint32(pIter, &iCol); - } -} - -/* -** Gather the results for matchinfo directives 'y' and 'b'. -*/ -static void fts3ExprLHitGather( - Fts3Expr *pExpr, - MatchInfo *p -){ - assert( (pExpr->pLeft==0)==(pExpr->pRight==0) ); - if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ - if( pExpr->pLeft ){ - fts3ExprLHitGather(pExpr->pLeft, p); - fts3ExprLHitGather(pExpr->pRight, p); - }else{ - fts3ExprLHits(pExpr, p); - } - } -} - /* ** fts3ExprIterate() callback used to collect the "global" matchinfo stats ** for a single query. @@ -153941,12 +142080,10 @@ static int fts3MatchinfoCheck( || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) || (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_HITS) - || (cArg==FTS3_MATCHINFO_LHITS) - || (cArg==FTS3_MATCHINFO_LHITS_BM) ){ return SQLITE_OK; } - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); + *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); return SQLITE_ERROR; } @@ -153966,14 +142103,6 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ nVal = pInfo->nCol; break; - case FTS3_MATCHINFO_LHITS: - nVal = pInfo->nCol * pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_LHITS_BM: - nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32); - break; - default: assert( cArg==FTS3_MATCHINFO_HITS ); nVal = pInfo->nCol * pInfo->nPhrase * 3; @@ -154168,7 +142297,7 @@ static int fts3MatchinfoValues( sqlite3_stmt *pSelect = 0; for(i=0; rc==SQLITE_OK && zArg[i]; i++){ - pInfo->flag = zArg[i]; + switch( zArg[i] ){ case FTS3_MATCHINFO_NPHRASE: if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; @@ -154228,14 +142357,6 @@ static int fts3MatchinfoValues( } break; - case FTS3_MATCHINFO_LHITS_BM: - case FTS3_MATCHINFO_LHITS: { - int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); - memset(pInfo->aMatchinfo, 0, nZero); - fts3ExprLHitGather(pCsr->pExpr, pInfo); - break; - } - default: { Fts3Expr *pExpr; assert( zArg[i]==FTS3_MATCHINFO_HITS ); @@ -154248,7 +142369,6 @@ static int fts3MatchinfoValues( if( rc!=SQLITE_OK ) break; } rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); - sqlite3Fts3EvalTestDeferred(pCsr, &rc); if( rc!=SQLITE_OK ) break; } (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); @@ -154268,8 +142388,7 @@ static int fts3MatchinfoValues( ** Populate pCsr->aMatchinfo[] with data for the current row. The ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). */ -static void fts3GetMatchinfo( - sqlite3_context *pCtx, /* Return results here */ +static int fts3GetMatchinfo( Fts3Cursor *pCsr, /* FTS3 Cursor object */ const char *zArg /* Second argument to matchinfo() function */ ){ @@ -154278,9 +142397,6 @@ static void fts3GetMatchinfo( int rc = SQLITE_OK; int bGlobal = 0; /* Collect 'global' stats as well as local */ - u32 *aOut = 0; - void (*xDestroyOut)(void*) = 0; - memset(&sInfo, 0, sizeof(MatchInfo)); sInfo.pCursor = pCsr; sInfo.nCol = pTab->nColumn; @@ -154288,18 +142404,21 @@ static void fts3GetMatchinfo( /* If there is cached matchinfo() data, but the format string for the ** cache does not match the format string for this request, discard ** the cached data. */ - if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){ - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - pCsr->pMIBuffer = 0; + if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ + assert( pCsr->aMatchinfo ); + sqlite3_free(pCsr->aMatchinfo); + pCsr->zMatchinfo = 0; + pCsr->aMatchinfo = 0; } - /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the + /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the ** matchinfo function has been called for this query. In this case ** allocate the array used to accumulate the matchinfo data and ** initialize those elements that are constant for every row. */ - if( pCsr->pMIBuffer==0 ){ + if( pCsr->aMatchinfo==0 ){ int nMatchinfo = 0; /* Number of u32 elements in match-info */ + int nArg; /* Bytes in zArg */ int i; /* Used to iterate through zArg */ /* Determine the number of phrases in the query */ @@ -154308,46 +142427,30 @@ static void fts3GetMatchinfo( /* Determine the number of integers in the buffer returned by this call. */ for(i=0; zArg[i]; i++){ - char *zErr = 0; - if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ - sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); - return; - } nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); } /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ - pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg); - if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM; + nArg = (int)strlen(zArg); + pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); + if( !pCsr->aMatchinfo ) return SQLITE_NOMEM; + pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo]; + pCsr->nMatchinfo = nMatchinfo; + memcpy(pCsr->zMatchinfo, zArg, nArg+1); + memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo); pCsr->isMatchinfoNeeded = 1; bGlobal = 1; } - if( rc==SQLITE_OK ){ - xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut); - if( xDestroyOut==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - sInfo.aMatchinfo = aOut; - sInfo.nPhrase = pCsr->nPhrase; + sInfo.aMatchinfo = pCsr->aMatchinfo; + sInfo.nPhrase = pCsr->nPhrase; + if( pCsr->isMatchinfoNeeded ){ rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); - if( bGlobal ){ - fts3MIBufferSetGlobal(pCsr->pMIBuffer); - } + pCsr->isMatchinfoNeeded = 0; } - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - if( xDestroyOut ) xDestroyOut(aOut); - }else{ - int n = pCsr->pMIBuffer->nElem * sizeof(u32); - sqlite3_result_blob(pCtx, aOut, n, xDestroyOut); - } + return rc; } /* @@ -154409,7 +142512,7 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet( */ for(iRead=0; iReadnColumn; iRead++){ SnippetFragment sF = {0, 0, 0, 0}; - int iS = 0; + int iS; if( iCol>=0 && iRead!=iCol ) continue; /* Find the best snippet of nFToken tokens in column iRead. */ @@ -154553,7 +142656,7 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( */ sCtx.iCol = iCol; sCtx.iTerm = 0; - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx); + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); /* Retreive the text stored in column iCol. If an SQL NULL is stored ** in column iCol, jump immediately to the next iteration of the loop. @@ -154645,9 +142748,19 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo( const char *zArg /* Second arg to matchinfo() function */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; + int rc; + int i; const char *zFormat; if( zArg ){ + for(i=0; zArg[i]; i++){ + char *zErr = 0; + if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ + sqlite3_result_error(pContext, zErr, -1); + sqlite3_free(zErr); + return; + } + } zFormat = zArg; }else{ zFormat = FTS3_MATCHINFO_DEFAULT; @@ -154656,10 +142769,17 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo( if( !pCsr->pExpr ){ sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); return; + } + + /* Retrieve matchinfo() data. */ + rc = fts3GetMatchinfo(pCsr, zFormat); + sqlite3Fts3SegmentsClose(pTab); + + if( rc!=SQLITE_OK ){ + sqlite3_result_error_code(pContext, rc); }else{ - /* Retrieve matchinfo() data. */ - fts3GetMatchinfo(pContext, pCsr, zFormat); - sqlite3Fts3SegmentsClose(pTab); + int n = pCsr->nMatchinfo * sizeof(u32); + sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); } } @@ -154682,9 +142802,8 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo( ** Implementation of the "unicode" full-text-search tokenizer. */ -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include */ @@ -154692,7 +142811,6 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo( /* #include */ /* #include */ -/* #include "fts3_tokenizer.h" */ /* ** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied @@ -154900,7 +143018,7 @@ static int unicodeCreate( for(i=0; rc==SQLITE_OK && ibRemoveDiacritic = 1; @@ -154987,7 +143105,7 @@ static int unicodeNext( ){ unicode_cursor *pCsr = (unicode_cursor *)pC; unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); - int iCode = 0; + int iCode; char *zOut; const unsigned char *z = &pCsr->aInput[pCsr->iOff]; const unsigned char *zStart = z; @@ -155032,11 +143150,11 @@ static int unicodeNext( ); /* Set the output variables and return. */ - pCsr->iOff = (int)(z - pCsr->aInput); + pCsr->iOff = (z - pCsr->aInput); *paToken = pCsr->zToken; - *pnToken = (int)(zOut - pCsr->zToken); - *piStart = (int)(zStart - pCsr->aInput); - *piEnd = (int)(zEnd - pCsr->aInput); + *pnToken = zOut - pCsr->zToken; + *piStart = (zStart - pCsr->aInput); + *piEnd = (zEnd - pCsr->aInput); *piPos = pCsr->iToken++; return SQLITE_OK; } @@ -155059,7 +143177,7 @@ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const * } #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ -#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */ +#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */ /************** End of fts3_unicode.c ****************************************/ /************** Begin file fts3_unicode2.c ***********************************/ @@ -155080,7 +143198,7 @@ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const * ** DO NOT EDIT THIS MACHINE GENERATED FILE. */ -#ifndef SQLITE_DISABLE_FTS3_UNICODE +#if defined(SQLITE_ENABLE_FTS4_UNICODE61) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) /* #include */ @@ -155104,7 +143222,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ ** C. It is not possible to represent a range larger than 1023 codepoints ** using this format. */ - static const unsigned int aEntry[] = { + const static unsigned int aEntry[] = { 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, @@ -155196,7 +143314,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); }else if( c<(1<<22) ){ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; - int iRes = 0; + int iRes; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; int iLo = 0; while( iHi>=iLo ){ @@ -155267,7 +143385,7 @@ static int remove_diacritic(int c){ } assert( key>=aDia[iRes] ); return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); -} +}; /* @@ -155427,7 +143545,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ return ret; } #endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ -#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ +#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */ /************** End of fts3_unicode2.c ***************************************/ /************** Begin file rtree.c *******************************************/ @@ -155488,10 +143606,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) #ifndef SQLITE_CORE -/* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #else -/* #include "sqlite3.h" */ #endif /* #include */ @@ -155784,7 +143900,6 @@ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ - sqlite3_value **apSqlParam; /* Original SQL parameter values */ RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ }; @@ -155803,12 +143918,13 @@ static int readInt16(u8 *p){ return (p[0]<<8) + p[1]; } static void readCoord(u8 *p, RtreeCoord *pCoord){ - pCoord->u = ( + u32 i = ( (((u32)p[0]) << 24) + (((u32)p[1]) << 16) + (((u32)p[2]) << 8) + (((u32)p[3]) << 0) ); + *(u32 *)pCoord = i; } static i64 readInt64(u8 *p){ return ( @@ -155837,7 +143953,7 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); - i = pCoord->u; + i = *(u32 *)pCoord; p[0] = (i>>24)&0xFF; p[1] = (i>>16)&0xFF; p[2] = (i>> 8)&0xFF; @@ -156168,13 +144284,14 @@ static void nodeGetCell( RtreeCell *pCell /* OUT: Write the cell contents here */ ){ u8 *pData; + u8 *pEnd; RtreeCoord *pCoord; - int ii; pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); + pEnd = pData + pRtree->nDim*8; pCoord = pCell->aCoord; - for(ii=0; iinDim*2; ii++){ - readCoord(&pData[ii*4], &pCoord[ii]); + for(; pDataaPoint + i; pNew->rScore = rScore; pNew->iLevel = iLevel; - assert( iLevel<=RTREE_MAX_DEPTH ); + assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); while( i>0 ){ RtreeSearchPoint *pParent; j = (i-1)/2; @@ -156916,7 +145033,9 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); - if( nBlob<(int)sizeof(RtreeMatchArg) ){ + if( nBlob<(int)sizeof(RtreeMatchArg) + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 + ){ return SQLITE_ERROR; } @@ -156927,7 +145046,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); nExpected = (int)(sizeof(RtreeMatchArg) + - pBlob->nParam*sizeof(sqlite3_value*) + (pBlob->nParam-1)*sizeof(RtreeDValue)); if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ sqlite3_free(pInfo); @@ -156936,7 +145054,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ pInfo->pContext = pBlob->cb.pContext; pInfo->nParam = pBlob->nParam; pInfo->aParam = pBlob->aParam; - pInfo->apSqlParam = pBlob->apSqlParam; if( pBlob->cb.xGeom ){ pCons->u.xGeom = pBlob->cb.xGeom; @@ -156965,13 +145082,9 @@ static int rtreeFilter( rtreeReference(pRtree); - /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ freeCursorConstraints(pCsr); - sqlite3_free(pCsr->aPoint); - memset(pCsr, 0, sizeof(RtreeCursor)); - pCsr->base.pVtab = (sqlite3_vtab*)pRtree; - pCsr->iStrategy = idxNum; + if( idxNum==1 ){ /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ @@ -157103,30 +145216,17 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ Rtree *pRtree = (Rtree*)tab; int rc = SQLITE_OK; int ii; - int bMatch = 0; /* True if there exists a MATCH constraint */ i64 nRow; /* Estimated rows returned by this scan */ int iIdx = 0; char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; memset(zIdxStr, 0, sizeof(zIdxStr)); - /* Check if there exists a MATCH constraint - even an unusable one. If there - ** is, do not consider the lookup-by-rowid plan as using such a plan would - ** require the VDBE to evaluate the MATCH constraint, which is not currently - ** possible. */ - for(ii=0; iinConstraint; ii++){ - if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - bMatch = 1; - } - } - assert( pIdxInfo->idxStr==0 ); for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - if( bMatch==0 && p->usable - && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ - ){ + if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ /* We have an equality constraint on the rowid. Use strategy 1. */ int jj; for(jj=0; jj=1); - cell.iRowid = 0; /* Used only to suppress a compiler warning */ - /* Constraint handling. A write operation on an r-tree table may return ** SQLITE_CONSTRAINT for two reasons: ** @@ -158267,19 +146365,11 @@ static int rtreeUpdate( if( nData>1 ){ int ii; - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. - ** - ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared - ** with "column" that are interpreted as table constraints. - ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); - ** This problem was discovered after years of use, so we silently ignore - ** these kinds of misdeclared tables to avoid breaking any legacy. - */ - assert( nData<=(pRtree->nDim*2 + 3) ); - + /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ + assert( nData==(pRtree->nDim*2 + 3) ); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; iinDim*2); ii+=2){ cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ @@ -158290,7 +146380,7 @@ static int rtreeUpdate( }else #endif { - for(ii=0; iinDim*2); ii+=2){ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ @@ -158819,18 +146909,6 @@ static void rtreeFreeCallback(void *p){ sqlite3_free(p); } -/* -** This routine frees the BLOB that is returned by geomCallback(). -*/ -static void rtreeMatchArgFree(void *pArg){ - int i; - RtreeMatchArg *p = (RtreeMatchArg*)pArg; - for(i=0; inParam; i++){ - sqlite3_value_free(p->apSqlParam[i]); - } - sqlite3_free(p); -} - /* ** Each call to sqlite3_rtree_geometry_callback() or ** sqlite3_rtree_query_callback() creates an ordinary SQLite @@ -158849,10 +146927,8 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; int nBlob; - int memErr = 0; - nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue) - + nArg*sizeof(sqlite3_value*); + nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue); pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); if( !pBlob ){ sqlite3_result_error_nomem(ctx); @@ -158860,30 +146936,22 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ int i; pBlob->magic = RTREE_GEOMETRY_MAGIC; pBlob->cb = pGeomCtx[0]; - pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; pBlob->nParam = nArg; for(i=0; iapSqlParam[i] = sqlite3_value_dup(aArg[i]); - if( pBlob->apSqlParam[i]==0 ) memErr = 1; #ifdef SQLITE_RTREE_INT_ONLY pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); #else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); #endif } - if( memErr ){ - sqlite3_result_error_nomem(ctx); - rtreeMatchArgFree(pBlob); - }else{ - sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree); - } + sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free); } } /* ** Register a new geometry function for use with the r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( +SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zGeom, /* Name of the new SQL function */ int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ @@ -158907,7 +146975,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback( ** Register a new 2nd-generation geometry function for use with the ** r-tree MATCH operator. */ -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( +SQLITE_API int sqlite3_rtree_query_callback( sqlite3 *db, /* Register SQL function on this connection */ const char *zQueryFunc, /* Name of new SQL function */ int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ @@ -158932,7 +147000,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback( #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init( +SQLITE_API int sqlite3_rtree_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -158987,10 +147055,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init( /* #include */ #ifndef SQLITE_CORE -/* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #else -/* #include "sqlite3.h" */ #endif /* @@ -159031,6 +147097,7 @@ static int icuLikeCompare( /* Read (and consume) the next character from the input pattern. */ UChar32 uPattern; U8_NEXT_UNSAFE(zPattern, iPattern, uPattern); + assert(uPattern!=0); /* There are now 4 possibilities: ** @@ -159369,7 +147436,6 @@ static void icuLoadCollation( int rc; /* Return code from sqlite3_create_collation_x() */ assert(nArg==2); - (void)nArg; /* Unused parameter */ zLocale = (const char *)sqlite3_value_text(apArg[0]); zName = (const char *)sqlite3_value_text(apArg[1]); @@ -159439,7 +147505,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ #ifdef _WIN32 __declspec(dllexport) #endif -SQLITE_API int SQLITE_STDCALL sqlite3_icu_init( +SQLITE_API int sqlite3_icu_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi @@ -159466,13 +147532,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_icu_init( ************************************************************************* ** This file implements a tokenizer for fts3 based on the ICU library. */ -/* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) #ifdef SQLITE_ENABLE_ICU /* #include */ /* #include */ -/* #include "fts3_tokenizer.h" */ #include /* #include */ @@ -159695,13 +147759,12 @@ static int icuNext( ** The set of routines that implement the simple tokenizer */ static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ - 0, /* xLanguageid */ + 0, /* iVersion */ + icuCreate, /* xCreate */ + icuDestroy, /* xCreate */ + icuOpen, /* xOpen */ + icuClose, /* xClose */ + icuNext, /* xNext */ }; /* @@ -159717,26325 +147780,3 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ -/************** Begin file sqlite3rbu.c **************************************/ -/* -** 2014 August 30 -** -** 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. -** -************************************************************************* -** -** -** OVERVIEW -** -** The RBU extension requires that the RBU update be packaged as an -** SQLite database. The tables it expects to find are described in -** sqlite3rbu.h. Essentially, for each table xyz in the target database -** that the user wishes to write to, a corresponding data_xyz table is -** created in the RBU database and populated with one row for each row to -** update, insert or delete from the target table. -** -** The update proceeds in three stages: -** -** 1) The database is updated. The modified database pages are written -** to a *-oal file. A *-oal file is just like a *-wal file, except -** that it is named "-oal" instead of "-wal". -** Because regular SQLite clients do not look for file named -** "-oal", they go on using the original database in -** rollback mode while the *-oal file is being generated. -** -** During this stage RBU does not update the database by writing -** directly to the target tables. Instead it creates "imposter" -** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses -** to update each b-tree individually. All updates required by each -** b-tree are completed before moving on to the next, and all -** updates are done in sorted key order. -** -** 2) The "-oal" file is moved to the equivalent "-wal" -** location using a call to rename(2). Before doing this the RBU -** module takes an EXCLUSIVE lock on the database file, ensuring -** that there are no other active readers. -** -** Once the EXCLUSIVE lock is released, any other database readers -** detect the new *-wal file and read the database in wal mode. At -** this point they see the new version of the database - including -** the updates made as part of the RBU update. -** -** 3) The new *-wal file is checkpointed. This proceeds in the same way -** as a regular database checkpoint, except that a single frame is -** checkpointed each time sqlite3rbu_step() is called. If the RBU -** handle is closed before the entire *-wal file is checkpointed, -** the checkpoint progress is saved in the RBU database and the -** checkpoint can be resumed by another RBU client at some point in -** the future. -** -** POTENTIAL PROBLEMS -** -** The rename() call might not be portable. And RBU is not currently -** syncing the directory after renaming the file. -** -** When state is saved, any commit to the *-oal file and the commit to -** the RBU update database are not atomic. So if the power fails at the -** wrong moment they might get out of sync. As the main database will be -** committed before the RBU update database this will likely either just -** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE -** constraint violations). -** -** If some client does modify the target database mid RBU update, or some -** other error occurs, the RBU extension will keep throwing errors. It's -** not really clear how to get out of this state. The system could just -** by delete the RBU update database and *-oal file and have the device -** download the update again and start over. -** -** At present, for an UPDATE, both the new.* and old.* records are -** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all -** fields are collected. This means we're probably writing a lot more -** data to disk when saving the state of an ongoing update to the RBU -** update database than is strictly necessary. -** -*/ - -/* #include */ -/* #include */ -/* #include */ - -/* #include "sqlite3.h" */ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) -/************** Include sqlite3rbu.h in the middle of sqlite3rbu.c ***********/ -/************** Begin file sqlite3rbu.h **************************************/ -/* -** 2014 August 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the public interface for the RBU extension. -*/ - -/* -** SUMMARY -** -** Writing a transaction containing a large number of operations on -** b-tree indexes that are collectively larger than the available cache -** memory can be very inefficient. -** -** The problem is that in order to update a b-tree, the leaf page (at least) -** containing the entry being inserted or deleted must be modified. If the -** working set of leaves is larger than the available cache memory, then a -** single leaf that is modified more than once as part of the transaction -** may be loaded from or written to the persistent media multiple times. -** Additionally, because the index updates are likely to be applied in -** random order, access to pages within the database is also likely to be in -** random order, which is itself quite inefficient. -** -** One way to improve the situation is to sort the operations on each index -** by index key before applying them to the b-tree. This leads to an IO -** pattern that resembles a single linear scan through the index b-tree, -** and all but guarantees each modified leaf page is loaded and stored -** exactly once. SQLite uses this trick to improve the performance of -** CREATE INDEX commands. This extension allows it to be used to improve -** the performance of large transactions on existing databases. -** -** Additionally, this extension allows the work involved in writing the -** large transaction to be broken down into sub-transactions performed -** sequentially by separate processes. This is useful if the system cannot -** guarantee that a single update process will run for long enough to apply -** the entire update, for example because the update is being applied on a -** mobile device that is frequently rebooted. Even after the writer process -** has committed one or more sub-transactions, other database clients continue -** to read from the original database snapshot. In other words, partially -** applied transactions are not visible to other clients. -** -** "RBU" stands for "Resumable Bulk Update". As in a large database update -** transmitted via a wireless network to a mobile device. A transaction -** applied using this extension is hence refered to as an "RBU update". -** -** -** LIMITATIONS -** -** An "RBU update" transaction is subject to the following limitations: -** -** * The transaction must consist of INSERT, UPDATE and DELETE operations -** only. -** -** * INSERT statements may not use any default values. -** -** * UPDATE and DELETE statements must identify their target rows by -** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY -** KEY fields may not be updated or deleted. If the table being written -** has no PRIMARY KEY, affected rows must be identified by rowid. -** -** * UPDATE statements may not modify PRIMARY KEY columns. -** -** * No triggers will be fired. -** -** * No foreign key violations are detected or reported. -** -** * CHECK constraints are not enforced. -** -** * No constraint handling mode except for "OR ROLLBACK" is supported. -** -** -** PREPARATION -** -** An "RBU update" is stored as a separate SQLite database. A database -** containing an RBU update is an "RBU database". For each table in the -** target database to be updated, the RBU database should contain a table -** named "data_" containing the same set of columns as the -** target table, and one more - "rbu_control". The data_% table should -** have no PRIMARY KEY or UNIQUE constraints, but each column should have -** the same type as the corresponding column in the target database. -** The "rbu_control" column should have no type at all. For example, if -** the target database contains: -** -** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE); -** -** Then the RBU database should contain: -** -** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control); -** -** The order of the columns in the data_% table does not matter. -** -** Instead of a regular table, the RBU database may also contain virtual -** tables or view named using the data_ naming scheme. -** -** Instead of the plain data_ naming scheme, RBU database tables -** may also be named data_, where is any sequence -** of zero or more numeric characters (0-9). This can be significant because -** tables within the RBU database are always processed in order sorted by -** name. By judicious selection of the the portion of the names -** of the RBU tables the user can therefore control the order in which they -** are processed. This can be useful, for example, to ensure that "external -** content" FTS4 tables are updated before their underlying content tables. -** -** If the target database table is a virtual table or a table that has no -** PRIMARY KEY declaration, the data_% table must also contain a column -** named "rbu_rowid". This column is mapped to the tables implicit primary -** key column - "rowid". Virtual tables for which the "rowid" column does -** not function like a primary key value cannot be updated using RBU. For -** example, if the target db contains either of the following: -** -** CREATE VIRTUAL TABLE x1 USING fts3(a, b); -** CREATE TABLE x1(a, b) -** -** then the RBU database should contain: -** -** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control); -** -** All non-hidden columns (i.e. all columns matched by "SELECT *") of the -** target table must be present in the input table. For virtual tables, -** hidden columns are optional - they are updated by RBU if present in -** the input table, or not otherwise. For example, to write to an fts4 -** table with a hidden languageid column such as: -** -** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid'); -** -** Either of the following input table schemas may be used: -** -** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control); -** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control); -** -** For each row to INSERT into the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain integer value 0. The -** other columns should be set to the values that make up the new record -** to insert. -** -** If the target database table has an INTEGER PRIMARY KEY, it is not -** possible to insert a NULL value into the IPK column. Attempting to -** do so results in an SQLITE_MISMATCH error. -** -** For each row to DELETE from the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain integer value 1. The -** real primary key values of the row to delete should be stored in the -** corresponding columns of the data_% table. The values stored in the -** other columns are not used. -** -** For each row to UPDATE from the target database as part of the RBU -** update, the corresponding data_% table should contain a single record -** with the "rbu_control" column set to contain a value of type text. -** The real primary key values identifying the row to update should be -** stored in the corresponding columns of the data_% table row, as should -** the new values of all columns being update. The text value in the -** "rbu_control" column must contain the same number of characters as -** there are columns in the target database table, and must consist entirely -** of 'x' and '.' characters (or in some special cases 'd' - see below). For -** each column that is being updated, the corresponding character is set to -** 'x'. For those that remain as they are, the corresponding character of the -** rbu_control value should be set to '.'. For example, given the tables -** above, the update statement: -** -** UPDATE t1 SET c = 'usa' WHERE a = 4; -** -** is represented by the data_t1 row created by: -** -** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x'); -** -** Instead of an 'x' character, characters of the rbu_control value specified -** for UPDATEs may also be set to 'd'. In this case, instead of updating the -** target table with the value stored in the corresponding data_% column, the -** user-defined SQL function "rbu_delta()" is invoked and the result stored in -** the target table column. rbu_delta() is invoked with two arguments - the -** original value currently stored in the target table column and the -** value specified in the data_xxx table. -** -** For example, this row: -** -** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d'); -** -** is similar to an UPDATE statement such as: -** -** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4; -** -** Finally, if an 'f' character appears in place of a 'd' or 's' in an -** ota_control string, the contents of the data_xxx table column is assumed -** to be a "fossil delta" - a patch to be applied to a blob value in the -** format used by the fossil source-code management system. In this case -** the existing value within the target database table must be of type BLOB. -** It is replaced by the result of applying the specified fossil delta to -** itself. -** -** If the target database table is a virtual table or a table with no PRIMARY -** KEY, the rbu_control value should not include a character corresponding -** to the rbu_rowid value. For example, this: -** -** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) -** VALUES(NULL, 'usa', 12, '.x'); -** -** causes a result similar to: -** -** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; -** -** The data_xxx tables themselves should have no PRIMARY KEY declarations. -** However, RBU is more efficient if reading the rows in from each data_xxx -** table in "rowid" order is roughly the same as reading them sorted by -** the PRIMARY KEY of the corresponding target database table. In other -** words, rows should be sorted using the destination table PRIMARY KEY -** fields before they are inserted into the data_xxx tables. -** -** USAGE -** -** The API declared below allows an application to apply an RBU update -** stored on disk to an existing target database. Essentially, the -** application: -** -** 1) Opens an RBU handle using the sqlite3rbu_open() function. -** -** 2) Registers any required virtual table modules with the database -** handle returned by sqlite3rbu_db(). Also, if required, register -** the rbu_delta() implementation. -** -** 3) Calls the sqlite3rbu_step() function one or more times on -** the new handle. Each call to sqlite3rbu_step() performs a single -** b-tree operation, so thousands of calls may be required to apply -** a complete update. -** -** 4) Calls sqlite3rbu_close() to close the RBU update handle. If -** sqlite3rbu_step() has been called enough times to completely -** apply the update to the target database, then the RBU database -** is marked as fully applied. Otherwise, the state of the RBU -** update application is saved in the RBU database for later -** resumption. -** -** See comments below for more detail on APIs. -** -** If an update is only partially applied to the target database by the -** time sqlite3rbu_close() is called, various state information is saved -** within the RBU database. This allows subsequent processes to automatically -** resume the RBU update from where it left off. -** -** To remove all RBU extension state information, returning an RBU database -** to its original contents, it is sufficient to drop all tables that begin -** with the prefix "rbu_" -** -** DATABASE LOCKING -** -** An RBU update may not be applied to a database in WAL mode. Attempting -** to do so is an error (SQLITE_ERROR). -** -** While an RBU handle is open, a SHARED lock may be held on the target -** database file. This means it is possible for other clients to read the -** database, but not to write it. -** -** If an RBU update is started and then suspended before it is completed, -** then an external client writes to the database, then attempting to resume -** the suspended RBU update is also an error (SQLITE_BUSY). -*/ - -#ifndef _SQLITE3RBU_H -#define _SQLITE3RBU_H - -/* #include "sqlite3.h" ** Required for error code definitions ** */ - -#if 0 -extern "C" { -#endif - -typedef struct sqlite3rbu sqlite3rbu; - -/* -** Open an RBU handle. -** -** Argument zTarget is the path to the target database. Argument zRbu is -** the path to the RBU database. Each call to this function must be matched -** by a call to sqlite3rbu_close(). When opening the databases, RBU passes -** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget -** or zRbu begin with "file:", it will be interpreted as an SQLite -** database URI, not a regular file name. -** -** If the zState argument is passed a NULL value, the RBU extension stores -** the current state of the update (how many rows have been updated, which -** indexes are yet to be updated etc.) within the RBU database itself. This -** can be convenient, as it means that the RBU application does not need to -** organize removing a separate state file after the update is concluded. -** Or, if zState is non-NULL, it must be a path to a database file in which -** the RBU extension can store the state of the update. -** -** When resuming an RBU update, the zState argument must be passed the same -** value as when the RBU update was started. -** -** Once the RBU update is finished, the RBU extension does not -** automatically remove any zState database file, even if it created it. -** -** By default, RBU uses the default VFS to access the files on disk. To -** use a VFS other than the default, an SQLite "file:" URI containing a -** "vfs=..." option may be passed as the zTarget option. -** -** IMPORTANT NOTE FOR ZIPVFS USERS: The RBU extension works with all of -** SQLite's built-in VFSs, including the multiplexor VFS. However it does -** not work out of the box with zipvfs. Refer to the comment describing -** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. -*/ -SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( - const char *zTarget, - const char *zRbu, - const char *zState -); - -/* -** Internally, each RBU connection uses a separate SQLite database -** connection to access the target and rbu update databases. This -** API allows the application direct access to these database handles. -** -** The first argument passed to this function must be a valid, open, RBU -** handle. The second argument should be passed zero to access the target -** database handle, or non-zero to access the rbu update database handle. -** Accessing the underlying database handles may be useful in the -** following scenarios: -** -** * If any target tables are virtual tables, it may be necessary to -** call sqlite3_create_module() on the target database handle to -** register the required virtual table implementations. -** -** * If the data_xxx tables in the RBU source database are virtual -** tables, the application may need to call sqlite3_create_module() on -** the rbu update db handle to any required virtual table -** implementations. -** -** * If the application uses the "rbu_delta()" feature described above, -** it must use sqlite3_create_function() or similar to register the -** rbu_delta() implementation with the target database handle. -** -** If an error has occurred, either while opening or stepping the RBU object, -** this function may return NULL. The error code and message may be collected -** when sqlite3rbu_close() is called. -** -** Database handles returned by this function remain valid until the next -** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db(). -*/ -SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); - -/* -** Do some work towards applying the RBU update to the target db. -** -** Return SQLITE_DONE if the update has been completely applied, or -** SQLITE_OK if no error occurs but there remains work to do to apply -** the RBU update. If an error does occur, some other error code is -** returned. -** -** Once a call to sqlite3rbu_step() has returned a value other than -** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops -** that immediately return the same value. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); - -/* -** Force RBU to save its state to disk. -** -** If a power failure or application crash occurs during an update, following -** system recovery RBU may resume the update from the point at which the state -** was last saved. In other words, from the most recent successful call to -** sqlite3rbu_close() or this function. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_savestate(sqlite3rbu *pRbu); - -/* -** Close an RBU handle. -** -** If the RBU update has been completely applied, mark the RBU database -** as fully applied. Otherwise, assuming no error has occurred, save the -** current state of the RBU update appliation to the RBU database. -** -** If an error has already occurred as part of an sqlite3rbu_step() -** or sqlite3rbu_open() call, or if one occurs within this function, an -** SQLite error code is returned. Additionally, *pzErrmsg may be set to -** point to a buffer containing a utf-8 formatted English language error -** message. It is the responsibility of the caller to eventually free any -** such buffer using sqlite3_free(). -** -** Otherwise, if no error occurs, this function returns SQLITE_OK if the -** update has been partially applied, or SQLITE_DONE if it has been -** completely applied. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); - -/* -** Return the total number of key-value operations (inserts, deletes or -** updates) that have been performed on the target database since the -** current RBU update was started. -*/ -SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); - -/* -** Create an RBU VFS named zName that accesses the underlying file-system -** via existing VFS zParent. Or, if the zParent parameter is passed NULL, -** then the new RBU VFS uses the default system VFS to access the file-system. -** The new object is registered as a non-default VFS with SQLite before -** returning. -** -** Part of the RBU implementation uses a custom VFS object. Usually, this -** object is created and deleted automatically by RBU. -** -** The exception is for applications that also use zipvfs. In this case, -** the custom VFS must be explicitly created by the user before the RBU -** handle is opened. The RBU VFS should be installed so that the zipvfs -** VFS uses the RBU VFS, which in turn uses any other VFS layers in use -** (for example multiplexor) to access the file-system. For example, -** to assemble an RBU enabled VFS stack that uses both zipvfs and -** multiplexor (error checking omitted): -** -** // Create a VFS named "multiplex" (not the default). -** sqlite3_multiplex_initialize(0, 0); -** -** // Create an rbu VFS named "rbu" that uses multiplexor. If the -** // second argument were replaced with NULL, the "rbu" VFS would -** // access the file-system via the system default VFS, bypassing the -** // multiplexor. -** sqlite3rbu_create_vfs("rbu", "multiplex"); -** -** // Create a zipvfs VFS named "zipvfs" that uses rbu. -** zipvfs_create_vfs_v3("zipvfs", "rbu", 0, xCompressorAlgorithmDetector); -** -** // Make zipvfs the default VFS. -** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); -** -** Because the default VFS created above includes a RBU functionality, it -** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack -** that does not include the RBU layer results in an error. -** -** The overhead of adding the "rbu" VFS to the system is negligible for -** non-RBU users. There is no harm in an application accessing the -** file-system via "rbu" all the time, even if it only uses RBU functionality -** occasionally. -*/ -SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent); - -/* -** Deregister and destroy an RBU vfs created by an earlier call to -** sqlite3rbu_create_vfs(). -** -** VFS objects are not reference counted. If a VFS object is destroyed -** before all database handles that use it have been closed, the results -** are undefined. -*/ -SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); - -#if 0 -} /* end of the 'extern "C"' block */ -#endif - -#endif /* _SQLITE3RBU_H */ - -/************** End of sqlite3rbu.h ******************************************/ -/************** Continuing where we left off in sqlite3rbu.c *****************/ - -#if defined(_WIN32_WCE) -/* #include "windows.h" */ -#endif - -/* Maximum number of prepared UPDATE statements held by this module */ -#define SQLITE_RBU_UPDATE_CACHESIZE 16 - -/* -** Swap two objects of type TYPE. -*/ -#if !defined(SQLITE_AMALGAMATION) -# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} -#endif - -/* -** The rbu_state table is used to save the state of a partially applied -** update so that it can be resumed later. The table consists of integer -** keys mapped to values as follows: -** -** RBU_STATE_STAGE: -** May be set to integer values 1, 2, 4 or 5. As follows: -** 1: the *-rbu file is currently under construction. -** 2: the *-rbu file has been constructed, but not yet moved -** to the *-wal path. -** 4: the checkpoint is underway. -** 5: the rbu update has been checkpointed. -** -** RBU_STATE_TBL: -** Only valid if STAGE==1. The target database name of the table -** currently being written. -** -** RBU_STATE_IDX: -** Only valid if STAGE==1. The target database name of the index -** currently being written, or NULL if the main table is currently being -** updated. -** -** RBU_STATE_ROW: -** Only valid if STAGE==1. Number of rows already processed for the current -** table/index. -** -** RBU_STATE_PROGRESS: -** Trbul number of sqlite3rbu_step() calls made so far as part of this -** rbu update. -** -** RBU_STATE_CKPT: -** Valid if STAGE==4. The 64-bit checksum associated with the wal-index -** header created by recovering the *-wal file. This is used to detect -** cases when another client appends frames to the *-wal file in the -** middle of an incremental checkpoint (an incremental checkpoint cannot -** be continued if this happens). -** -** RBU_STATE_COOKIE: -** Valid if STAGE==1. The current change-counter cookie value in the -** target db file. -** -** RBU_STATE_OALSZ: -** Valid if STAGE==1. The size in bytes of the *-oal file. -*/ -#define RBU_STATE_STAGE 1 -#define RBU_STATE_TBL 2 -#define RBU_STATE_IDX 3 -#define RBU_STATE_ROW 4 -#define RBU_STATE_PROGRESS 5 -#define RBU_STATE_CKPT 6 -#define RBU_STATE_COOKIE 7 -#define RBU_STATE_OALSZ 8 - -#define RBU_STAGE_OAL 1 -#define RBU_STAGE_MOVE 2 -#define RBU_STAGE_CAPTURE 3 -#define RBU_STAGE_CKPT 4 -#define RBU_STAGE_DONE 5 - - -#define RBU_CREATE_STATE \ - "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" - -typedef struct RbuFrame RbuFrame; -typedef struct RbuObjIter RbuObjIter; -typedef struct RbuState RbuState; -typedef struct rbu_vfs rbu_vfs; -typedef struct rbu_file rbu_file; -typedef struct RbuUpdateStmt RbuUpdateStmt; - -#if !defined(SQLITE_AMALGAMATION) -typedef unsigned int u32; -typedef unsigned char u8; -typedef sqlite3_int64 i64; -#endif - -/* -** These values must match the values defined in wal.c for the equivalent -** locks. These are not magic numbers as they are part of the SQLite file -** format. -*/ -#define WAL_LOCK_WRITE 0 -#define WAL_LOCK_CKPT 1 -#define WAL_LOCK_READ0 3 - -/* -** A structure to store values read from the rbu_state table in memory. -*/ -struct RbuState { - int eStage; - char *zTbl; - char *zIdx; - i64 iWalCksum; - int nRow; - i64 nProgress; - u32 iCookie; - i64 iOalSz; -}; - -struct RbuUpdateStmt { - char *zMask; /* Copy of update mask used with pUpdate */ - sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ - RbuUpdateStmt *pNext; -}; - -/* -** An iterator of this type is used to iterate through all objects in -** the target database that require updating. For each such table, the -** iterator visits, in order: -** -** * the table itself, -** * each index of the table (zero or more points to visit), and -** * a special "cleanup table" state. -** -** abIndexed: -** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, -** it points to an array of flags nTblCol elements in size. The flag is -** set for each column that is either a part of the PK or a part of an -** index. Or clear otherwise. -** -*/ -struct RbuObjIter { - sqlite3_stmt *pTblIter; /* Iterate through tables */ - sqlite3_stmt *pIdxIter; /* Index iterator */ - int nTblCol; /* Size of azTblCol[] array */ - char **azTblCol; /* Array of unquoted target column names */ - char **azTblType; /* Array of target column types */ - int *aiSrcOrder; /* src table col -> target table col */ - u8 *abTblPk; /* Array of flags, set on target PK columns */ - u8 *abNotNull; /* Array of flags, set on NOT NULL columns */ - u8 *abIndexed; /* Array of flags, set on indexed & PK cols */ - int eType; /* Table type - an RBU_PK_XXX value */ - - /* Output variables. zTbl==0 implies EOF. */ - int bCleanup; /* True in "cleanup" state */ - const char *zTbl; /* Name of target db table */ - const char *zDataTbl; /* Name of rbu db table (or null) */ - const char *zIdx; /* Name of target db index (or null) */ - int iTnum; /* Root page of current object */ - int iPkTnum; /* If eType==EXTERNAL, root of PK index */ - int bUnique; /* Current index is unique */ - - /* Statements created by rbuObjIterPrepareAll() */ - int nCol; /* Number of columns in current object */ - sqlite3_stmt *pSelect; /* Source data */ - sqlite3_stmt *pInsert; /* Statement for INSERT operations */ - sqlite3_stmt *pDelete; /* Statement for DELETE ops */ - sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ - - /* Last UPDATE used (for PK b-tree updates only), or NULL. */ - RbuUpdateStmt *pRbuUpdate; -}; - -/* -** Values for RbuObjIter.eType -** -** 0: Table does not exist (error) -** 1: Table has an implicit rowid. -** 2: Table has an explicit IPK column. -** 3: Table has an external PK index. -** 4: Table is WITHOUT ROWID. -** 5: Table is a virtual table. -*/ -#define RBU_PK_NOTABLE 0 -#define RBU_PK_NONE 1 -#define RBU_PK_IPK 2 -#define RBU_PK_EXTERNAL 3 -#define RBU_PK_WITHOUT_ROWID 4 -#define RBU_PK_VTAB 5 - - -/* -** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs -** one of the following operations. -*/ -#define RBU_INSERT 1 /* Insert on a main table b-tree */ -#define RBU_DELETE 2 /* Delete a row from a main table b-tree */ -#define RBU_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */ -#define RBU_IDX_INSERT 4 /* Insert on an aux. index b-tree */ -#define RBU_UPDATE 5 /* Update a row in a main table b-tree */ - - -/* -** A single step of an incremental checkpoint - frame iWalFrame of the wal -** file should be copied to page iDbPage of the database file. -*/ -struct RbuFrame { - u32 iDbPage; - u32 iWalFrame; -}; - -/* -** RBU handle. -*/ -struct sqlite3rbu { - int eStage; /* Value of RBU_STATE_STAGE field */ - sqlite3 *dbMain; /* target database handle */ - sqlite3 *dbRbu; /* rbu database handle */ - char *zTarget; /* Path to target db */ - char *zRbu; /* Path to rbu db */ - char *zState; /* Path to state db (or NULL if zRbu) */ - char zStateDb[5]; /* Db name for state ("stat" or "main") */ - int rc; /* Value returned by last rbu_step() call */ - char *zErrmsg; /* Error message if rc!=SQLITE_OK */ - int nStep; /* Rows processed for current object */ - int nProgress; /* Rows processed for all objects */ - RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ - const char *zVfsName; /* Name of automatically created rbu vfs */ - rbu_file *pTargetFd; /* File handle open on target db */ - i64 iOalSz; - - /* The following state variables are used as part of the incremental - ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding - ** function rbuSetupCheckpoint() for details. */ - u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ - u32 mLock; - int nFrame; /* Entries in aFrame[] array */ - int nFrameAlloc; /* Allocated size of aFrame[] array */ - RbuFrame *aFrame; - int pgsz; - u8 *aBuf; - i64 iWalCksum; -}; - -/* -** An rbu VFS is implemented using an instance of this structure. -*/ -struct rbu_vfs { - sqlite3_vfs base; /* rbu VFS shim methods */ - sqlite3_vfs *pRealVfs; /* Underlying VFS */ - sqlite3_mutex *mutex; /* Mutex to protect pMain */ - rbu_file *pMain; /* Linked list of main db files */ -}; - -/* -** Each file opened by an rbu VFS is represented by an instance of -** the following structure. -*/ -struct rbu_file { - sqlite3_file base; /* sqlite3_file methods */ - sqlite3_file *pReal; /* Underlying file handle */ - rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ - sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ - - int openFlags; /* Flags this file was opened with */ - u32 iCookie; /* Cookie value for main db files */ - u8 iWriteVer; /* "write-version" value for main db files */ - - int nShm; /* Number of entries in apShm[] array */ - char **apShm; /* Array of mmap'd *-shm regions */ - char *zDel; /* Delete this when closing file */ - - const char *zWal; /* Wal filename for this main db file */ - rbu_file *pWalFd; /* Wal file descriptor for this main db */ - rbu_file *pMainNext; /* Next MAIN_DB file */ -}; - - -/************************************************************************* -** The following three functions, found below: -** -** rbuDeltaGetInt() -** rbuDeltaChecksum() -** rbuDeltaApply() -** -** are lifted from the fossil source code (http://fossil-scm.org). They -** are used to implement the scalar SQL function rbu_fossil_delta(). -*/ - -/* -** Read bytes from *pz and convert them into a positive integer. When -** finished, leave *pz pointing to the first character past the end of -** the integer. The *pLen parameter holds the length of the string -** in *pz and is decremented once for each character in the integer. -*/ -static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){ - static const signed char zValue[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36, - -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1, - }; - unsigned int v = 0; - int c; - unsigned char *z = (unsigned char*)*pz; - unsigned char *zStart = z; - while( (c = zValue[0x7f&*(z++)])>=0 ){ - v = (v<<6) + c; - } - z--; - *pLen -= z - zStart; - *pz = (char*)z; - return v; -} - -/* -** Compute a 32-bit checksum on the N-byte buffer. Return the result. -*/ -static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){ - const unsigned char *z = (const unsigned char *)zIn; - unsigned sum0 = 0; - unsigned sum1 = 0; - unsigned sum2 = 0; - unsigned sum3 = 0; - while(N >= 16){ - sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]); - sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]); - sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]); - sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]); - z += 16; - N -= 16; - } - while(N >= 4){ - sum0 += z[0]; - sum1 += z[1]; - sum2 += z[2]; - sum3 += z[3]; - z += 4; - N -= 4; - } - sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24); - switch(N){ - case 3: sum3 += (z[2] << 8); - case 2: sum3 += (z[1] << 16); - case 1: sum3 += (z[0] << 24); - default: ; - } - return sum3; -} - -/* -** Apply a delta. -** -** The output buffer should be big enough to hold the whole output -** file and a NUL terminator at the end. The delta_output_size() -** routine will determine this size for you. -** -** The delta string should be null-terminated. But the delta string -** may contain embedded NUL characters (if the input and output are -** binary files) so we also have to pass in the length of the delta in -** the lenDelta parameter. -** -** This function returns the size of the output file in bytes (excluding -** the final NUL terminator character). Except, if the delta string is -** malformed or intended for use with a source file other than zSrc, -** then this routine returns -1. -** -** Refer to the delta_create() documentation above for a description -** of the delta file format. -*/ -static int rbuDeltaApply( - const char *zSrc, /* The source or pattern file */ - int lenSrc, /* Length of the source file */ - const char *zDelta, /* Delta to apply to the pattern */ - int lenDelta, /* Length of the delta */ - char *zOut /* Write the output into this preallocated buffer */ -){ - unsigned int limit; - unsigned int total = 0; -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST - char *zOrigOut = zOut; -#endif - - limit = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - zDelta++; lenDelta--; - while( *zDelta && lenDelta>0 ){ - unsigned int cnt, ofst; - cnt = rbuDeltaGetInt(&zDelta, &lenDelta); - switch( zDelta[0] ){ - case '@': { - zDelta++; lenDelta--; - ofst = rbuDeltaGetInt(&zDelta, &lenDelta); - if( lenDelta>0 && zDelta[0]!=',' ){ - /* ERROR: copy command not terminated by ',' */ - return -1; - } - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: copy exceeds output file size */ - return -1; - } - if( (int)(ofst+cnt) > lenSrc ){ - /* ERROR: copy extends past end of input */ - return -1; - } - memcpy(zOut, &zSrc[ofst], cnt); - zOut += cnt; - break; - } - case ':': { - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: insert command gives an output larger than predicted */ - return -1; - } - if( (int)cnt>lenDelta ){ - /* ERROR: insert count exceeds size of delta */ - return -1; - } - memcpy(zOut, zDelta, cnt); - zOut += cnt; - zDelta += cnt; - lenDelta -= cnt; - break; - } - case ';': { - zDelta++; lenDelta--; - zOut[0] = 0; -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST - if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ - /* ERROR: bad checksum */ - return -1; - } -#endif - if( total!=limit ){ - /* ERROR: generated size does not match predicted size */ - return -1; - } - return total; - } - default: { - /* ERROR: unknown delta operator */ - return -1; - } - } - } - /* ERROR: unterminated delta */ - return -1; -} - -static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){ - int size; - size = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - return size; -} - -/* -** End of code taken from fossil. -*************************************************************************/ - -/* -** Implementation of SQL scalar function rbu_fossil_delta(). -** -** This function applies a fossil delta patch to a blob. Exactly two -** arguments must be passed to this function. The first is the blob to -** patch and the second the patch to apply. If no error occurs, this -** function returns the patched blob. -*/ -static void rbuFossilDeltaFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *aDelta; - int nDelta; - const char *aOrig; - int nOrig; - - int nOut; - int nOut2; - char *aOut; - - assert( argc==2 ); - - nOrig = sqlite3_value_bytes(argv[0]); - aOrig = (const char*)sqlite3_value_blob(argv[0]); - nDelta = sqlite3_value_bytes(argv[1]); - aDelta = (const char*)sqlite3_value_blob(argv[1]); - - /* Figure out the size of the output */ - nOut = rbuDeltaOutputSize(aDelta, nDelta); - if( nOut<0 ){ - sqlite3_result_error(context, "corrupt fossil delta", -1); - return; - } - - aOut = sqlite3_malloc(nOut+1); - if( aOut==0 ){ - sqlite3_result_error_nomem(context); - }else{ - nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut); - if( nOut2!=nOut ){ - sqlite3_result_error(context, "corrupt fossil delta", -1); - }else{ - sqlite3_result_blob(context, aOut, nOut, sqlite3_free); - } - } -} - - -/* -** Prepare the SQL statement in buffer zSql against database handle db. -** If successful, set *ppStmt to point to the new statement and return -** SQLITE_OK. -** -** Otherwise, if an error does occur, set *ppStmt to NULL and return -** an SQLite error code. Additionally, set output variable *pzErrmsg to -** point to a buffer containing an error message. It is the responsibility -** of the caller to (eventually) free this buffer using sqlite3_free(). -*/ -static int prepareAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - const char *zSql -){ - int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - *ppStmt = 0; - } - return rc; -} - -/* -** Reset the SQL statement passed as the first argument. Return a copy -** of the value returned by sqlite3_reset(). -** -** If an error has occurred, then set *pzErrmsg to point to a buffer -** containing an error message. It is the responsibility of the caller -** to eventually free this buffer using sqlite3_free(). -*/ -static int resetAndCollectError(sqlite3_stmt *pStmt, char **pzErrmsg){ - int rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt))); - } - return rc; -} - -/* -** Unless it is NULL, argument zSql points to a buffer allocated using -** sqlite3_malloc containing an SQL statement. This function prepares the SQL -** statement against database db and frees the buffer. If statement -** compilation is successful, *ppStmt is set to point to the new statement -** handle and SQLITE_OK is returned. -** -** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code -** returned. In this case, *pzErrmsg may also be set to point to an error -** message. It is the responsibility of the caller to free this error message -** buffer using sqlite3_free(). -** -** If argument zSql is NULL, this function assumes that an OOM has occurred. -** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL. -*/ -static int prepareFreeAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - char *zSql -){ - int rc; - assert( *pzErrmsg==0 ); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - *ppStmt = 0; - }else{ - rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); - sqlite3_free(zSql); - } - return rc; -} - -/* -** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated -** by an earlier call to rbuObjIterCacheTableInfo(). -*/ -static void rbuObjIterFreeCols(RbuObjIter *pIter){ - int i; - for(i=0; inTblCol; i++){ - sqlite3_free(pIter->azTblCol[i]); - sqlite3_free(pIter->azTblType[i]); - } - sqlite3_free(pIter->azTblCol); - pIter->azTblCol = 0; - pIter->azTblType = 0; - pIter->aiSrcOrder = 0; - pIter->abTblPk = 0; - pIter->abNotNull = 0; - pIter->nTblCol = 0; - pIter->eType = 0; /* Invalid value */ -} - -/* -** Finalize all statements and free all allocations that are specific to -** the current object (table/index pair). -*/ -static void rbuObjIterClearStatements(RbuObjIter *pIter){ - RbuUpdateStmt *pUp; - - sqlite3_finalize(pIter->pSelect); - sqlite3_finalize(pIter->pInsert); - sqlite3_finalize(pIter->pDelete); - sqlite3_finalize(pIter->pTmpInsert); - pUp = pIter->pRbuUpdate; - while( pUp ){ - RbuUpdateStmt *pTmp = pUp->pNext; - sqlite3_finalize(pUp->pUpdate); - sqlite3_free(pUp); - pUp = pTmp; - } - - pIter->pSelect = 0; - pIter->pInsert = 0; - pIter->pDelete = 0; - pIter->pRbuUpdate = 0; - pIter->pTmpInsert = 0; - pIter->nCol = 0; -} - -/* -** Clean up any resources allocated as part of the iterator object passed -** as the only argument. -*/ -static void rbuObjIterFinalize(RbuObjIter *pIter){ - rbuObjIterClearStatements(pIter); - sqlite3_finalize(pIter->pTblIter); - sqlite3_finalize(pIter->pIdxIter); - rbuObjIterFreeCols(pIter); - memset(pIter, 0, sizeof(RbuObjIter)); -} - -/* -** Advance the iterator to the next position. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the next entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ - int rc = p->rc; - if( rc==SQLITE_OK ){ - - /* Free any SQLite statements used while processing the previous object */ - rbuObjIterClearStatements(pIter); - if( pIter->zIdx==0 ){ - rc = sqlite3_exec(p->dbMain, - "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update2_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_delete_tr;" - , 0, 0, &p->zErrmsg - ); - } - - if( rc==SQLITE_OK ){ - if( pIter->bCleanup ){ - rbuObjIterFreeCols(pIter); - pIter->bCleanup = 0; - rc = sqlite3_step(pIter->pTblIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); - pIter->zTbl = 0; - }else{ - pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); - pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); - rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; - } - }else{ - if( pIter->zIdx==0 ){ - sqlite3_stmt *pIdx = pIter->pIdxIter; - rc = sqlite3_bind_text(pIdx, 1, pIter->zTbl, -1, SQLITE_STATIC); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_step(pIter->pIdxIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pIdxIter, &p->zErrmsg); - pIter->bCleanup = 1; - pIter->zIdx = 0; - }else{ - pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0); - pIter->iTnum = sqlite3_column_int(pIter->pIdxIter, 1); - pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2); - rc = pIter->zIdx ? SQLITE_OK : SQLITE_NOMEM; - } - } - } - } - } - - if( rc!=SQLITE_OK ){ - rbuObjIterFinalize(pIter); - p->rc = rc; - } - return rc; -} - - -/* -** The implementation of the rbu_target_name() SQL function. This function -** accepts one argument - the name of a table in the RBU database. If the -** table name matches the pattern: -** -** data[0-9]_ -** -** where is any sequence of 1 or more characters, is returned. -** Otherwise, if the only argument does not match the above pattern, an SQL -** NULL is returned. -** -** "data_t1" -> "t1" -** "data0123_t2" -> "t2" -** "dataAB_t3" -> NULL -*/ -static void rbuTargetNameFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zIn; - assert( argc==1 ); - - zIn = (const char*)sqlite3_value_text(argv[0]); - if( zIn && strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ - int i; - for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); - if( zIn[i]=='_' && zIn[i+1] ){ - sqlite3_result_text(context, &zIn[i+1], -1, SQLITE_STATIC); - } - } -} - -/* -** Initialize the iterator structure passed as the second argument. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the first entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ - int rc; - memset(pIter, 0, sizeof(RbuObjIter)); - - rc = prepareAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, - "SELECT rbu_target_name(name) AS target, name FROM sqlite_master " - "WHERE type IN ('table', 'view') AND target IS NOT NULL " - "ORDER BY name" - ); - - if( rc==SQLITE_OK ){ - rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, - "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " - " FROM main.sqlite_master " - " WHERE type='index' AND tbl_name = ?" - ); - } - - pIter->bCleanup = 1; - p->rc = rc; - return rbuObjIterNext(p, pIter); -} - -/* -** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, -** an error code is stored in the RBU handle passed as the first argument. -** -** If an error has already occurred (p->rc is already set to something other -** than SQLITE_OK), then this function returns NULL without modifying the -** stored error code. In this case it still calls sqlite3_free() on any -** printf() parameters associated with %z conversions. -*/ -static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ - char *zSql = 0; - va_list ap; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ) p->rc = SQLITE_NOMEM; - }else{ - sqlite3_free(zSql); - zSql = 0; - } - va_end(ap); - return zSql; -} - -/* -** Argument zFmt is a sqlite3_mprintf() style format string. The trailing -** arguments are the usual subsitution values. This function performs -** the printf() style substitutions and executes the result as an SQL -** statement on the RBU handles database. -** -** If an error occurs, an error code and error message is stored in the -** RBU handle. If an error has already occurred when this function is -** called, it is a no-op. -*/ -static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ - va_list ap; - char *zSql; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg); - } - } - sqlite3_free(zSql); - va_end(ap); - return p->rc; -} - -/* -** Attempt to allocate and return a pointer to a zeroed block of nByte -** bytes. -** -** If an error (i.e. an OOM condition) occurs, return NULL and leave an -** error code in the rbu handle passed as the first argument. Or, if an -** error has already occurred when this function is called, return NULL -** immediately without attempting the allocation or modifying the stored -** error code. -*/ -static void *rbuMalloc(sqlite3rbu *p, int nByte){ - void *pRet = 0; - if( p->rc==SQLITE_OK ){ - assert( nByte>0 ); - pRet = sqlite3_malloc(nByte); - if( pRet==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - memset(pRet, 0, nByte); - } - } - return pRet; -} - - -/* -** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that -** there is room for at least nCol elements. If an OOM occurs, store an -** error code in the RBU handle passed as the first argument. -*/ -static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ - int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; - char **azNew; - - azNew = (char**)rbuMalloc(p, nByte); - if( azNew ){ - pIter->azTblCol = azNew; - pIter->azTblType = &azNew[nCol]; - pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol]; - pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol]; - pIter->abNotNull = (u8*)&pIter->abTblPk[nCol]; - pIter->abIndexed = (u8*)&pIter->abNotNull[nCol]; - } -} - -/* -** The first argument must be a nul-terminated string. This function -** returns a copy of the string in memory obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free this memory -** using sqlite3_free(). -** -** If an OOM condition is encountered when attempting to allocate memory, -** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, -** if the allocation succeeds, (*pRc) is left unchanged. -*/ -static char *rbuStrndup(const char *zStr, int *pRc){ - char *zRet = 0; - - assert( *pRc==SQLITE_OK ); - if( zStr ){ - int nCopy = strlen(zStr) + 1; - zRet = (char*)sqlite3_malloc(nCopy); - if( zRet ){ - memcpy(zRet, zStr, nCopy); - }else{ - *pRc = SQLITE_NOMEM; - } - } - - return zRet; -} - -/* -** Finalize the statement passed as the second argument. -** -** If the sqlite3_finalize() call indicates that an error occurs, and the -** rbu handle error code is not already set, set the error code and error -** message accordingly. -*/ -static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){ - sqlite3 *db = sqlite3_db_handle(pStmt); - int rc = sqlite3_finalize(pStmt); - if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){ - p->rc = rc; - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } -} - -/* Determine the type of a table. -** -** peType is of type (int*), a pointer to an output parameter of type -** (int). This call sets the output parameter as follows, depending -** on the type of the table specified by parameters dbName and zTbl. -** -** RBU_PK_NOTABLE: No such table. -** RBU_PK_NONE: Table has an implicit rowid. -** RBU_PK_IPK: Table has an explicit IPK column. -** RBU_PK_EXTERNAL: Table has an external PK index. -** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. -** RBU_PK_VTAB: Table is a virtual table. -** -** Argument *piPk is also of type (int*), and also points to an output -** parameter. Unless the table has an external primary key index -** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, -** if the table does have an external primary key index, then *piPk -** is set to the root page number of the primary key index before -** returning. -** -** ALGORITHM: -** -** if( no entry exists in sqlite_master ){ -** return RBU_PK_NOTABLE -** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ -** return RBU_PK_VTAB -** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ -** if( the index that is the pk exists in sqlite_master ){ -** *piPK = rootpage of that index. -** return RBU_PK_EXTERNAL -** }else{ -** return RBU_PK_WITHOUT_ROWID -** } -** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ -** return RBU_PK_IPK -** }else{ -** return RBU_PK_NONE -** } -*/ -static void rbuTableType( - sqlite3rbu *p, - const char *zTab, - int *peType, - int *piTnum, - int *piPk -){ - /* - ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q) - ** 1) PRAGMA index_list = ? - ** 2) SELECT count(*) FROM sqlite_master where name=%Q - ** 3) PRAGMA table_info = ? - */ - sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; - - *peType = RBU_PK_NOTABLE; - *piPk = 0; - - assert( p->rc==SQLITE_OK ); - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, - sqlite3_mprintf( - "SELECT (sql LIKE 'create virtual%%'), rootpage" - " FROM sqlite_master" - " WHERE name=%Q", zTab - )); - if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ - /* Either an error, or no such table. */ - goto rbuTableType_end; - } - if( sqlite3_column_int(aStmt[0], 0) ){ - *peType = RBU_PK_VTAB; /* virtual table */ - goto rbuTableType_end; - } - *piTnum = sqlite3_column_int(aStmt[0], 1); - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, - sqlite3_mprintf("PRAGMA index_list=%Q",zTab) - ); - if( p->rc ) goto rbuTableType_end; - while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ - const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); - const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); - if( zOrig && zIdx && zOrig[0]=='p' ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, - sqlite3_mprintf( - "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx - )); - if( p->rc==SQLITE_OK ){ - if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ - *piPk = sqlite3_column_int(aStmt[2], 0); - *peType = RBU_PK_EXTERNAL; - }else{ - *peType = RBU_PK_WITHOUT_ROWID; - } - } - goto rbuTableType_end; - } - } - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info=%Q",zTab) - ); - if( p->rc==SQLITE_OK ){ - while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ - if( sqlite3_column_int(aStmt[3],5)>0 ){ - *peType = RBU_PK_IPK; /* explicit IPK column */ - goto rbuTableType_end; - } - } - *peType = RBU_PK_NONE; - } - -rbuTableType_end: { - unsigned int i; - for(i=0; iabIndexed[] array. -*/ -static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ - sqlite3_stmt *pList = 0; - int bIndex = 0; - - if( p->rc==SQLITE_OK ){ - memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); - p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - } - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ - const char *zIdx = (const char*)sqlite3_column_text(pList, 1); - sqlite3_stmt *pXInfo = 0; - if( zIdx==0 ) break; - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - if( iCid>=0 ) pIter->abIndexed[iCid] = 1; - } - rbuFinalize(p, pXInfo); - bIndex = 1; - } - - rbuFinalize(p, pList); - if( bIndex==0 ) pIter->abIndexed = 0; -} - - -/* -** If they are not already populated, populate the pIter->azTblCol[], -** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to -** the table (not index) that the iterator currently points to. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. If -** an error does occur, an error code and error message are also left in -** the RBU handle. -*/ -static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ - if( pIter->azTblCol==0 ){ - sqlite3_stmt *pStmt = 0; - int nCol = 0; - int i; /* for() loop iterator variable */ - int bRbuRowid = 0; /* If input table has column "rbu_rowid" */ - int iOrder = 0; - int iTnum = 0; - - /* Figure out the type of table this step will deal with. */ - assert( pIter->eType==0 ); - rbuTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_NOTABLE ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); - } - if( p->rc ) return p->rc; - if( pIter->zIdx==0 ) pIter->iTnum = iTnum; - - assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK - || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID - || pIter->eType==RBU_PK_VTAB - ); - - /* Populate the azTblCol[] and nTblCol variables based on the columns - ** of the input table. Ignore any input table columns that begin with - ** "rbu_". */ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT * FROM '%q'", pIter->zDataTbl) - ); - if( p->rc==SQLITE_OK ){ - nCol = sqlite3_column_count(pStmt); - rbuAllocateIterArrays(p, pIter, nCol); - } - for(i=0; p->rc==SQLITE_OK && irc); - pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol; - pIter->azTblCol[pIter->nTblCol++] = zCopy; - } - else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ - bRbuRowid = 1; - } - } - sqlite3_finalize(pStmt); - pStmt = 0; - - if( p->rc==SQLITE_OK - && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) - ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf( - "table %q %s rbu_rowid column", pIter->zDataTbl, - (bRbuRowid ? "may not have" : "requires") - ); - } - - /* Check that all non-HIDDEN columns in the destination table are also - ** present in the input table. Populate the abTblPk[], azTblType[] and - ** aiTblOrder[] arrays at the same time. */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl) - ); - } - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zName = (const char*)sqlite3_column_text(pStmt, 1); - if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */ - for(i=iOrder; inTblCol; i++){ - if( 0==strcmp(zName, pIter->azTblCol[i]) ) break; - } - if( i==pIter->nTblCol ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("column missing from %q: %s", - pIter->zDataTbl, zName - ); - }else{ - int iPk = sqlite3_column_int(pStmt, 5); - int bNotNull = sqlite3_column_int(pStmt, 3); - const char *zType = (const char*)sqlite3_column_text(pStmt, 2); - - if( i!=iOrder ){ - SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); - SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); - } - - pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); - pIter->abTblPk[iOrder] = (iPk!=0); - pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); - iOrder++; - } - } - - rbuFinalize(p, pStmt); - rbuObjIterCacheIndexedCols(p, pIter); - assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); - } - - return p->rc; -} - -/* -** This function constructs and returns a pointer to a nul-terminated -** string containing some SQL clause or list based on one or more of the -** column names currently stored in the pIter->azTblCol[] array. -*/ -static char *rbuObjIterGetCollist( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter /* Object iterator for column names */ -){ - char *zList = 0; - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - const char *z = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z); - zSep = ", "; - } - return zList; -} - -/* -** This function is used to create a SELECT list (the list of SQL -** expressions that follows a SELECT keyword) for a SELECT statement -** used to read from an data_xxx or rbu_tmp_xxx table while updating the -** index object currently indicated by the iterator object passed as the -** second argument. A "PRAGMA index_xinfo = " statement is used -** to obtain the required information. -** -** If the index is of the following form: -** -** CREATE INDEX i1 ON t1(c, b COLLATE nocase); -** -** and "t1" is a table with an explicit INTEGER PRIMARY KEY column -** "ipk", the returned string is: -** -** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" -** -** As well as the returned string, three other malloc'd strings are -** returned via output parameters. As follows: -** -** pzImposterCols: ... -** pzImposterPk: ... -** pzWhere: ... -*/ -static char *rbuObjIterGetIndexCols( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter, /* Object iterator for column names */ - char **pzImposterCols, /* OUT: Columns for imposter table */ - char **pzImposterPk, /* OUT: Imposter PK clause */ - char **pzWhere, /* OUT: WHERE clause */ - int *pnBind /* OUT: Trbul number of columns */ -){ - int rc = p->rc; /* Error code */ - int rc2; /* sqlite3_finalize() return code */ - char *zRet = 0; /* String to return */ - char *zImpCols = 0; /* String to return via *pzImposterCols */ - char *zImpPK = 0; /* String to return via *pzImposterPK */ - char *zWhere = 0; /* String to return via *pzWhere */ - int nBind = 0; /* Value to return via *pnBind */ - const char *zCom = ""; /* Set to ", " later on */ - const char *zAnd = ""; /* Set to " AND " later on */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = ? */ - - if( rc==SQLITE_OK ){ - assert( p->zErrmsg==0 ); - rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) - ); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol; - const char *zType; - - if( iCid<0 ){ - /* An integer primary key. If the table has an explicit IPK, use - ** its name. Otherwise, use "rbu_rowid". */ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else{ - zCol = "rbu_rowid"; - } - zType = "INTEGER"; - }else{ - zCol = pIter->azTblCol[iCid]; - zType = pIter->azTblType[iCid]; - } - - zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); - if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ - const char *zOrder = (bDesc ? " DESC" : ""); - zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", - zImpPK, zCom, nBind, zCol, zOrder - ); - } - zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", - zImpCols, zCom, nBind, zCol, zType, zCollate - ); - zWhere = sqlite3_mprintf( - "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol - ); - if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM; - zCom = ", "; - zAnd = " AND "; - nBind++; - } - - rc2 = sqlite3_finalize(pXInfo); - if( rc==SQLITE_OK ) rc = rc2; - - if( rc!=SQLITE_OK ){ - sqlite3_free(zRet); - sqlite3_free(zImpCols); - sqlite3_free(zImpPK); - sqlite3_free(zWhere); - zRet = 0; - zImpCols = 0; - zImpPK = 0; - zWhere = 0; - p->rc = rc; - } - - *pzImposterCols = zImpCols; - *pzImposterPk = zImpPK; - *pzWhere = zWhere; - *pnBind = nBind; - return zRet; -} - -/* -** Assuming the current table columns are "a", "b" and "c", and the zObj -** paramter is passed "old", return a string of the form: -** -** "old.a, old.b, old.b" -** -** With the column names escaped. -** -** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append -** the text ", old._rowid_" to the returned value. -*/ -static char *rbuObjIterGetOldlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zObj -){ - char *zList = 0; - if( p->rc==SQLITE_OK && pIter->abIndexed ){ - const char *zS = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abIndexed[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol); - }else{ - zList = sqlite3_mprintf("%z%sNULL", zList, zS); - } - zS = ", "; - if( zList==0 ){ - p->rc = SQLITE_NOMEM; - break; - } - } - - /* For a table with implicit rowids, append "old._rowid_" to the list. */ - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "%z, %s._rowid_", zList, zObj); - } - } - return zList; -} - -/* -** Return an expression that can be used in a WHERE clause to match the -** primary key of the current table. For example, if the table is: -** -** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)); -** -** Return the string: -** -** "b = ?1 AND c = ?2" -*/ -static char *rbuObjIterGetWhere( - sqlite3rbu *p, - RbuObjIter *pIter -){ - char *zList = 0; - if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); - }else if( pIter->eType==RBU_PK_EXTERNAL ){ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); - zSep = " AND "; - } - } - zList = rbuMPrintf(p, - "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList - ); - - }else{ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1); - zSep = " AND "; - } - } - } - return zList; -} - -/* -** The SELECT statement iterating through the keys for the current object -** (p->objiter.pSelect) currently points to a valid row. However, there -** is something wrong with the rbu_control value in the rbu_control value -** stored in the (p->nCol+1)'th column. Set the error code and error message -** of the RBU handle to something reflecting this. -*/ -static void rbuBadControlError(sqlite3rbu *p){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("invalid rbu_control value"); -} - - -/* -** Return a nul-terminated string containing the comma separated list of -** assignments that should be included following the "SET" keyword of -** an UPDATE statement used to update the table object that the iterator -** passed as the second argument currently points to if the rbu_control -** column of the data_xxx table entry is set to zMask. -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetSetlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zMask -){ - char *zList = 0; - if( p->rc==SQLITE_OK ){ - int i; - - if( (int)strlen(zMask)!=pIter->nTblCol ){ - rbuBadControlError(p); - }else{ - const char *zSep = ""; - for(i=0; inTblCol; i++){ - char c = zMask[pIter->aiSrcOrder[i]]; - if( c=='x' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", - zList, zSep, pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='d' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='f' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - } - } - } - return zList; -} - -/* -** Return a nul-terminated string consisting of nByte comma separated -** "?" expressions. For example, if nByte is 3, return a pointer to -** a buffer containing the string "?,?,?". -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ - char *zRet = 0; - int nByte = nBind*2 + 1; - - zRet = (char*)rbuMalloc(p, nByte); - if( zRet ){ - int i; - for(i=0; izIdx==0 ); - if( p->rc==SQLITE_OK ){ - const char *zSep = "PRIMARY KEY("; - sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = */ - - p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){ - const char *zOrig = (const char*)sqlite3_column_text(pXList,3); - if( zOrig && strcmp(zOrig, "pk")==0 ){ - const char *zIdx = (const char*)sqlite3_column_text(pXList,1); - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - break; - } - } - rbuFinalize(p, pXList); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - if( sqlite3_column_int(pXInfo, 5) ){ - /* int iCid = sqlite3_column_int(pXInfo, 0); */ - const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); - const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; - z = rbuMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); - zSep = ", "; - } - } - z = rbuMPrintf(p, "%z)", z); - rbuFinalize(p, pXInfo); - } - return z; -} - -/* -** This function creates the second imposter table used when writing to -** a table b-tree where the table has an external primary key. If the -** iterator passed as the second argument does not currently point to -** a table (not index) with an external primary key, this function is a -** no-op. -** -** Assuming the iterator does point to a table with an external PK, this -** function creates a WITHOUT ROWID imposter table named "rbu_imposter2" -** used to access that PK index. For example, if the target table is -** declared as follows: -** -** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c)); -** -** then the imposter table schema is: -** -** CREATE TABLE rbu_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID; -** -*/ -static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_EXTERNAL ){ - int tnum = pIter->iPkTnum; /* Root page of PK index */ - sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */ - const char *zIdx = 0; /* Name of PK index */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */ - const char *zComma = ""; - char *zCols = 0; /* Used to build up list of table cols */ - char *zPk = 0; /* Used to build up table PK declaration */ - - /* Figure out the name of the primary key index for the current table. - ** This is needed for the argument to "PRAGMA index_xinfo". Set - ** zIdx to point to a nul-terminated string containing this name. */ - p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, - "SELECT name FROM sqlite_master WHERE rootpage = ?" - ); - if( p->rc==SQLITE_OK ){ - sqlite3_bind_int(pQuery, 1, tnum); - if( SQLITE_ROW==sqlite3_step(pQuery) ){ - zIdx = (const char*)sqlite3_column_text(pQuery, 0); - } - } - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - rbuFinalize(p, pQuery); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int bKey = sqlite3_column_int(pXInfo, 5); - if( bKey ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, - iCid, pIter->azTblType[iCid], zCollate - ); - zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); - zComma = ", "; - } - } - zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); - rbuFinalize(p, pXInfo); - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", - zCols, zPk - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** If an error has already occurred when this function is called, it -** immediately returns zero (without doing any work). Or, if an error -** occurs during the execution of this function, it sets the error code -** in the sqlite3rbu object indicated by the first argument and returns -** zero. -** -** The iterator passed as the second argument is guaranteed to point to -** a table (not an index) when this function is called. This function -** attempts to create any imposter table required to write to the main -** table b-tree of the table before returning. Non-zero is returned if -** an imposter table are created, or zero otherwise. -** -** An imposter table is required in all cases except RBU_PK_VTAB. Only -** virtual tables are written to directly. The imposter table has the -** same schema as the actual target table (less any UNIQUE constraints). -** More precisely, the "same schema" means the same columns, types, -** collation sequences. For tables that do not have an external PRIMARY -** KEY, it also means the same PRIMARY KEY declaration. -*/ -static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){ - int tnum = pIter->iTnum; - const char *zComma = ""; - char *zSql = 0; - int iCol; - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - - for(iCol=0; p->rc==SQLITE_OK && iColnTblCol; iCol++){ - const char *zPk = ""; - const char *zCol = pIter->azTblCol[iCol]; - const char *zColl = 0; - - p->rc = sqlite3_table_column_metadata( - p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0 - ); - - if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ - /* If the target table column is an "INTEGER PRIMARY KEY", add - ** "PRIMARY KEY" to the imposter table column declaration. */ - zPk = "PRIMARY KEY "; - } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", - zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, - (pIter->abNotNull[iCol] ? " NOT NULL" : "") - ); - zComma = ", "; - } - - if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ - char *zPk = rbuWithoutRowidPK(p, pIter); - if( zPk ){ - zSql = rbuMPrintf(p, "%z, %z", zSql, zPk); - } - } - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", - pIter->zTbl, zSql, - (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** Prepare a statement used to insert rows into the "rbu_tmp_xxx" table. -** Specifically a statement of the form: -** -** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...); -** -** The number of bound variables is equal to the number of columns in -** the target table, plus one (for the rbu_control column), plus one more -** (for the rbu_rowid column) if the target table is an implicit IPK or -** virtual table. -*/ -static void rbuObjIterPrepareTmpInsert( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zCollist, - const char *zRbuRowid -){ - int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE); - char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid); - if( zBind ){ - assert( pIter->pTmpInsert==0 ); - p->rc = prepareFreeAndCollectError( - p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( - "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", - p->zStateDb, pIter->zDataTbl, zCollist, zRbuRowid, zBind - )); - } -} - -static void rbuTmpInsertFunc( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - sqlite3rbu *p = sqlite3_user_data(pCtx); - int rc = SQLITE_OK; - int i; - - for(i=0; rc==SQLITE_OK && iobjiter.pTmpInsert, i+1, apVal[i]); - } - if( rc==SQLITE_OK ){ - sqlite3_step(p->objiter.pTmpInsert); - rc = sqlite3_reset(p->objiter.pTmpInsert); - } - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - } -} - -/* -** Ensure that the SQLite statement handles required to update the -** target database object currently indicated by the iterator passed -** as the second argument are available. -*/ -static int rbuObjIterPrepareAll( - sqlite3rbu *p, - RbuObjIter *pIter, - int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ -){ - assert( pIter->bCleanup==0 ); - if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ - const int tnum = pIter->iTnum; - char *zCollist = 0; /* List of indexed columns */ - char **pz = &p->zErrmsg; - const char *zIdx = pIter->zIdx; - char *zLimit = 0; - - if( nOffset ){ - zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset); - if( !zLimit ) p->rc = SQLITE_NOMEM; - } - - if( zIdx ){ - const char *zTbl = pIter->zTbl; - char *zImposterCols = 0; /* Columns for imposter table */ - char *zImposterPK = 0; /* Primary key declaration for imposter */ - char *zWhere = 0; /* WHERE clause on PK columns */ - char *zBind = 0; - int nBind = 0; - - assert( pIter->eType!=RBU_PK_VTAB ); - zCollist = rbuObjIterGetIndexCols( - p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind - ); - zBind = rbuObjIterGetBindlist(p, nBind); - - /* Create the imposter table used to write to this index. */ - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE \"rbu_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID", - zTbl, zImposterCols, zImposterPK - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - - /* Create the statement to insert index entries */ - pIter->nCol = nBind; - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pInsert, &p->zErrmsg, - sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) - ); - } - - /* And to delete index entries */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pDelete, &p->zErrmsg, - sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) - ); - } - - /* Create the SELECT statement to read keys in sorted order */ - if( p->rc==SQLITE_OK ){ - char *zSql; - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, - zCollist, zLimit - ); - }else{ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM '%q' " - "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " - "UNION ALL " - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " - "ORDER BY %s%s", - zCollist, pIter->zDataTbl, - zCollist, p->zStateDb, pIter->zDataTbl, - zCollist, zLimit - ); - } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); - } - - sqlite3_free(zImposterCols); - sqlite3_free(zImposterPK); - sqlite3_free(zWhere); - sqlite3_free(zBind); - }else{ - int bRbuRowid = (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE); - const char *zTbl = pIter->zTbl; /* Table this step applies to */ - const char *zWrite; /* Imposter table name */ - - char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); - char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); - - zCollist = rbuObjIterGetCollist(p, pIter); - pIter->nCol = pIter->nTblCol; - - /* Create the imposter table or tables (if required). */ - rbuCreateImposterTable(p, pIter); - rbuCreateImposterTable2(p, pIter); - zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); - - /* Create the INSERT statement to write to the target PK b-tree */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, - sqlite3_mprintf( - "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", - zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings - ) - ); - } - - /* Create the DELETE statement to write to the target PK b-tree */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, - sqlite3_mprintf( - "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere - ) - ); - } - - if( pIter->abIndexed ){ - const char *zRbuRowid = ""; - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zRbuRowid = ", rbu_rowid"; - } - - /* Create the rbu_tmp_xxx table and the triggers to populate it. */ - rbuMPrintfExec(p, p->dbRbu, - "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " - "SELECT *%s FROM '%q' WHERE 0;" - , p->zStateDb, pIter->zDataTbl - , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") - , pIter->zDataTbl - ); - - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(2, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(2, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" - "END;", - zWrite, zTbl, zOldlist, - zWrite, zTbl, zOldlist, - zWrite, zTbl, zNewlist - ); - - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(0, %s);" - "END;", - zWrite, zTbl, zNewlist - ); - } - - rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); - } - - /* Create the SELECT statement to read keys from data_xxx */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, - sqlite3_mprintf( - "SELECT %s, rbu_control%s FROM '%q'%s", - zCollist, (bRbuRowid ? ", rbu_rowid" : ""), - pIter->zDataTbl, zLimit - ) - ); - } - - sqlite3_free(zWhere); - sqlite3_free(zOldlist); - sqlite3_free(zNewlist); - sqlite3_free(zBindings); - } - sqlite3_free(zCollist); - sqlite3_free(zLimit); - } - - return p->rc; -} - -/* -** Set output variable *ppStmt to point to an UPDATE statement that may -** be used to update the imposter table for the main table b-tree of the -** table object that pIter currently points to, assuming that the -** rbu_control column of the data_xyz table contains zMask. -** -** If the zMask string does not specify any columns to update, then this -** is not an error. Output variable *ppStmt is set to NULL in this case. -*/ -static int rbuGetUpdateStmt( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter, /* Object iterator */ - const char *zMask, /* rbu_control value ('x.x.') */ - sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */ -){ - RbuUpdateStmt **pp; - RbuUpdateStmt *pUp = 0; - int nUp = 0; - - /* In case an error occurs */ - *ppStmt = 0; - - /* Search for an existing statement. If one is found, shift it to the front - ** of the LRU queue and return immediately. Otherwise, leave nUp pointing - ** to the number of statements currently in the cache and pUp to the - ** last object in the list. */ - for(pp=&pIter->pRbuUpdate; *pp; pp=&((*pp)->pNext)){ - pUp = *pp; - if( strcmp(pUp->zMask, zMask)==0 ){ - *pp = pUp->pNext; - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - *ppStmt = pUp->pUpdate; - return SQLITE_OK; - } - nUp++; - } - assert( pUp==0 || pUp->pNext==0 ); - - if( nUp>=SQLITE_RBU_UPDATE_CACHESIZE ){ - for(pp=&pIter->pRbuUpdate; *pp!=pUp; pp=&((*pp)->pNext)); - *pp = 0; - sqlite3_finalize(pUp->pUpdate); - pUp->pUpdate = 0; - }else{ - pUp = (RbuUpdateStmt*)rbuMalloc(p, sizeof(RbuUpdateStmt)+pIter->nTblCol+1); - } - - if( pUp ){ - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zSet = rbuObjIterGetSetlist(p, pIter, zMask); - char *zUpdate = 0; - - pUp->zMask = (char*)&pUp[1]; - memcpy(pUp->zMask, zMask, pIter->nTblCol); - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - - if( zSet ){ - const char *zPrefix = ""; - - if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_"; - zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", - zPrefix, pIter->zTbl, zSet, zWhere - ); - p->rc = prepareFreeAndCollectError( - p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate - ); - *ppStmt = pUp->pUpdate; - } - sqlite3_free(zWhere); - sqlite3_free(zSet); - } - - return p->rc; -} - -static sqlite3 *rbuOpenDbhandle(sqlite3rbu *p, const char *zName){ - sqlite3 *db = 0; - if( p->rc==SQLITE_OK ){ - const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; - p->rc = sqlite3_open_v2(zName, &db, flags, p->zVfsName); - if( p->rc ){ - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - sqlite3_close(db); - db = 0; - } - } - return db; -} - -/* -** Open the database handle and attach the RBU database as "rbu". If an -** error occurs, leave an error code and message in the RBU handle. -*/ -static void rbuOpenDatabase(sqlite3rbu *p){ - assert( p->rc==SQLITE_OK ); - assert( p->dbMain==0 && p->dbRbu==0 ); - - p->eStage = 0; - p->dbMain = rbuOpenDbhandle(p, p->zTarget); - p->dbRbu = rbuOpenDbhandle(p, p->zRbu); - - /* If using separate RBU and state databases, attach the state database to - ** the RBU db handle now. */ - if( p->zState ){ - rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); - memcpy(p->zStateDb, "stat", 4); - }else{ - memcpy(p->zStateDb, "main", 4); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbRbu, - "rbu_target_name", 1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); - - /* Mark the database file just opened as an RBU target database. If - ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. - ** This is an error. */ - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - - if( p->rc==SQLITE_NOTFOUND ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("rbu vfs not found"); - } -} - -/* -** This routine is a copy of the sqlite3FileSuffix3() routine from the core. -** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. -** -** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database -** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and -** if filename in z[] has a suffix (a.k.a. "extension") that is longer than -** three characters, then shorten the suffix on z[] to be the last three -** characters of the original suffix. -** -** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always -** do the suffix shortening regardless of URI parameter. -** -** Examples: -** -** test.db-journal => test.nal -** test.db-wal => test.wal -** test.db-shm => test.shm -** test.db-mj7f3319fa => test.9fa -*/ -static void rbuFileSuffix3(const char *zBase, char *z){ -#ifdef SQLITE_ENABLE_8_3_NAMES -#if SQLITE_ENABLE_8_3_NAMES<2 - if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) -#endif - { - int i, sz; - sz = sqlite3Strlen30(z); - for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} - if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); - } -#endif -} - -/* -** Return the current wal-index header checksum for the target database -** as a 64-bit integer. -** -** The checksum is store in the first page of xShmMap memory as an 8-byte -** blob starting at byte offset 40. -*/ -static i64 rbuShmChecksum(sqlite3rbu *p){ - i64 iRet = 0; - if( p->rc==SQLITE_OK ){ - sqlite3_file *pDb = p->pTargetFd->pReal; - u32 volatile *ptr; - p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); - if( p->rc==SQLITE_OK ){ - iRet = ((i64)ptr[10] << 32) + ptr[11]; - } - } - return iRet; -} - -/* -** This function is called as part of initializing or reinitializing an -** incremental checkpoint. -** -** It populates the sqlite3rbu.aFrame[] array with the set of -** (wal frame -> db page) copy operations required to checkpoint the -** current wal file, and obtains the set of shm locks required to safely -** perform the copy operations directly on the file-system. -** -** If argument pState is not NULL, then the incremental checkpoint is -** being resumed. In this case, if the checksum of the wal-index-header -** following recovery is not the same as the checksum saved in the RbuState -** object, then the rbu handle is set to DONE state. This occurs if some -** other client appends a transaction to the wal file in the middle of -** an incremental checkpoint. -*/ -static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){ - - /* If pState is NULL, then the wal file may not have been opened and - ** recovered. Running a read-statement here to ensure that doing so - ** does not interfere with the "capture" process below. */ - if( pState==0 ){ - p->eStage = 0; - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0); - } - } - - /* Assuming no error has occurred, run a "restart" checkpoint with the - ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following - ** special behaviour in the rbu VFS: - ** - ** * If the exclusive shm WRITER or READ0 lock cannot be obtained, - ** the checkpoint fails with SQLITE_BUSY (normally SQLite would - ** proceed with running a passive checkpoint instead of failing). - ** - ** * Attempts to read from the *-wal file or write to the database file - ** do not perform any IO. Instead, the frame/page combinations that - ** would be read/written are recorded in the sqlite3rbu.aFrame[] - ** array. - ** - ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, - ** READ0 and CHECKPOINT locks taken as part of the checkpoint are - ** no-ops. These locks will not be released until the connection - ** is closed. - ** - ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL - ** error. - ** - ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the - ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[] - ** array populated with a set of (frame -> page) mappings. Because the - ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy - ** data from the wal file into the database file according to the - ** contents of aFrame[]. - */ - if( p->rc==SQLITE_OK ){ - int rc2; - p->eStage = RBU_STAGE_CAPTURE; - rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); - if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; - } - - if( p->rc==SQLITE_OK ){ - p->eStage = RBU_STAGE_CKPT; - p->nStep = (pState ? pState->nRow : 0); - p->aBuf = rbuMalloc(p, p->pgsz); - p->iWalCksum = rbuShmChecksum(p); - } - - if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){ - p->rc = SQLITE_DONE; - p->eStage = RBU_STAGE_DONE; - } -} - -/* -** Called when iAmt bytes are read from offset iOff of the wal file while -** the rbu object is in capture mode. Record the frame number of the frame -** being read in the aFrame[] array. -*/ -static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ - const u32 mReq = (1<mLock!=mReq ){ - pRbu->rc = SQLITE_BUSY; - return SQLITE_INTERNAL; - } - - pRbu->pgsz = iAmt; - if( pRbu->nFrame==pRbu->nFrameAlloc ){ - int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; - RbuFrame *aNew; - aNew = (RbuFrame*)sqlite3_realloc(pRbu->aFrame, nNew * sizeof(RbuFrame)); - if( aNew==0 ) return SQLITE_NOMEM; - pRbu->aFrame = aNew; - pRbu->nFrameAlloc = nNew; - } - - iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; - if( pRbu->iMaxFrame