Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest trunk enhancements into the begin-concurrent branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | begin-concurrent |
Files: | files | file ages | folders |
SHA3-256: |
1ae8d60237d24f82392aeb6cc934c3b2 |
User & Date: | drh 2025-06-28 14:16:26.496 |
Context
2025-06-28
| ||
14:16 | Merge the latest trunk enhancements into the begin-concurrent branch. (Leaf check-in: 1ae8d60237 user: drh tags: begin-concurrent) | |
2025-06-27
| ||
19:02 | Raise an error right away if the number of aggregate terms in a query exceeds the maximum number of columns. (check-in: 5508b56fd2 user: drh tags: trunk) | |
2025-05-29
| ||
14:40 | Bring the begin-concurrent branch up to version 3.50.0. (check-in: 436609fdb1 user: drh tags: begin-concurrent) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 218 219 220 221 222 | # it at configure-time instead of calculate it at make-time. # #TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ #TCL_LIB_SPEC = @TCL_LIB_SPEC@ #TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ #TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@ #TCL_VERSION = @TCL_VERSION@ # # $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it # is calculated at make-time by the targets which need it but we # export it here so that it can be set at configure-time, so that # clients are not required to pass it at make-time, or may set it in # their environment to override it. # | > > > > > > > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | # it at configure-time instead of calculate it at make-time. # #TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ #TCL_LIB_SPEC = @TCL_LIB_SPEC@ #TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ #TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@ #TCL_VERSION = @TCL_VERSION@ TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@ # ^^^ main.mk optionally uses this for determining the Tcl extension's # DLL name. TCL_EXT_DLL_BASENAME = @TCL_EXT_DLL_BASENAME@ # ^^^ base name of the Tcl extension DLL. It varies by platform and # Tcl version. # # $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it # is calculated at make-time by the targets which need it but we # export it here so that it can be set at configure-time, so that # clients are not required to pass it at make-time, or may set it in # their environment to override it. # |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1619 1620 1621 1622 1623 1624 1625 | $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ $(TOP)\src\test_tclsh.c \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vdbecov.c \ $(TOP)\src\test_vfs.c \ | < | 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 | $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ $(TOP)\src\test_tclsh.c \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vdbecov.c \ $(TOP)\src\test_vfs.c \ $(TOP)\src\test_window.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c \ $(TOP)\ext\session\test_session.c \ $(TOP)\ext\session\sqlite3changebatch.c |
︙ | ︙ | |||
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 | $(TOP)\ext\misc\sha1.c \ $(TOP)\ext\misc\shathree.c \ $(TOP)\ext\misc\sqlar.c \ $(TOP)\ext\misc\sqlite3_stdio.c \ $(TOP)\ext\misc\sqlite3_stdio.h \ $(TOP)\ext\misc\uint.c \ $(TOP)\ext\misc\vfstrace.c \ $(TOP)\ext\misc\zipfile.c \ $(TOP)\ext\recover\dbdata.c \ $(TOP)\ext\recover\sqlite3recover.c \ | > | < < | 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 | $(TOP)\ext\misc\sha1.c \ $(TOP)\ext\misc\shathree.c \ $(TOP)\ext\misc\sqlar.c \ $(TOP)\ext\misc\sqlite3_stdio.c \ $(TOP)\ext\misc\sqlite3_stdio.h \ $(TOP)\ext\misc\uint.c \ $(TOP)\ext\misc\vfstrace.c \ $(TOP)\ext\misc\windirent.h \ $(TOP)\ext\misc\zipfile.c \ $(TOP)\ext\recover\dbdata.c \ $(TOP)\ext\recover\sqlite3recover.c \ $(TOP)\ext\recover\sqlite3recover.h # If use of zlib is enabled, add the "zipfile.c" source file. # !IF $(USE_ZLIB)!=0 SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\sqlar.c SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\zipfile.c !ENDIF |
︙ | ︙ | |||
2582 2583 2584 2585 2586 2587 2588 | | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH) !ENDIF testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ | | | 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 | | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH) !ENDIF testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ -DBUILD_sqlite -I$(TCLINCDIR) -I$(TOP)\ext\misc \ $(TESTFIXTURE_SRC) \ /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS) # A small helper for manually running individual tests tf.bat: testfixture.exe Makefile.msc echo @set PATH=$(LIBTCLPATH);%PATH% > $@ echo .\testfixture.exe %* >> $@ |
︙ | ︙ | |||
2671 2672 2673 2674 2675 2676 2677 | # are up-to-date. # srctree-check: $(TOP)\tool\srctree-check.tcl $(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl # Testing for a release # | | > > > > > > > | 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | # are up-to-date. # srctree-check: $(TOP)\tool\srctree-check.tcl $(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl # Testing for a release # releasetest: verify-source $(TCLSH_CMD) $(TOP)\test\testrunner.tcl release # xdevtest is like releasetest, except that it skips the # dependency on verify-source so that xdevtest can be run from # a modified source tree. # xdevtest: $(TCLSH_CMD) $(TOP)\test\testrunner.tcl release smoketest: $(TESTPROGS) @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS) |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.51.0 |
Changes to autoconf/Makefile.in.
︙ | ︙ | |||
220 221 222 223 224 225 226 | # # Flags to link the shell app either directly against sqlite3.c # (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0). # ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@ sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3) | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | # # Flags to link the shell app either directly against sqlite3.c # (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0). # ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@ sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3) sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib) $(LDFLAGS.math) sqlite3-shell-deps.1 = $(TOP)/sqlite3.c sqlite3-shell-deps.0 = $(libsqlite3.DLL) # # STATIC_CLI_SHELL = 1 to statically link sqlite3$(T.exe), else # 0. Requires static versions of all requisite libraries. Primarily # intended for use with static-friendly environments like Alpine # Linux. |
︙ | ︙ |
Changes to autoconf/tea/Makefile.in.
︙ | ︙ | |||
142 143 144 145 146 147 148 | # # tx.src is the list of source or object files to include in the # (single) compiler/linker invocation. This will initially contain any # sources passed to [teaish-src-add], but may also be appended to by # teaish.make. # | | > > > > > | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | # # tx.src is the list of source or object files to include in the # (single) compiler/linker invocation. This will initially contain any # sources passed to [teaish-src-add], but may also be appended to by # teaish.make. # tx.src = @TEAISH_EXT_SRC@ # # tx.CFLAGS is typically set by teaish.make, whereas TEAISH_CFLAGS # gets set up via the configure script. # tx.CFLAGS = # # tx.LDFLAGS is typically set by teaish.make, whereas TEAISH_LDFLAGS # gets set up via the configure script. # tx.LDFLAGS = # # The list of 'dist' files may be appended to from teaish.make.in. # It can also be set up from teaish.tcl using [teaish-dist-add] # and/or [teaish-src-add -dist ...]. # tx.dist.files = @TEAISH_DIST_FILES@ # # The base name for a distribution tar/zip file. # tx.dist.basename = $(tx.name.dist)-$(tx.version) # List of deps which may trigger an auto-reconfigure. # teaish__autogen.deps = \ $(tx.makefile.in) $(teaish.makefile.in) \ $(tx.tcl) \ @TEAISH_PKGINDEX_TCL_IN@ @TEAISH_TM_TCL_IN@ \ @AUTODEPS@ |
︙ | ︙ | |||
195 196 197 198 199 200 201 | reconfigure: $(teaish.autoreconfig) $(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \ @AUTODEPS@ @if TEAISH_TESTER_TCL_IN | | | > > > > | > | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | reconfigure: $(teaish.autoreconfig) $(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \ @AUTODEPS@ @if TEAISH_TESTER_TCL_IN @TEAISH_TESTER_TCL_IN@: $(teaish__autogen.deps) config.log: @TEAISH_TESTER_TCL_IN@ @TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@ @endif @if TEAISH_TEST_TCL_IN @TEAISH_TEST_TCL_IN@: $(teaish__autogen.deps) config.log: @TEAISH_TEST_TCL_IN@ @TEAISH_TEST_TCL@: @TEAISH_TEST_TCL_IN@ @endif # # CC variant for compiling Tcl-using sources. # CC.tcl = \ $(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS) # # CC variant for linking $(tx.src) into an extension DLL. Note that # $(tx.src) must come before $(LDFLAGS...) for linking to third-party # libs to work. # CC.dll = \ $(CC.tcl) $(tx.src) $(LDFLAGS.shlib) \ $(tx.LDFLAGS) $(LDFLAGS.configure) $(LDFLAGS) $(TCL_STUB_LIB_SPEC) @if TEAISH_ENABLE_DLL # # The rest of this makefile exists solely to support this brief # target: the extension shared lib. # $(tx.dll): $(tx.src) config.log |
︙ | ︙ | |||
244 245 246 247 248 249 250 | # .PHONY: test-pre test-prepre test-core test test-post test-extension test-extension: # this name is reserved for use by teaish.make[.in] @if TEAISH_ENABLE_DLL test-prepre: $(tx.dll) @endif @if TEAISH_TESTER_TCL | | > > > > > | | > > > > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | # .PHONY: test-pre test-prepre test-core test test-post test-extension test-extension: # this name is reserved for use by teaish.make[.in] @if TEAISH_ENABLE_DLL test-prepre: $(tx.dll) @endif @if TEAISH_TESTER_TCL teaish.tester.tcl = @TEAISH_TESTER_TCL@ test-core.args = $(teaish.tester.tcl) @if TEAISH_ENABLE_DLL test-core.args += '$(tx.dll)' '$(tx.loadPrefix)' @else test-core.args += '' '' @endif test-core.args += @TEAISH_TESTUTIL_TCL@ # Clients may pass additional args via test.args=... # and ::argv will be rewritten before the test script loads, to # remove $(test-core.args) test.args ?= test-core: test-pre $(TCLSH) $(test-core.args) $(test.args) test-gdb: $(teaish.tester.tcl) gdb --args $(TCLSH) $(test-core.args) $(test.args) test-vg.flags ?= --leak-check=full -v --show-reachable=yes --track-origins=yes test-vg: $(teaish.tester.tcl) valgrind $(test-vg.flags) $(TCLSH) $(test-core.args) $(test.args) @else # !TEAISH_TESTER_TCL test-prepre: @endif # TEAISH_TESTER_TCL test-pre: test-prepre test-core: test-pre test-post: test-core test: test-post |
︙ | ︙ | |||
284 285 286 287 288 289 290 | rm -f config.log config.defines.txt @if TEAISH_MAKEFILE_IN @if TEAISH_MAKEFILE rm -f @TEAISH_MAKEFILE@ @endif @endif @if TEAISH_TESTER_TCL_IN | | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | rm -f config.log config.defines.txt @if TEAISH_MAKEFILE_IN @if TEAISH_MAKEFILE rm -f @TEAISH_MAKEFILE@ @endif @endif @if TEAISH_TESTER_TCL_IN rm -f $(teaish.tester.tcl) @endif @if TEAISH_PKGINDEX_TCL_IN rm -f @TEAISH_PKGINDEX_TCL@ @endif @if TEAISH_PKGINIT_TCL_IN rm -f @TEAISH_PKGINIT_TCL@ @endif |
︙ | ︙ | |||
351 352 353 354 355 356 357 358 | @if [ ! -d "$(install-core.tmdir)" ]; then \ set -x; $(INSTALL) -d "$(install-core.tmdir)"; \ fi $(INSTALL.noexec) "@TEAISH_TM_TCL@" "$(install-core.tmdir)/$(tx.tm.tgt)" @endif install-test: install-core @echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \ if echo \ | > > > > | | > | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | @if [ ! -d "$(install-core.tmdir)" ]; then \ set -x; $(INSTALL) -d "$(install-core.tmdir)"; \ fi $(INSTALL.noexec) "@TEAISH_TM_TCL@" "$(install-core.tmdir)/$(tx.tm.tgt)" @endif install-test: install-core @echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \ set xtra=""; \ if [ x != "x$(DESTDIR)" ]; then \ xtra='set ::auto_path [linsert $$::auto_path 0 [file normalize $(DESTDIR)$(TCLLIBDIR)/..]];'; \ fi; \ if echo \ 'set c 0; ' $$xtra \ '@TEAISH_POSTINST_PREREQUIRE@' \ 'if {[catch {package require $(tx.name.pkg) $(tx.version)} xc]} {incr c};' \ 'if {$$c && "" ne $$xc} {puts $$xc; puts "auto_path=$$::auto_path"};' \ 'exit $$c' \ | $(TCLSH) ; then \ echo "passed"; \ else \ echo "FAILED"; \ exit 1; \ fi |
︙ | ︙ | |||
402 403 404 405 406 407 408 | # When installing teaish as part of "make dist", we need to run # configure with similar flags to what we last configured with but we # must not pass on any extension-specific flags, as those won't be # recognized when running in --teaish-install mode, causing # the sub-configure to fail. dist.flags = --with-tclsh=$(TCLSH) | | < | | | | | | | | | | | | | | | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | # When installing teaish as part of "make dist", we need to run # configure with similar flags to what we last configured with but we # must not pass on any extension-specific flags, as those won't be # recognized when running in --teaish-install mode, causing # the sub-configure to fail. dist.flags = --with-tclsh=$(TCLSH) dist.reconfig = $(teaish.dir)/configure $(tx.dist.reconfig-flags) $(dist.flags) # Temp dir for dist.zip. Must be different than dist.tgz or else # parallel builds may hose the dist. teaish__dist.tmp.zip = teaish__dist_zip # # Make a distribution zip file... # dist.zip = $(tx.dist.basename).zip .PHONY: dist.zip dist.zip-core dist.zip-post #dist.zip-pre: # We apparently can't add a pre-hook here, else "make dist" rebuilds # the archive each time it's run. $(dist.zip): $(tx.dist.files) @rm -fr $(teaish__dist.tmp.zip) @mkdir -p $(teaish__dist.tmp.zip)/$(tx.dist.basename) @tar cf $(teaish__dist.tmp.zip)/tmp.tar $(tx.dist.files) @tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(tx.dist.basename) @if TEAISH_DIST_FULL @$(dist.reconfig) \ --teaish-install=$(teaish__dist.tmp.zip)/$(tx.dist.basename) \ --t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null @endif @rm -f $(tx.dist.basename)/tmp.tar $(dist.zip) @cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(tx.dist.basename) @rm -fr $(teaish__dist.tmp.zip) @ls -la $(dist.zip) dist.zip-core: $(dist.zip) dist.zip-post: dist.zip-core dist.zip: dist.zip-post dist: dist.zip undist-zip: rm -f $(dist.zip) undist: undist-zip @endif #BIN_ZIP # # Make a distribution tarball... # teaish__dist.tmp.tgz = teaish__dist_tgz dist.tgz = $(tx.dist.basename).tar.gz .PHONY: dist.tgz dist.tgz-core dist.tgz-post # dist.tgz-pre: # see notes in dist.zip $(dist.tgz): $(tx.dist.files) @rm -fr $(teaish__dist.tmp.tgz) @mkdir -p $(teaish__dist.tmp.tgz)/$(tx.dist.basename) @tar cf $(teaish__dist.tmp.tgz)/tmp.tar $(tx.dist.files) @tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(tx.dist.basename) @if TEAISH_DIST_FULL @rm -f $(teaish__dist.tmp.tgz)/$(tx.dist.basename)/pkgIndex.tcl.in; # kludge @$(dist.reconfig) \ --teaish-install=$(teaish__dist.tmp.tgz)/$(tx.dist.basename) \ --t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null @endif @rm -f $(tx.dist.basename)/tmp.tar $(dist.tgz) @cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(tx.dist.basename) @rm -fr $(teaish__dist.tmp.tgz) @ls -la $(dist.tgz) dist.tgz-core: $(dist.tgz) dist.tgz-post: dist.tgz-core dist.tgz: dist.tgz-post dist: dist.tgz undist-tgz: |
︙ | ︙ |
Changes to autoconf/tea/README.txt.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 | In both of the above, replace $(TCLSH) with the full pathname of of the tclsh that you want the SQLite extension to work with. See step-by-step instructions at the links below for more information: https://sqlite.org/src/doc/trunk/doc/compile-for-unix.md https://sqlite.org/src/doc/trunk/doc/compile-for-windows.md The whole point of the amalgamation-autoconf tarball (in which this | > > > > | | | | | | | | | > | > > > < | > | | < < | | < < < < < < | < < < < < | | | 36 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | In both of the above, replace $(TCLSH) with the full pathname of of the tclsh that you want the SQLite extension to work with. See step-by-step instructions at the links below for more information: https://sqlite.org/src/doc/trunk/doc/compile-for-unix.md https://sqlite.org/src/doc/trunk/doc/compile-for-windows.md And info about the extension's Tcl interface can be found at: https://sqlite.org/tclsqlite.html The whole point of the amalgamation-autoconf tarball (in which this README.txt file is embedded) is to provide a means of compiling SQLite that does not require first installing TCL and/or "tclsh". The canonical Makefile in the SQLite source tree provides more capabilities (such as the the ability to run test cases to ensure that the build worked) and is better maintained. The only downside of the canonical Makefile is that it requires a TCL installation. But if you are wanting to build the TCL extension for SQLite, then presumably you already have a TCL installation. So why not just use the more-capable and better-maintained canoncal Makefile? As of version 3.50.0, this build process uses "teaish": https://fossil.wanderinghorse.net/r/teaish which is conceptually derived from the pre-3.50 toolchain, TEA: http://core.tcl-lang.org/tclconfig http://core.tcl-lang.org/sampleextension It to works for us. It might also work for you. But we cannot promise that. If you want to use this TEA builder and it works for you, that's fine. But if you have trouble, the first thing you should do is go back to using the canonical Makefile in the SQLite source tree. ------------------------------------------------------------------ UNIX BUILD ========== Building under most UNIX systems is easy, just run the configure script and then run make. For example: $ cd sqlite-*-tea $ ./configure --with-tcl=/path/to/tcl/install/root $ make test $ make install WINDOWS BUILD ============= On Windows this build is known to work on Cygwin and some Msys2 environments. We do not currently support Microsoft makefiles for native Windows builds. |
Changes to autoconf/tea/_teaish.tester.tcl.in.
︙ | ︙ | |||
17 18 19 20 21 22 23 | @TEAISH_VSATISFIES_CODE@ @endif if {[llength [lindex $::argv 0]] > 0} { load [file normalize [lindex $::argv 0]] [lindex $::argv 1]; # ----^^^^^^^ needed on Haiku when argv 0 is just a filename, else # load cannot find the file. } | > | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | @TEAISH_VSATISFIES_CODE@ @endif if {[llength [lindex $::argv 0]] > 0} { load [file normalize [lindex $::argv 0]] [lindex $::argv 1]; # ----^^^^^^^ needed on Haiku when argv 0 is just a filename, else # load cannot find the file. } set ::argv [lassign $argv - -] source -encoding utf-8 [lindex $::argv 0]; # teaish/tester.tcl @if TEAISH_PKGINIT_TCL apply {{file} { set dir [file dirname $::argv0] source -encoding utf-8 $file }} [join {@TEAISH_PKGINIT_TCL@}] @endif @if TEAISH_TM_TCL |
︙ | ︙ |
Deleted autoconf/tea/doc/sqlite3.n.
|
| < < < < < < < < < < < < < < < |
Changes to autoconf/tea/teaish.tcl.
︙ | ︙ | |||
60 61 62 63 64 65 66 | } teaish-pkginfo-set -vars { -name sqlite -name.pkg sqlite3 -version $version -name.dist $distname | < > > > > > > > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | } teaish-pkginfo-set -vars { -name sqlite -name.pkg sqlite3 -version $version -name.dist $distname -libDir sqlite$version -pragmas $pragmas -src generic/tclsqlite3.c } # We should also have: # -vsatisfies 8.6- # But at least one platform is failing this vsatisfies check # for no apparent reason: # https://sqlite.org/forum/forumpost/fde857fb8101a4be }} [teaish-get -dir] # # Must return either an empty string or a list in the form accepted by # autosetup's [options] function. # proc teaish-options {} { # These flags and defaults mostly derive from the historical TEA |
︙ | ︙ | |||
115 116 117 118 119 120 121 | # # Gets called by tea-configure-core. Must perform any configuration # work needed for this extension. # proc teaish-configure {} { use teaish/feature | < < | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | # # Gets called by tea-configure-core. Must perform any configuration # work needed for this extension. # proc teaish-configure {} { use teaish/feature if {[proj-opt-was-provided override-sqlite-version]} { teaish-pkginfo-set -version [opt-val override-sqlite-version] proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version] } elseif {[proj-opt-was-provided with-system-sqlite] && [opt-val with-system-sqlite] ne "0"} { proj-fatal "when using --with-system-sqlite also use" \ "--override-sqlite-version to specify a library version number." |
︙ | ︙ |
Changes to autosetup/proj.tcl.
︙ | ︙ | |||
56 57 58 59 60 61 62 | # updating global state via feature tests. # # # $proj__Config is an internal-use-only array for storing whatever generic # internal stuff we need stored. # | | | > > | < < | > > | | | | | < | | < | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # updating global state via feature tests. # # # $proj__Config is an internal-use-only array for storing whatever generic # internal stuff we need stored. # array set ::proj__Config [subst { self-tests [get-env proj.self-tests 0] verbose-assert [get-env proj.assert-verbose 0] isatty [isatty? stdout] }] # # List of dot-in files to filter in the final stages of # configuration. Some configuration steps may append to this. Each # one in this list which exists will trigger the generation of a # file with that same name, minus the ".in", in the build directory # (which differ from the source dir in out-of-tree builds). # # See: proj-dot-ins-append and proj-dot-ins-process # set ::proj__Config(dot-in-files) [list] # # @proj-warn msg # # Emits a warning message to stderr. All args are appended with a # space between each. # proc proj-warn {args} { show-notices puts stderr [join [list "WARNING:" \[ [proj-scope 1] \]: {*}$args] " "] } # # Internal impl of [proj-fatal] and [proj-error]. It must be called # using tailcall. # proc proj__faterr {failMode args} { show-notices set lvl 1 while {"-up" eq [lindex $args 0]} { set args [lassign $args -] incr lvl } if {$failMode} { puts stderr [join [list "FATAL:" \[ [proj-scope $lvl] \]: {*}$args]] exit 1 } else { error [join [list in \[ [proj-scope $lvl] \]: {*}$args]] } } # # @proj-fatal ?-up...? msg... # # Emits an error message to stderr and exits with non-0. All args are # appended with a space between each. # # The calling scope's name is used in the error message. To instead # use the name of a call higher up in the stack, use -up once for each # additional level. # proc proj-fatal {args} { tailcall proj__faterr 1 {*}$args } # # @proj-error ?-up...? msg... # # Works like proj-fatal but uses [error] intead of [exit]. # proc proj-error {args} { tailcall proj__faterr 0 {*}$args } # # @proj-assert script ?message? # # Kind of like a C assert: if uplevel of [list expr $script] is false, # a fatal error is triggered. The error message, by default, includes # the body of the failed assertion, but if $msg is set then that is # used instead. # proc proj-assert {script {msg ""}} { if {1 eq $::proj__Config(verbose-assert)} { msg-result [proj-bold "asserting: $script"] } if {![uplevel 1 [list expr $script]]} { if {"" eq $msg} { set msg $script } tailcall proj__faterr 1 "Assertion failed:" $msg } } # # @proj-bold str # # If this function believes that the current console might support |
︙ | ︙ | |||
881 882 883 884 885 886 887 | # Looks at either the 'host' (==compilation target platform) or # 'build' (==the being-built-on platform) define value and returns if # if that value seems to indicate that it represents a Mac platform, # else returns 0. # proc proj-looks-like-mac {{key host}} { switch -glob -- [get-define $key] { | | > > | 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | # Looks at either the 'host' (==compilation target platform) or # 'build' (==the being-built-on platform) define value and returns if # if that value seems to indicate that it represents a Mac platform, # else returns 0. # proc proj-looks-like-mac {{key host}} { switch -glob -- [get-define $key] { *-*-darwin* { # https://sqlite.org/forum/forumpost/7b218c3c9f207646 # There's at least one Linux out there which matches *apple*. return 1 } default { return 0 } } } |
︙ | ︙ | |||
923 924 925 926 927 928 929 | # and TARGET_DLLEXT to one of (.so, ,dll, .dylib). # # Trivia: for .dylib files, the linker needs the -dynamiclib flag # instead of -shared. # proc proj-dll-extension {} { set inner {{key} { | | < | | < > | | < | < < | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 | # and TARGET_DLLEXT to one of (.so, ,dll, .dylib). # # Trivia: for .dylib files, the linker needs the -dynamiclib flag # instead of -shared. # proc proj-dll-extension {} { set inner {{key} { if {[proj-looks-like-mac $key]} { return ".dylib" } if {[proj-looks-like-windows $key]} { return ".dll" } return ".so" }} define BUILD_DLLEXT [apply $inner build] define TARGET_DLLEXT [apply $inner host] } # # @proj-lib-extension |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | 2 { lappend fileIn {*}$args } default { proj-fatal "Too many arguments: $fileIn $args" } } | | | 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 | 2 { lappend fileIn {*}$args } default { proj-fatal "Too many arguments: $fileIn $args" } } #puts "******* [proj-scope]: adding [llength $fileIn]-length item: $fileIn" lappend ::proj__Config(dot-in-files) $fileIn } # # @proj-dot-ins-list # # Returns the current list of [proj-dot-ins-append]'d files, noting |
︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 | # associated script, if any, it runs the file through # proj-validate-no-unresolved-ats, erroring out if that does. # # -clear: after processing, empty the dot-ins list. This effectively # makes proj-dot-ins-append available for re-use. # proc proj-dot-ins-process {args} { | | > | | 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 | # associated script, if any, it runs the file through # proj-validate-no-unresolved-ats, erroring out if that does. # # -clear: after processing, empty the dot-ins list. This effectively # makes proj-dot-ins-append available for re-use. # proc proj-dot-ins-process {args} { proj-parse-flags args flags { -touch "" {return "-touch"} -clear 0 {expr 1} -validate 0 {expr 1} } #puts "args=$args"; parray flags if {[llength $args] > 0} { error "Invalid argument to [proj-scope]: $args" } foreach f $::proj__Config(dot-in-files) { proj-assert {3==[llength $f]} \ "Expecting proj-dot-ins-list to be stored in 3-entry lists. Got: $f" lassign $f fIn fOut fScript #puts "DOING $fIn ==> $fOut" proj-make-from-dot-in {*}$flags(-touch) $fIn $fOut if {$flags(-validate)} { proj-validate-no-unresolved-ats $fOut } if {"" ne $fScript} { |
︙ | ︙ | |||
1749 1750 1751 1752 1753 1754 1755 | # proc proj-validate-no-unresolved-ats {args} { foreach f $args { set lnno 1 set isMake [string match {*[Mm]ake*} $f] foreach line [proj-file-content-list $f] { if {!$isMake || ![string match "#*" [string trimleft $line]]} { | | | 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | # proc proj-validate-no-unresolved-ats {args} { foreach f $args { set lnno 1 set isMake [string match {*[Mm]ake*} $f] foreach line [proj-file-content-list $f] { if {!$isMake || ![string match "#*" [string trimleft $line]]} { if {[regexp {(@[A-Za-z0-9_\.]+@)} $line match]} { error "Unresolved reference to $match at line $lnno of $f" } } incr lnno } } } |
︙ | ︙ | |||
1889 1890 1891 1892 1893 1894 1895 | # # By default it returns the result as string of all -D... flags, # but if passed the -list flag it will return a list of the # individual CFLAGS. # proc proj-define-to-cflag {args} { set rv {} | | | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 | # # By default it returns the result as string of all -D... flags, # but if passed the -list flag it will return a list of the # individual CFLAGS. # proc proj-define-to-cflag {args} { set rv {} proj-parse-flags args flags { -list 0 {expr 1} -quote 0 {expr 1} -zero-undef 0 {expr 1} } foreach d $args { set v [get-define $d ""] set li {} |
︙ | ︙ | |||
1997 1998 1999 2000 2001 2002 2003 | # @proj-cache-set ?-key KEY? ?-level 0? value # # Sets a feature-check cache entry with the given key. # # See proj-cache-key for -key's and -level's semantics, noting that # this function adds one to -level for purposes of that call. proc proj-cache-set {args} { | | | 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 | # @proj-cache-set ?-key KEY? ?-level 0? value # # Sets a feature-check cache entry with the given key. # # See proj-cache-key for -key's and -level's semantics, noting that # this function adds one to -level for purposes of that call. proc proj-cache-set {args} { proj-parse-flags args flags { -key => 0 -level => 0 } lassign $args val set key [proj-cache-key $flags(-key) [expr {1 + $flags(-level)}]] #puts "** fcheck set $key = $val" set ::proj__Cache($key) $val |
︙ | ︙ | |||
2033 2034 2035 2036 2037 2038 2039 | # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-key for $key's and $addLevel's semantics, noting that # this function adds one to $addLevel for purposes of that call. proc proj-cache-check {args} { | | | 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 | # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-key for $key's and $addLevel's semantics, noting that # this function adds one to $addLevel for purposes of that call. proc proj-cache-check {args} { proj-parse-flags args flags { -key => 0 -level => 0 } lassign $args tgtVar upvar $tgtVar tgt set rc 0 set key [proj-cache-key $flags(-key) [expr {1 + $flags(-level)}]] |
︙ | ︙ | |||
2066 2067 2068 2069 2070 2071 2072 | return $arg } } return "" } # | | | > > > | > > | | > | > > > > > | > > > > > > > > > > > > > > > > > | < | | > | | | < | | | | > > > > > > > > > > | > > > > > > > | | | > | | | < < < | > | | > | | | | | > | | | > > > > | < | | | | | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > | > > > > > | | | > > > > > > > | > > > | | | | | | | < | > > > > > > > | | > | > > > > > > > > | < > | | | > | > | > | > > > > > | > | > > > > > > > > | > > > > > > | > > > > > > > > > > > > | > > > > > > > > > > > > > | 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 | return $arg } } return "" } # # @proj-parse-flags argvListName targetArrayName {prototype} # # A helper to parse flags from proc argument lists. # # The first argument is the name of a var holding the args to # parse. It will be overwritten, possibly with a smaller list. # # The second argument is the name of an array variable to create in # the caller's scope. # # The third argument, $prototype, is a description of how to handle # the flags. Each entry in that list must be in one of the # following forms: # # -flag defaultValue ?-literal|-call|-apply? # script|number|incr|proc-name|{apply $aLambda} # # -flag* ...as above... # # -flag => defaultValue ?-call proc-name-and-args|-apply lambdaExpr? # # -flag* => ...as above... # # :PRAGMA # # The first two forms represents a basic flag with no associated # following argument. The third and fourth forms, called arg-consuming # flags, extract the value from the following argument in $argvName # (pneumonic: => points to the next argument.). The :PRAGMA form # offers a way to configure certain aspects of this call. # # If $argv contains any given flag from $prototype, its default value # is overridden depending on several factors: # # - If the -literal flag is used, or the flag's script is a number, # value is used verbatim. # # - Else if the -call flag is used, the argument must be a proc name # and any leading arguments, e.g. {apply $myLambda}. The proc is passed # the (flag, value) as arguments (non-consuming flags will get # passed the flag's current/starting value and consuming flags will # get the next argument). Its result becomes the result of the # flag. # # - Else if -apply X is used, it's effectively shorthand for -call # {apply X}. Its argument may either be a $lambaRef or a {{f v} # {body}} construct. # # - Else if $script is one of the following values, it is treated as # the result of... # # - incr: increments the current value of the flag. # # - Else $script is eval'd to get its result value. That result # becomes the new flag value for $tgtArrayName(-flag). This # function intercepts [return $val] from eval'ing $script. Any # empty script will result in the flag having "" assigned to it. # # Unless the -flag has a trailing asterisk, e.g. -flag*, this function # assumes that each flag is unique, and using a flag more than once # causes an error to be triggered. the -flag* forms works similarly # except that may appear in $argv any number of times: # # - For non-arg-consuming flags, each invocation of -flag causes the # result of $script to overwrite the previous value. e.g. so # {-flag* {x} {incr foo}} has a default value of x, but passing in # -flag twice would change it to the result of incrementing foo # twice. This form can be used to implement, e.g., increasing # verbosity levels by passing -verbose multiple times. # # - For arg-consuming flags, the given flag starts with value X, but # if the flag is provided in $argv, the default is cleared, then # each instance of -flag causes its value to be appended to the # result, so {-flag* => {a b c}} defaults to {a b c}, but passing # in -flag y -flag z would change it to {y z}, not {a b c y z}.. # # By default, the args list is only inspected until the first argument # which is not described by $prototype. i.e. the first "non-flag" (not # counting values consumed for flags defined like -flag => default). # The :all-flags pragma (see below) can modify this behavior. # # If a "--" flag is encountered, no more arguments are inspected as # flags unless the :all-flags pragma (see below) is in effect. The # first instance of "--" is removed from the target result list but # all remaining instances of "--" are are passed through. # # Any argvName entries not described in $prototype are considered to # be "non-flags" for purposes of this function, even if they # ostensibly look like flags. # # Returns the number of flags it processed in $argvName, not counting # "--". # # Example: # ## set args [list -foo -bar {blah} -z 8 9 10 -theEnd] ## proj-parse-flags args flags { ## -foo 0 {expr 1} ## -bar => 0 ## -no-baz 1 {return 0} ## -z 0 2 ## } # # After that $flags would contain {-foo 1 -bar {blah} -no-baz 1 -z 2} # and $args would be {8 9 10 -theEnd}. # # Pragmas: # # Passing :PRAGMAS to this function may modify how it works. The # following pragmas are supported (note the leading ":"): # # :all-flags indicates that the whole input list should be scanned, # not stopping at the first non-flag or "--". # proc proj-parse-flags {argvName tgtArrayName prototype} { upvar $argvName argv upvar $tgtArrayName outFlags array set flags {}; # staging area array set blob {}; # holds markers for various per-key state and options set incrSkip 1; # 1 if we stop at the first non-flag, else 0 # Parse $prototype for flag definitions... set n [llength $prototype] set checkProtoFlag { #puts "**** checkProtoFlag #$i of $n k=$k fv=$fv" switch -exact -- $fv { -literal { proj-assert {![info exists blob(${k}.consumes)]} set blob(${k}.script) [list expr [lindex $prototype [incr i]]] } -apply { set fv [lindex $prototype [incr i]] if {2 == [llength $fv]} { # Treat this as a lambda literal set fv [list $fv] } lappend blob(${k}.call) "apply $fv" } -call { # arg is either a proc name or {apply $aLambda} set fv [lindex $prototype [incr i]] lappend blob(${k}.call) $fv } default { proj-assert {![info exists blob(${k}.consumes)]} set blob(${k}.script) $fv } } if {$i >= $n} { proj-error -up "[proj-scope]: Missing argument for $k flag" } } for {set i 0} {$i < $n} {incr i} { set k [lindex $prototype $i] #puts "**** #$i of $n k=$k" # Check for :PRAGMA... switch -exact -- $k { :all-flags { set incrSkip 0 continue } } proj-assert {[string match -* $k]} \ "Invalid argument: $k" if {[string match {*\*} $k]} { # Re-map -foo* to -foo and flag -foo as a repeatable flag set k [string map {* ""} $k] incr blob(${k}.multi) } if {[info exists flags($k)]} { proj-error -up "[proj-scope]: Duplicated prototype for flag $k" } switch -exact -- [lindex $prototype [expr {$i + 1}]] { => { # -flag => DFLT ?-subflag arg? incr i 2 if {$i >= $n} { proj-error -up "[proj-scope]: Missing argument for $k => flag" } incr blob(${k}.consumes) set vi [lindex $prototype $i] if {$vi in {-apply -call}} { proj-error -up "[proj-scope]: Missing default value for $k flag" } else { set fv [lindex $prototype [expr {$i + 1}]] if {$fv in {-apply -call}} { incr i eval $checkProtoFlag } } } default { # -flag VALUE ?flag? SCRIPT set vi [lindex $prototype [incr i]] set fv [lindex $prototype [incr i]] eval $checkProtoFlag } } #puts "**** #$i of $n k=$k vi=$vi" set flags($k) $vi } #puts "-- flags"; parray flags #puts "-- blob"; parray blob set rc 0 set rv {}; # staging area for the target argv value set skipMode 0 set n [llength $argv] # Now look for those flags in $argv... for {set i 0} {$i < $n} {incr i} { set arg [lindex $argv $i] #puts "-- [proj-scope] arg=$arg" if {$skipMode} { lappend rv $arg } elseif {"--" eq $arg} { # "--" is the conventional way to end processing of args if {[incr blob(--)] > 1} { # Elide only the first one lappend rv $arg } incr skipMode $incrSkip } elseif {[info exists flags($arg)]} { # A known flag... set isMulti [info exists blob(${arg}.multi)] incr blob(${arg}.seen) if {1 < $blob(${arg}.seen) && !$isMulti} { proj-error -up [proj-scope] "$arg flag was used multiple times" } set vMode 0; # 0=as-is, 1=eval, 2=call set isConsuming [info exists blob(${arg}.consumes)] if {$isConsuming} { incr i if {$i >= $n} { proj-error -up [proj-scope] "is missing argument for $arg flag" } set vv [lindex $argv $i] } elseif {[info exists blob(${arg}.script)]} { set vMode 1 set vv $blob(${arg}.script) } else { set vv $flags($arg) } if {[info exists blob(${arg}.call)]} { set vMode 2 set vv [concat {*}$blob(${arg}.call) $arg $vv] } elseif {$isConsuming} { proj-assert {!$vMode} # fall through } elseif {"" eq $vv || [string is double -strict $vv]} { set vMode 0 } elseif {$vv in {incr}} { set vMode 0 switch -exact $vv { incr { set xx $flags($k); incr xx; set vv $xx; unset xx } default { proj-error "Unhandled \$vv value $vv" } } } else { set vv [list eval $vv] set vMode 1 } if {$vMode} { set code [catch [list uplevel 1 $vv] vv xopt] if {$code ni {0 2}} { return {*}$xopt $vv } } if {$isConsuming && $isMulti} { if {1 == $blob(${arg}.seen)} { # On the first hit, overwrite the default with a new list. set flags($arg) [list $vv] } else { # On subsequent hits, append to the list. lappend flags($arg) $vv } } else { set flags($arg) $vv } incr rc } else { # Non-flag incr skipMode $incrSkip lappend rv $arg } } set argv $rv array set outFlags [array get flags] #puts "-- rv=$rv argv=$argv flags="; parray flags return $rc }; # proj-parse-flags # # Older (deprecated) name of proj-parse-flags. # proc proj-parse-simple-flags {args} { tailcall proj-parse-flags {*}$args } if {$::proj__Config(self-tests)} { set __ova $::proj__Config(verbose-assert); set ::proj__Config(verbose-assert) 1 puts "Running [info script] self-tests..." # proj-cache... apply {{} { #proj-warn "Test code for proj-cache" proj-assert {![proj-cache-check -key here check]} proj-assert {"here" eq [proj-cache-key here]} proj-assert {"" eq $check} proj-cache-set -key here thevalue proj-assert {[proj-cache-check -key here check]} |
︙ | ︙ | |||
2229 2230 2231 2232 2233 2234 2235 | #parray ::proj__Cache; proj-assert {"" ne [proj-cache-remove]} proj-assert {![proj-cache-check check]} proj-assert {"" eq [proj-cache-remove]} proj-assert {"" eq $check} }} | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 | #parray ::proj__Cache; proj-assert {"" ne [proj-cache-remove]} proj-assert {![proj-cache-check check]} proj-assert {"" eq [proj-cache-remove]} proj-assert {"" eq $check} }} # proj-parse-flags ... apply {{} { set foo 3 set argv {-a "hi - world" -b -b -b -- -a {bye bye} -- -d -D c -a "" --} proj-parse-flags argv flags { :all-flags -a* => "gets overwritten" -b* 7 {incr foo} -d 1 0 -D 0 1 } #puts "-- argv = $argv"; parray flags; proj-assert {"-- c --" eq $argv} proj-assert {$flags(-a) eq "{hi - world} {bye bye} {}"} proj-assert {$foo == 6} proj-assert {$flags(-b) eq $foo} proj-assert {$flags(-d) == 0} proj-assert {$flags(-D) == 1} set foo 0 foreach x $flags(-a) { proj-assert {$x in {{hi - world} {bye bye} {}}} incr foo } proj-assert {3 == $foo} set argv {-a {hi world} -b -maybe -- -a {bye bye} -- -b c --} set foo 0 proj-parse-flags argv flags { -a => "aaa" -b 0 {incr foo} -maybe no -literal yes } #parray flags; puts "--- argv = $argv" proj-assert {"-a {bye bye} -- -b c --" eq $argv} proj-assert {$flags(-a) eq "hi world"} proj-assert {1 == $flags(-b)} proj-assert {"yes" eq $flags(-maybe)} set argv {-f -g -a aaa -M -M -M -L -H -A AAA a b c} set foo 0 set myLambda {{flag val} { proj-assert {$flag in {-f -g -M}} #puts "myLambda flag=$flag val=$val" incr val }} proc myNonLambda {flag val} { proj-assert {$flag in {-A -a}} #puts "myNonLambda flag=$flag val=$val" concat $val $val } proj-parse-flags argv flags { -f 0 -call {apply $myLambda} -g 2 -apply $myLambda -h 3 -apply $myLambda -H 30 33 -a => aAAAa -apply {{f v} { set v }} -A => AaaaA -call myNonLambda -B => 17 -call myNonLambda -M* 0 -apply $myLambda -L "" -literal $myLambda } rename myNonLambda "" #puts "--- argv = $argv"; parray flags proj-assert {$flags(-f) == 1} proj-assert {$flags(-g) == 3} proj-assert {$flags(-h) == 3} proj-assert {$flags(-H) == 33} proj-assert {$flags(-a) == {aaa}} proj-assert {$flags(-A) eq "AAA AAA"} proj-assert {$flags(-B) == 17} proj-assert {$flags(-M) == 3} proj-assert {$flags(-L) eq $myLambda} set argv {-touch -validate} proj-parse-flags argv flags { -touch "" {return "-touch"} -validate 0 1 } #puts "----- argv = $argv"; parray flags proj-assert {$flags(-touch) eq "-touch"} proj-assert {$flags(-validate) == 1} proj-assert {$argv eq {}} set argv {-i -i -i} proj-parse-flags argv flags { -i* 0 incr } proj-assert {3 == $flags(-i)} }} set ::proj__Config(verbose-assert) $__ova unset __ova puts "Done running [info script] self-tests." }; # proj- API self-tests |
Changes to autosetup/sqlite-config.tcl.
︙ | ︙ | |||
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | rtree => {Enable the RTREE extension} session => {Enable the SESSION extension} all=$::sqliteConfig(all-flag-default) => {$allFlagHelp} largefile=1 => {This legacy flag has no effect on the library but may influence the generated sqlite_cfg.h by adding #define HAVE_LFS} } } # Options for TCL support tcl { {canonical} { tcl=1 => {Disable components which require TCL, including all tests. This tree requires TCL for code generation but can use the in-tree copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the test code require a canonical tclsh.} | > > > > > < < | > | < < | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | rtree => {Enable the RTREE extension} session => {Enable the SESSION extension} all=$::sqliteConfig(all-flag-default) => {$allFlagHelp} largefile=1 => {This legacy flag has no effect on the library but may influence the generated sqlite_cfg.h by adding #define HAVE_LFS} } {canonical} { column-metadata => {Enable the column metadata APIs} # ^^^ Affects how sqlite3.c is generated, so is not available in # the autoconf build. } } # Options for TCL support tcl { {canonical} { tcl=1 => {Disable components which require TCL, including all tests. This tree requires TCL for code generation but can use the in-tree copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the test code require a canonical tclsh.} with-tcl:DIR => {Directory containing tclConfig.sh or a directory one level up from that, from which we can derive a directory containing tclConfig.sh. A dir name of "prefix" is equivalent to the directory specified by the --prefix flag.} with-tclsh:PATH => {Full pathname of tclsh to use. It is used for (A) trying to find tclConfig.sh and (B) all TCL-based code generation. Use --with-tcl unless you have a specific need for this flag. Warning: if its containing dir has multiple tclsh versions, it may select the wrong tclConfig.sh!} static-tclsqlite3=0 => {Statically-link tclsqlite3. This only works if TCL support is enabled and all requisite libraries are available in static form. Note that glibc is unable to fully statically link certain libraries required by tclsqlite3, so this won't work on most Linux environments.} } |
︙ | ︙ | |||
330 331 332 333 334 335 336 | # --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704 # Note that this has a different meaning from --static-cli-shell in the # canonical build! static-shell=1 => {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c} } {canonical autoconf} { | < | > | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | # --disable-static-shell: https://sqlite.org/forum/forumpost/cc219ee704 # Note that this has a different meaning from --static-cli-shell in the # canonical build! static-shell=1 => {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c} } {canonical autoconf} { rpath=1 => {Disable use of the rpath linker flag} # soname: https://sqlite.org/src/forumpost/5a3b44f510df8ded soname:=legacy => {SONAME for libsqlite3.so. "none", or not using this flag, sets no soname. "legacy" sets it to its historical value of libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets it to that literal value. Any other value is assumed to be a suffix which gets applied to "libsqlite3.so.", |
︙ | ︙ | |||
768 769 770 771 772 773 774 | if {[opt-bool memsys5]} { proj-warn "not enabling memsys3 because memsys5 is enabled." expr 0 } else { sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3 } } | | > | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | if {[opt-bool memsys5]} { proj-warn "not enabling memsys3 because memsys5 is enabled." expr 0 } else { sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3 } } scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {} column-metadata -DSQLITE_ENABLE_COLUMN_METADATA {} }] { if {$boolFlag ni $::autosetup(options)} { # Skip flags which are in the canonical build but not # the autoconf bundle. continue } proj-if-opt-truthy $boolFlag { |
︙ | ︙ | |||
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 | # 2024-10-28: calculation of TCLLIBDIR is now done via the shell # in main.mk (search it for T.tcl.env.sh) so that # static/hand-written makefiles which import main.mk do not have # to define that before importing main.mk. Even so, we export # TCLLIBDIR from here, which will cause the canonical makefile to # use this one rather than to re-calculate it at make-time. set tcllibdir [get-env TCLLIBDIR ""] if {"" eq $tcllibdir} { # Attempt to extract TCLLIBDIR from TCL's $auto_path if {"" ne $with_tclsh && [catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} { foreach i $result { if {[file isdir $i]} { | > | | 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 | # 2024-10-28: calculation of TCLLIBDIR is now done via the shell # in main.mk (search it for T.tcl.env.sh) so that # static/hand-written makefiles which import main.mk do not have # to define that before importing main.mk. Even so, we export # TCLLIBDIR from here, which will cause the canonical makefile to # use this one rather than to re-calculate it at make-time. set tcllibdir [get-env TCLLIBDIR ""] set sq3Ver [get-define PACKAGE_VERSION] if {"" eq $tcllibdir} { # Attempt to extract TCLLIBDIR from TCL's $auto_path if {"" ne $with_tclsh && [catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} { foreach i $result { if {[file isdir $i]} { set tcllibdir $i/sqlite${sq3Ver} break } } } else { proj-warn "Cannot determine TCLLIBDIR." # The makefile will fail fatally in this case if a target is # invoked which requires TCLLIBDIR. |
︙ | ︙ | |||
2107 2108 2109 2110 2111 2112 2113 | }; # sqlite-determine-codegen-tcl ######################################################################## # Runs sqlite-check-tcl and, if this is the canonical build, # sqlite-determine-codegen-tcl. proc sqlite-handle-tcl {} { sqlite-check-tcl | | | | > > > > > > > > > > > > > > > > > < > | | | | | < > | 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 | }; # sqlite-determine-codegen-tcl ######################################################################## # Runs sqlite-check-tcl and, if this is the canonical build, # sqlite-determine-codegen-tcl. proc sqlite-handle-tcl {} { sqlite-check-tcl if {"canonical" ne $::sqliteConfig(build-mode)} return msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]" # Determine the base name of the Tcl extension's DLL # if {[get-define HAVE_TCL]} { if {[string match *-cygwin [get-define host]]} { set libname cyg } else { set libname lib } if {[get-define TCL_MAJOR_VERSION] > 8} { append libname tcl9 } append libname sqlite } else { set libname "" } define TCL_EXT_DLL_BASENAME $libname # The extension is added in the makefile } ######################################################################## # Handle the --enable/disable-rpath flag. proc sqlite-handle-rpath {} { # autosetup/cc-shared.tcl sets the rpath flag definition in # [get-define SH_LINKRPATH], but it does so on a per-platform basis # rather than as a compiler check. Though we should do a proper # compiler check (as proj-check-rpath does), we may want to consider # adopting its approach of clearing the rpath flags for environments # for which sqlite-env-is-unix-on-windows returns a non-empty # string. # https://sqlite.org/forum/forumpost/13cac3b56516f849 if {[proj-opt-truthy rpath]} { proj-check-rpath } else { msg-result "Disabling use of rpath." define LDFLAGS_RPATH "" } } ######################################################################## # If the --dump-defines configure flag is provided then emit a list of # all [define] values to config.defines.txt, else do nothing. proc sqlite-dump-defines {} { proj-if-opt-truthy dump-defines { |
︙ | ︙ |
Changes to ext/fts3/fts3Int.h.
︙ | ︙ | |||
209 210 211 212 213 214 215 | #define deliberate_fall_through /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #define deliberate_fall_through /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof # define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif |
︙ | ︙ |
Changes to ext/fts5/fts5Int.h.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include "fts5.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <string.h> #include <assert.h> #ifndef SQLITE_AMALGAMATION typedef unsigned char u8; typedef unsigned int u32; typedef unsigned short u16; typedef short i16; | > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include "fts5.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <string.h> #include <assert.h> #include <stddef.h> #ifndef SQLITE_AMALGAMATION typedef unsigned char u8; typedef unsigned int u32; typedef unsigned short u16; typedef short i16; |
︙ | ︙ | |||
75 76 77 78 79 80 81 | # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof # define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 | /* Variables populated based on current entry. */ Fts5Buffer term; /* Current term */ i64 iRowid; /* Current rowid */ int nPos; /* Number of bytes in current position list */ u8 bDel; /* True if the delete flag is set */ }; /* ** Array of tombstone pages. Reference counted. */ struct Fts5TombstoneArray { int nRef; /* Number of pointers to this object */ int nTombstone; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | /* Variables populated based on current entry. */ Fts5Buffer term; /* Current term */ i64 iRowid; /* Current rowid */ int nPos; /* Number of bytes in current position list */ u8 bDel; /* True if the delete flag is set */ }; static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){ pIdx->rc = FTS5_CORRUPT; sqlite3Fts5ConfigErrmsg(pIdx->pConfig, "fts5: corruption found reading blob %lld from table \"%s\"", iRowid, pIdx->pConfig->zName ); return SQLITE_CORRUPT_VTAB; } #define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid) static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){ pIdx->rc = FTS5_CORRUPT; sqlite3Fts5ConfigErrmsg(pIdx->pConfig, "fts5: corruption on page %d, segment %d, table \"%s\"", pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName ); return SQLITE_CORRUPT_VTAB; } #define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter) static int fts5IndexCorruptIdx(Fts5Index *pIdx){ pIdx->rc = FTS5_CORRUPT; sqlite3Fts5ConfigErrmsg(pIdx->pConfig, "fts5: corruption in table \"%s\"", pIdx->pConfig->zName ); return SQLITE_CORRUPT_VTAB; } #define FTS5_CORRUPT_IDX(pIdx) fts5IndexCorruptIdx(pIdx) /* ** Array of tombstone pages. Reference counted. */ struct Fts5TombstoneArray { int nRef; /* Number of pointers to this object */ int nTombstone; |
︙ | ︙ | |||
839 840 841 842 843 844 845 | } /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead. ** All the reasons those functions might return SQLITE_ERROR - missing ** table, missing row, non-blob/text in block column - indicate ** backing store corruption. */ | | | 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | } /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead. ** All the reasons those functions might return SQLITE_ERROR - missing ** table, missing row, non-blob/text in block column - indicate ** backing store corruption. */ if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT_ROWID(p, iRowid); if( rc==SQLITE_OK ){ u8 *aOut = 0; /* Read blob data into this buffer */ int nByte = sqlite3_blob_bytes(p->pReader); int szData = (sizeof(Fts5Data) + 7) & ~7; sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING; pRet = (Fts5Data*)sqlite3_malloc64(nAlloc); |
︙ | ︙ | |||
889 890 891 892 893 894 895 | sqlite3_free(pData); } static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ | | | 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 | sqlite3_free(pData); } static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ FTS5_CORRUPT_ROWID(p, iRowid); fts5DataRelease(pRet); pRet = 0; } } return pRet; } |
︙ | ︙ | |||
1248 1249 1250 1251 1252 1253 1254 | Fts5Data *pData; pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); if( p->rc==SQLITE_OK ){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); | > | | > > > > > | 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | Fts5Data *pData; pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); if( p->rc==SQLITE_OK ){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); if( p->rc==SQLITE_OK ){ if( (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); } }else if( p->rc==SQLITE_CORRUPT_VTAB ){ sqlite3Fts5ConfigErrmsg(p->pConfig, "fts5: corrupt structure record for table \"%s\"", p->pConfig->zName ); } fts5DataRelease(pData); if( p->rc!=SQLITE_OK ){ fts5StructureRelease(pRet); pRet = 0; } } |
︙ | ︙ | |||
1872 1873 1874 1875 1876 1877 1878 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); while( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ | | | 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); while( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ if( p->rc==SQLITE_OK ) FTS5_CORRUPT_ITER(p, pIter); return; } iOff = 4; a = pIter->pLeaf->p; } iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; |
︙ | ︙ | |||
1904 1905 1906 1907 1908 1909 1910 | static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; /* Offset to read at */ int nNew; /* Bytes of new data */ iOff += fts5GetVarint32(&a[iOff], nNew); if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){ | | | 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 | static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; /* Offset to read at */ int nNew; /* Bytes of new data */ iOff += fts5GetVarint32(&a[iOff], nNew); if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){ FTS5_CORRUPT_ITER(p, pIter); return; } pIter->term.n = nKeep; fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); assert( pIter->term.n<=pIter->term.nSpace ); iOff += nNew; pIter->iTermLeafOffset = iOff; |
︙ | ︙ | |||
2099 2100 2101 2102 2103 2104 2105 | pIter->iLeafOffset = pIter->iTermLeafOffset; } }else{ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ if( iRowidOff>=pNew->szLeaf ){ | | | 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 | pIter->iLeafOffset = pIter->iTermLeafOffset; } }else{ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ if( iRowidOff>=pNew->szLeaf ){ FTS5_CORRUPT_ITER(p, pIter); }else{ pIter->pLeaf = pNew; pIter->iLeafOffset = iRowidOff; } } } |
︙ | ︙ | |||
2333 2334 2335 2336 2337 2338 2339 | ); pIter->iLeafOffset = iOff; pIter->iEndofDoclist = iOff; bNewTerm = 1; } assert_nc( iOff<pLeaf->szLeaf ); if( iOff>pLeaf->szLeaf ){ | | | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 | ); pIter->iLeafOffset = iOff; pIter->iEndofDoclist = iOff; bNewTerm = 1; } assert_nc( iOff<pLeaf->szLeaf ); if( iOff>pLeaf->szLeaf ){ FTS5_CORRUPT_ITER(p, pIter); return; } } } /* Check if the iterator is now at EOF. If so, return early. */ if( pIter->pLeaf ){ |
︙ | ︙ | |||
2443 2444 2445 2446 2447 2448 2449 | if( pLast ){ int iOff; fts5DataRelease(pIter->pLeaf); pIter->pLeaf = pLast; pIter->iLeafPgno = pgnoLast; iOff = fts5LeafFirstRowidOff(pLast); if( iOff>pLast->szLeaf ){ | | | 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 | if( pLast ){ int iOff; fts5DataRelease(pIter->pLeaf); pIter->pLeaf = pLast; pIter->iLeafPgno = pgnoLast; iOff = fts5LeafFirstRowidOff(pLast); if( iOff>pLast->szLeaf ){ FTS5_CORRUPT_ITER(p, pIter); return; } iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; if( fts5LeafIsTermless(pLast) ){ pIter->iEndofDoclist = pLast->nn+1; |
︙ | ︙ | |||
2522 2523 2524 2525 2526 2527 2528 | assert( p->rc==SQLITE_OK ); iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ | | | 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 | assert( p->rc==SQLITE_OK ); iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ FTS5_CORRUPT_ITER(p, pIter); return; } while( 1 ){ /* Figure out how many new bytes are in this term */ fts5FastGetVarint32(a, iOff, nNew); |
︙ | ︙ | |||
2565 2566 2567 2568 2569 2570 2571 | } iPgidx += fts5GetVarint32(&a[iPgidx], nKeep); iTermOff += nKeep; iOff = iTermOff; if( iOff>=n ){ | | | 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 | } iPgidx += fts5GetVarint32(&a[iPgidx], nKeep); iTermOff += nKeep; iOff = iTermOff; if( iOff>=n ){ FTS5_CORRUPT_ITER(p, pIter); return; } /* Read the nKeep field of the next term. */ fts5FastGetVarint32(a, iOff, nKeep); } |
︙ | ︙ | |||
2587 2588 2589 2590 2591 2592 2593 | fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ) return; a = pIter->pLeaf->p; if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){ | | | | 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ) return; a = pIter->pLeaf->p; if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){ FTS5_CORRUPT_ITER(p, pIter); return; }else{ nKeep = 0; iTermOff = iOff; n = (u32)pIter->pLeaf->nn; iOff += fts5GetVarint32(&a[iOff], nNew); break; } } }while( 1 ); } search_success: if( (i64)iOff+nNew>n || nNew<1 ){ FTS5_CORRUPT_ITER(p, pIter); return; } pIter->iLeafOffset = iOff + nNew; pIter->iTermLeafOffset = pIter->iLeafOffset; pIter->iTermLeafPgno = pIter->iLeafPgno; fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm); |
︙ | ︙ | |||
3067 3068 3069 3070 3071 3072 3073 | Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ int iLeafPgno ){ assert( iLeafPgno>pIter->iLeafPgno ); if( iLeafPgno>pIter->pSeg->pgnoLast ){ | | | | 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 | Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ int iLeafPgno ){ assert( iLeafPgno>pIter->iLeafPgno ); if( iLeafPgno>pIter->pSeg->pgnoLast ){ FTS5_CORRUPT_IDX(p); }else{ fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; pIter->iLeafPgno = iLeafPgno-1; while( p->rc==SQLITE_OK ){ int iOff; fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ) break; iOff = fts5LeafFirstRowidOff(pIter->pLeaf); if( iOff>0 ){ u8 *a = pIter->pLeaf->p; int n = pIter->pLeaf->szLeaf; if( iOff<4 || iOff>=n ){ FTS5_CORRUPT_IDX(p); }else{ iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; fts5SegIterLoadNPos(p, pIter); } break; } |
︙ | ︙ | |||
3561 3562 3563 3564 3565 3566 3567 | while( 1 ){ xChunk(p, pCtx, pChunk, nChunk); nRem -= nChunk; fts5DataRelease(pData); if( nRem<=0 ){ break; }else if( pSeg->pSeg==0 ){ | | | 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 | while( 1 ){ xChunk(p, pCtx, pChunk, nChunk); nRem -= nChunk; fts5DataRelease(pData); if( nRem<=0 ){ break; }else if( pSeg->pSeg==0 ){ FTS5_CORRUPT_IDX(p); return; }else{ pgno++; pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); if( pData==0 ) break; pChunk = &pData->p[4]; nChunk = MIN(nRem, pData->szLeaf - 4); |
︙ | ︙ | |||
4664 4665 4666 4667 4668 4669 4670 | pData = fts5LeafRead(p, iLeafRowid); if( pData ){ if( iOff>pData->szLeaf ){ /* This can occur if the pages that the segments occupy overlap - if ** a single page has been assigned to more than one segment. In ** this case a prior iteration of this loop may have corrupted the ** segment currently being trimmed. */ | | | 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 | pData = fts5LeafRead(p, iLeafRowid); if( pData ){ if( iOff>pData->szLeaf ){ /* This can occur if the pages that the segments occupy overlap - if ** a single page has been assigned to more than one segment. In ** this case a prior iteration of this loop may have corrupted the ** segment currently being trimmed. */ FTS5_CORRUPT_ROWID(p, iLeafRowid); }else{ fts5BufferZero(&buf); fts5BufferGrow(&p->rc, &buf, pData->nn); fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); fts5BufferAppendBlob(&p->rc, &buf,pData->szLeaf-iOff,&pData->p[iOff]); |
︙ | ︙ | |||
5131 5132 5133 5134 5135 5136 5137 | assert_nc( bDetailNone==0 || pLeaf->nn==4 ); if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty)); fts5DataRelease(pLeaf); pLeaf = 0; }else if( bDetailNone ){ break; }else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){ | | | | 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 | assert_nc( bDetailNone==0 || pLeaf->nn==4 ); if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty)); fts5DataRelease(pLeaf); pLeaf = 0; }else if( bDetailNone ){ break; }else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){ FTS5_CORRUPT_ROWID(p, iRowid); break; }else{ int nShift = iNext - 4; int nPg; int nIdx = 0; u8 *aIdx = 0; /* Unless the current page footer is 0 bytes in size (in which case ** the new page footer will be as well), allocate and populate a ** buffer containing the new page footer. Set stack variables aIdx ** and nIdx accordingly. */ if( pLeaf->nn>pLeaf->szLeaf ){ int iFirst = 0; int i1 = pLeaf->szLeaf; int i2 = 0; i1 += fts5GetVarint32(&aPg[i1], iFirst); if( iFirst<iNext ){ FTS5_CORRUPT_ROWID(p, iRowid); break; } aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2); if( aIdx==0 ) break; i2 = sqlite3Fts5PutVarint(aIdx, iFirst-nShift); if( i1<pLeaf->nn ){ memcpy(&aIdx[i2], &aPg[i1], pLeaf->nn-i1); |
︙ | ︙ | |||
5374 5375 5376 5377 5378 5379 5380 | } iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix); nPrefix = MIN(nPrefix, nPrefix2); nSuffix = (nPrefix2 + nSuffix2) - nPrefix; if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ | | | | 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 | } iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix); nPrefix = MIN(nPrefix, nPrefix2); nSuffix = (nPrefix2 + nSuffix2) - nPrefix; if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ FTS5_CORRUPT_IDX(p); }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); if( nPrefix2>pSeg->term.n ){ FTS5_CORRUPT_IDX(p); }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); iOff += (nPrefix2-nPrefix); } memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2); iOff += nSuffix2; iNextOff += nSuffix2; |
︙ | ︙ | |||
6174 6175 6176 6177 6178 6179 6180 | nTmp += pSave->iter.nPoslist + 10; nMerge++; fts5PrefixMergerInsertByPosition(&pHead, pSave); pSave = pNext; } if( pHead==0 || pHead->pNext==0 ){ | | | 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 | nTmp += pSave->iter.nPoslist + 10; nMerge++; fts5PrefixMergerInsertByPosition(&pHead, pSave); pSave = pNext; } if( pHead==0 || pHead->pNext==0 ){ FTS5_CORRUPT_IDX(p); break; } /* See the earlier comment in this function for an explanation of why ** corrupt input position lists might cause the output to consume ** at most nMerge*10 bytes of unexpected space. */ if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){ |
︙ | ︙ | |||
6211 6212 6213 6214 6215 6216 6217 | } nTail = pHead->iter.nPoslist - pHead->iOff; /* WRITEPOSLISTSIZE */ assert_nc( tmp.n+nTail<=nTmp ); assert( tmp.n+nTail<=nTmp+nMerge*10 ); if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){ | | | 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 | } nTail = pHead->iter.nPoslist - pHead->iOff; /* WRITEPOSLISTSIZE */ assert_nc( tmp.n+nTail<=nTmp ); assert( tmp.n+nTail<=nTmp+nMerge*10 ); if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){ if( p->rc==SQLITE_OK ) FTS5_CORRUPT_IDX(p); break; } fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2); fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); if( nTail>0 ){ fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail); } |
︙ | ︙ | |||
8340 8341 8342 8343 8344 8345 8346 | int i; /* Now check that the iter.nEmpty leaves following the current leaf ** (a) exist and (b) contain no terms. */ for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){ Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); if( pLeaf ){ | | | > > > | | | | | | 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 | int i; /* Now check that the iter.nEmpty leaves following the current leaf ** (a) exist and (b) contain no terms. */ for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){ Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); if( pLeaf ){ if( !fts5LeafIsTermless(pLeaf) || (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf)) ){ FTS5_CORRUPT_ROWID(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); } } fts5DataRelease(pLeaf); } } static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ i64 iTermOff = 0; int ii; Fts5Buffer buf1 = {0,0,0}; Fts5Buffer buf2 = {0,0,0}; ii = pLeaf->szLeaf; while( ii<pLeaf->nn && p->rc==SQLITE_OK ){ int res; i64 iOff; int nIncr; ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); iTermOff += nIncr; iOff = iTermOff; if( iOff>=pLeaf->szLeaf ){ FTS5_CORRUPT_ROWID(p, iRowid); }else if( iTermOff==nIncr ){ int nByte; iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( (iOff+nByte)>pLeaf->szLeaf ){ FTS5_CORRUPT_ROWID(p, iRowid); }else{ fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); } }else{ int nKeep, nByte; iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep); iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){ FTS5_CORRUPT_ROWID(p, iRowid); }else{ buf1.n = nKeep; fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); } if( p->rc==SQLITE_OK ){ res = fts5BufferCompare(&buf1, &buf2); if( res<=0 ) FTS5_CORRUPT_ROWID(p, iRowid); } } fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p); } fts5BufferFree(&buf1); fts5BufferFree(&buf2); |
︙ | ︙ | |||
8448 8449 8450 8451 8452 8453 8454 | && pLeaf->nn==pLeaf->szLeaf && pLeaf->nn==4 ){ /* special case - the very first page in a segment keeps its %_idx ** entry even if all the terms are removed from it by secure-delete ** operations. */ }else{ | | | | | | 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 | && pLeaf->nn==pLeaf->szLeaf && pLeaf->nn==4 ){ /* special case - the very first page in a segment keeps its %_idx ** entry even if all the terms are removed from it by secure-delete ** operations. */ }else{ FTS5_CORRUPT_ROWID(p, iRow); } }else{ int iOff; /* Offset of first term on leaf */ int iRowidOff; /* Offset of first rowid on leaf */ int nTerm; /* Size of term on leaf in bytes */ int res; /* Comparison of term and split-key */ iOff = fts5LeafFirstTermOff(pLeaf); iRowidOff = fts5LeafFirstRowidOff(pLeaf); if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){ FTS5_CORRUPT_ROWID(p, iRow); }else{ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); if( res==0 ) res = nTerm - nIdxTerm; if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow); } fts5IntegrityCheckPgidx(p, iRow, pLeaf); } fts5DataRelease(pLeaf); if( p->rc ) break; /* Now check that the iter.nEmpty leaves following the current leaf ** (a) exist and (b) contain no terms. */ fts5IndexIntegrityCheckEmpty( |
︙ | ︙ | |||
8498 8499 8500 8501 8502 8503 8504 | ){ /* Check any rowid-less pages that occur before the current leaf. */ for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){ iKey = FTS5_SEGMENT_ROWID(iSegid, iPg); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ | | | | | 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 | ){ /* Check any rowid-less pages that occur before the current leaf. */ for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){ iKey = FTS5_SEGMENT_ROWID(iSegid, iPg); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey); fts5DataRelease(pLeaf); } } iPrevLeaf = fts5DlidxIterPgno(pDlidx); /* Check that the leaf page indicated by the iterator really does ** contain the rowid suggested by the same. */ iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ i64 iRowid; int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ FTS5_CORRUPT_ROWID(p, iKey); }else if( bSecureDelete==0 || iRowidOff>0 ){ i64 iDlRowid = fts5DlidxIterRowid(pDlidx); fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){ FTS5_CORRUPT_ROWID(p, iKey); } } fts5DataRelease(pLeaf); } } iDlidxPrevLeaf = iPg; |
︙ | ︙ | |||
8633 8634 8635 8636 8637 8638 8639 | cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n); } } } fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); fts5MultiIterFree(pIter); | | > > > > > | 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 | cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n); } } } fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); fts5MultiIterFree(pIter); if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){ p->rc = FTS5_CORRUPT; sqlite3Fts5ConfigErrmsg(p->pConfig, "fts5: checksum mismatch for table \"%s\"", p->pConfig->zName ); } fts5StructureRelease(pStruct); #ifdef SQLITE_DEBUG fts5BufferFree(&term); #endif fts5BufferFree(&poslist); return fts5IndexReturn(p); |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
3697 3698 3699 3700 3701 3702 3703 | zSchema, zTabname); rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM; }else{ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" " FTS5 table %s.%s: %s", zSchema, zTabname, sqlite3_errstr(rc)); } | | > | | 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 | zSchema, zTabname); rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM; }else{ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" " FTS5 table %s.%s: %s", zSchema, zTabname, sqlite3_errstr(rc)); } }else if( (rc&0xff)==SQLITE_CORRUPT ){ rc = SQLITE_OK; } sqlite3Fts5IndexCloseReader(pTab->p.pIndex); pTab->p.pConfig->pzErrmsg = 0; return rc; } static int fts5Init(sqlite3 *db){ |
︙ | ︙ |
Changes to ext/fts5/fts5_storage.c.
︙ | ︙ | |||
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | } ctx.pStorage = p; ctx.iCol = -1; for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){ if( pConfig->abUnindexed[iCol-1]==0 ){ sqlite3_value *pVal = 0; const char *pText = 0; int nText = 0; const char *pLoc = 0; int nLoc = 0; assert( pSeek==0 || apVal==0 ); assert( pSeek!=0 || apVal!=0 ); if( pSeek ){ pVal = sqlite3_column_value(pSeek, iCol); }else{ pVal = apVal[iCol-1]; } if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); }else{ | > > > > > > > > > > > | | | | | > > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | } ctx.pStorage = p; ctx.iCol = -1; for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){ if( pConfig->abUnindexed[iCol-1]==0 ){ sqlite3_value *pVal = 0; sqlite3_value *pFree = 0; const char *pText = 0; int nText = 0; const char *pLoc = 0; int nLoc = 0; assert( pSeek==0 || apVal==0 ); assert( pSeek!=0 || apVal!=0 ); if( pSeek ){ pVal = sqlite3_column_value(pSeek, iCol); }else{ pVal = apVal[iCol-1]; } if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){ rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc); }else{ if( sqlite3_value_type(pVal)!=SQLITE_TEXT ){ /* Make a copy of the value to work with. This is because the call ** to sqlite3_value_text() below forces the type of the value to ** SQLITE_TEXT, and we may need to use it again later. */ pFree = pVal = sqlite3_value_dup(pVal); if( pVal==0 ){ rc = SQLITE_NOMEM; } } if( rc==SQLITE_OK ){ pText = (const char*)sqlite3_value_text(pVal); nText = sqlite3_value_bytes(pVal); if( pConfig->bLocale && pSeek ){ pLoc = (const char*)sqlite3_column_text(pSeek, iCol+pConfig->nCol); nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol); } } } if( rc==SQLITE_OK ){ sqlite3Fts5SetLocale(pConfig, pLoc, nLoc); ctx.szCol = 0; rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx, fts5StorageInsertCallback ); p->aTotalSize[iCol-1] -= (i64)ctx.szCol; if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){ rc = FTS5_CORRUPT; } sqlite3Fts5ClearLocale(pConfig); } sqlite3_value_free(pFree); } } if( rc==SQLITE_OK && p->nTotalRow<1 ){ rc = FTS5_CORRUPT; }else{ p->nTotalRow--; } |
︙ | ︙ |
Changes to ext/fts5/test/fts5aa.test.
︙ | ︙ | |||
424 425 426 427 428 429 430 | } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 15.1 { UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; } do_catchsql_test 15.2 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | } sqlite3_db_config db DEFENSIVE 0 do_execsql_test 15.1 { UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; } do_catchsql_test 15.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {fts5: checksum mismatch for table "t1"}} #------------------------------------------------------------------------- # do_execsql_test 16.1 { CREATE VIRTUAL TABLE n1 USING fts5(a); INSERT INTO n1 VALUES('a b c d'); } |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt.test.
︙ | ︙ | |||
43 44 45 46 47 48 49 | sqlite3_db_config db DEFENSIVE 0 do_test 1.3 { execsql { DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } | | < | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | sqlite3_db_config db DEFENSIVE 0 do_test 1.3 { execsql { DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {fts5: corruption found reading blob 137438953476 from table "t1"}} do_execsql_test 1.3b { PRAGMA integrity_check(t1); } {{fts5: corruption found reading blob 137438953476 from table "t1"}} do_test 1.4 { db_restore_and_reopen sqlite3_db_config db DEFENSIVE 0 execsql { UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE rowid = fts5_rowid('segment', $segid, 4); } catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } } {1 {fts5: corruption found reading blob 137438953476 from table "t1"}} db_restore_and_reopen #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r} #-------------------------------------------------------------------- # |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt2.test.
︙ | ︙ | |||
105 106 107 108 109 110 111 | do_execsql_test 2.$i.1 { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE rowid=$lrowid; } do_catchsql_test 2.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | do_execsql_test 2.$i.1 { BEGIN; UPDATE t1_data SET block = substr(block, 1, $i) WHERE rowid=$lrowid; } do_catchsql_test 2.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/1.*fts5: corruption.*/} do_test 2.$i.3 { set res [catchsql {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'}] expr { [string match {*fts5: corruption*} $res] || $res=="0 {$all}" } } 1 do_execsql_test 2.$i.4 { ROLLBACK; INSERT INTO t1(t1) VALUES('integrity-check'); |
︙ | ︙ | |||
156 157 158 159 160 161 162 | fconfigure $fd -translation binary set existing [read $fd [string length $hdr]] seek $fd 0 puts -nonewline $fd $hdr close $fd set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}] | | | | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | fconfigure $fd -translation binary set existing [read $fd [string length $hdr]] seek $fd 0 puts -nonewline $fd $hdr close $fd set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}] if {[string match {*fts5: corruption*} $res]} {incr nCorrupt} set {} 1 } {1} if {($tn2 % 10)==0 && $existing != $hdr} { do_test 3.$tn.$tn2.2 { catchsql { INSERT INTO x3(x3) VALUES('integrity-check') } } {/.*fts5: corruption.*/} do_execsql_test 3.$tn.$tn2.3 { PRAGMA integrity_check(x3); } {/.*fts5: corruption.*/} } execsql ROLLBACK } do_test 3.$tn.x { expr $nCorrupt>0 } 1 } |
︙ | ︙ | |||
205 206 207 208 209 210 211 | UPDATE x4_data SET block = substr(block, 1, length(block)-$nCut) WHERE id = $rowid; } set res [catchsql { SELECT rowid FROM x4 WHERE x4 MATCH 'a' ORDER BY 1 DESC }] | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | UPDATE x4_data SET block = substr(block, 1, length(block)-$nCut) WHERE id = $rowid; } set res [catchsql { SELECT rowid FROM x4 WHERE x4 MATCH 'a' ORDER BY 1 DESC }] if {[string match {*fts5: corruption*} $res]} {incr nCorrupt} set {} 1 } {1} execsql ROLLBACK } # do_test 4.$tn.x { expr $nCorrupt>0 } 1 |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt3.test.
︙ | ︙ | |||
98 99 100 101 102 103 104 | incr i do_test $tn.$i { db eval BEGIN db eval {DELETE FROM t1_data WHERE rowid = $::rowid} list [ catch { db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'} } msg ] $msg | | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | incr i do_test $tn.$i { db eval BEGIN db eval {DELETE FROM t1_data WHERE rowid = $::rowid} list [ catch { db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'} } msg ] $msg } {/.*fts5: corruption.*/} catch { db eval ROLLBACK } } } do_3_test 3.2 do_execsql_test 3.3 { |
︙ | ︙ | |||
269 270 271 272 273 274 275 | do_execsql_test 6.1.1 { UPDATE t1_data SET block = X'000000180630626262626201020201056161616161010203040A' WHERE rowid>100; } do_catchsql_test 6.1.2 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | | | | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | do_execsql_test 6.1.1 { UPDATE t1_data SET block = X'000000180630626262626201020201056161616161010203040A' WHERE rowid>100; } do_catchsql_test 6.1.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} #------- reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.2.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); INSERT INTO t1 VALUES('aa bb cc dd ee'); SELECT pgno, quote(term) FROM t1_idx; } {2 X'' 4 X'3064'} do_execsql_test 6.2.1 { UPDATE t1_idx SET term = X'3065' WHERE pgno=4; } do_catchsql_test 6.2.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} #------- reset_db sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.3.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('abc abcdef abcdefghi'); SELECT quote(block) FROM t1_data WHERE id>100; } {X'0000001C043061626301020204036465660102030703676869010204040808'} do_execsql_test 6.3.1 { BEGIN; UPDATE t1_data SET block = X'0000001C043061626301020204036465660102035003676869010204040808' ------------------------------------------^^--------------------- WHERE id>100; } do_catchsql_test 6.3.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} do_execsql_test 6.3.3 { ROLLBACK; BEGIN; UPDATE t1_data SET block = X'0000001C043061626301020204036465660102030750676869010204040808' --------------------------------------------^^------------------- WHERE id>100; } do_catchsql_test 6.3.3 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} do_execsql_test 6.3.4 { ROLLBACK; BEGIN; UPDATE t1_data SET block = X'0000001C043061626301020204036465660102030707676869010204040850' --------------------------------------------------------------^^- WHERE id>100; } do_catchsql_test 6.3.5 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} do_execsql_test 6.3.6 { ROLLBACK; BEGIN; UPDATE t1_data SET block = X'0000001C503061626301020204036465660102030707676869010204040808' ----------^^----------------------------------------------------- WHERE id>100; } do_catchsql_test 6.3.5 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corruption.*/} #------------------------------------------------------------------------ # reset_db proc rnddoc {n} { set map [list a b c d] |
︙ | ︙ | |||
370 371 372 373 374 375 376 | sqlite3_db_config db DEFENSIVE 0 do_test 7.1 { foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { db eval BEGIN db eval {DELETE FROM t5_data WHERE rowid = $i} set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ] | | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | sqlite3_db_config db DEFENSIVE 0 do_test 7.1 { foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { db eval BEGIN db eval {DELETE FROM t5_data WHERE rowid = $i} set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ] if {![string match {*fts5: corruption*} $r]} { error $r } db eval ROLLBACK } } {} #------------------------------------------------------------------------ # Corruption within the structure record. # |
︙ | ︙ | |||
395 396 397 398 399 400 401 | append blob "06" ;# write counter append blob "0002" ;# first level has 0 segments merging, 2 other. append blob "450108" ;# first segment execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" } {} do_catchsql_test 9.1.2 { SELECT * FROM t1('one AND two'); | | | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | append blob "06" ;# write counter append blob "0002" ;# first level has 0 segments merging, 2 other. append blob "450108" ;# first segment execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" } {} do_catchsql_test 9.1.2 { SELECT * FROM t1('one AND two'); } {/.*fts5: corrupt.*/} do_test 9.2.1 { set blob "12345678" ;# cookie append blob "0205" ;# 2 levels, total of 5 segments append blob "06" ;# write counter append blob "0001" ;# first level has 0 segments merging, 1 other. append blob "450108" ;# first segment execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" } {} do_catchsql_test 9.2.2 { SELECT * FROM t1('one AND two'); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 10.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 32768 pagesize 4096 filename c9.db |
︙ | ︙ | |||
493 494 495 496 497 498 499 | | 32: 65 6e 74 29 0d 00 00 00 03 0f bd 00 0f e8 0f ef ent)............ | 48: 0f bd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | end c9.db }] } {} do_catchsql_test 10.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; | | | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | | 32: 65 6e 74 29 0d 00 00 00 03 0f bd 00 0f e8 0f ef ent)............ | 48: 0f bd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | end c9.db }] } {} do_catchsql_test 10.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- # reset_db do_test 11.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
674 675 676 677 678 679 680 | | 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e1 0f d6 00 00 ................ | 4048: 00 00 00 00 00 00 09 03 02 1b 72 65 62 75 69 6c ..........rebuil | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c2.db }]} {} | | | | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 | | 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e1 0f d6 00 00 ................ | 4048: 00 00 00 00 00 00 09 03 02 1b 72 65 62 75 69 6c ..........rebuil | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c2.db }]} {} do_catchsql_test 12.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; } {/.*fts5: corrupt.*/} do_catchsql_test 12.2 { INSERT INTO t1(t1, rank) VALUES('merge', 500); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- # reset_db do_test 13.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
866 867 868 869 870 871 872 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c14b.db }]} {} do_catchsql_test 14.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c14b.db }]} {} do_catchsql_test 14.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} #--------------------------------------------------------------------------- # reset_db do_test 15.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c17.db }]} {} do_catchsql_test 16.1 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c17.db }]} {} do_catchsql_test 16.1 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 17.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename c18.db |
︙ | ︙ | |||
1122 1123 1124 1125 1126 1127 1128 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c18.db }]} {} do_catchsql_test 17.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; | | | 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c18.db }]} {} do_catchsql_test 17.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 18.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename c19b.db |
︙ | ︙ | |||
1431 1432 1433 1434 1435 1436 1437 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c19b.db }]} {} do_catchsql_test 18.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c19b.db }]} {} do_catchsql_test 18.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 19.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename c20b.db |
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 86 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 .eck....optimize | end c20b.db }]} {} do_catchsql_test 19.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 86 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 .eck....optimize | end c20b.db }]} {} do_catchsql_test 19.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 20.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename crash-cf347c523f793c.db |
︙ | ︙ | |||
1626 1627 1628 1629 1630 1631 1632 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-cf347c523f793c.db }]} {} do_catchsql_test 20.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; | | | 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-cf347c523f793c.db }]} {} do_catchsql_test 20.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 21.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename c22b.db |
︙ | ︙ | |||
1760 1761 1762 1763 1764 1765 1766 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c22b.db }]} {} do_catchsql_test 21.1 { DELETE FROM t1 WHERE t1 MATCH 'ab*ndon'; | | | 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c22b.db }]} {} do_catchsql_test 21.1 { DELETE FROM t1 WHERE t1 MATCH 'ab*ndon'; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- # reset_db do_test 22.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
2096 2097 2098 2099 2100 2101 2102 | | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c22b.db }]} {} do_catchsql_test 22.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 | | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c22b.db }]} {} do_catchsql_test 22.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 23.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 28672 pagesize 4096 filename c24b.db |
︙ | ︙ | |||
2207 2208 2209 2210 2211 2212 2213 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c24b.db }]} {} do_catchsql_test 23.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end c24b.db }]} {} do_catchsql_test 23.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 24.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 32768 pagesize 4096 filename crash-b87dfef02880fe.db |
︙ | ︙ | |||
2425 2426 2427 2428 2429 2430 2431 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end crash-b87dfef02880fe.db }]} {} do_catchsql_test 24.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thread*'; | | | 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end crash-b87dfef02880fe.db }]} {} do_catchsql_test 24.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thread*'; } {/.*fts5: corrupt.*/} do_catchsql_test 24.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #-------------------------------------------------------------------------- reset_db |
︙ | ︙ | |||
2514 2515 2516 2517 2518 2519 2520 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-e3b1b19e4d4bcc.db }]} {} do_catchsql_test 25.1 { INSERT INTO t1(t1) VALUES('rebuild'); | | | 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-e3b1b19e4d4bcc.db }]} {} do_catchsql_test 25.1 { INSERT INTO t1(t1) VALUES('rebuild'); } {/.*fts5: corrupt.*/} do_execsql_test 25.2 { PRAGMA page_size=512; } #-------------------------------------------------------------------------- reset_db |
︙ | ︙ | |||
3007 3008 3009 3010 3011 3012 3013 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end timeout-2ca5b0658c98.db }]} {} do_catchsql_test 27.1 { DELETE FROM t1 WHERE a MATCH 'fts*'; | | | 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 uild....optimize | end timeout-2ca5b0658c98.db }]} {} do_catchsql_test 27.1 { DELETE FROM t1 WHERE a MATCH 'fts*'; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 28.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 40960 pagesize 4096 filename crash-e2d47e0624a42c.db |
︙ | ︙ | |||
3696 3697 3698 3699 3700 3701 3702 | }]} {} do_catchsql_test 32.1 { SELECT snippet(t1, -1, '.', '..', '[', ']'), highlight(t1, 2, '[', ']') FROM t1('g + h') WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank; | | | 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 | }]} {} do_catchsql_test 32.1 { SELECT snippet(t1, -1, '.', '..', '[', ']'), highlight(t1, 2, '[', ']') FROM t1('g + h') WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank; } {/.*fts5: corrupt.*/} do_catchsql_test 32.2 { SELECT * FROM t3; } {1 {database disk image is malformed}} do_catchsql_test 32.3 { SELECT * FROM t4; |
︙ | ︙ | |||
5347 5348 5349 5350 5351 5352 5353 | INSERT INTO t1_data VALUES(274877906945,X'00000183023030250601011d010331c2ba250601010d0101342506010121010135250601011e02036ec2ba250601012b0101382506010112010161250a0101021a1d02016f2506010111010162250601013201026377250601012f010166250801011f0c010167250601012701026863250601010f02026473250601013002016b2506010133020175250601010e010169250601012c0204386ec2be250601012001016a250601010401056bc2b2cebc250601010901016c25060101150203cebc71250601011301036dd18a250601010c01016f25060101260102706425060101240101712506010122010173250a010116040d02016f2506010134010175250801011b14020161250601010b010376c2aa25060101100202d7ac250601010601017725060101030201752506010114010179250a0101190e050202357a250601010701017a250601012e0102c2aa250801011c100201b3250601010a0202ba6225060101310203be656625060101080103c5a77425060101050102de8e250601011704080a08080a080a080809090809090808080b080c080a0a0809080a0809080a0908080a09080a08090a0a'); INSERT INTO t1_idx VALUES(1,X'',2); INSERT INTO t1_idx VALUES(2,X'',2); } do_catchsql_test 41.1 { INSERT INTO t1(t1) VALUES('optimize'); | | | 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 | INSERT INTO t1_data VALUES(274877906945,X'00000183023030250601011d010331c2ba250601010d0101342506010121010135250601011e02036ec2ba250601012b0101382506010112010161250a0101021a1d02016f2506010111010162250601013201026377250601012f010166250801011f0c010167250601012701026863250601010f02026473250601013002016b2506010133020175250601010e010169250601012c0204386ec2be250601012001016a250601010401056bc2b2cebc250601010901016c25060101150203cebc71250601011301036dd18a250601010c01016f25060101260102706425060101240101712506010122010173250a010116040d02016f2506010134010175250801011b14020161250601010b010376c2aa25060101100202d7ac250601010601017725060101030201752506010114010179250a0101190e050202357a250601010701017a250601012e0102c2aa250801011c100201b3250601010a0202ba6225060101310203be656625060101080103c5a77425060101050102de8e250601011704080a08080a080a080809090809090808080b080c080a0a0809080a0809080a0908080a09080a08090a0a'); INSERT INTO t1_idx VALUES(1,X'',2); INSERT INTO t1_idx VALUES(2,X'',2); } do_catchsql_test 41.1 { INSERT INTO t1(t1) VALUES('optimize'); } {/.*fts5: corrupt.*/} do_catchsql_test 41.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {database disk image is malformed}} #------------------------------------------------------------------------- reset_db |
︙ | ︙ | |||
5569 5570 5571 5572 5573 5574 5575 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 5d 69 7a 65 uild....opti]ize | end 8cfba7fbb67e48de92c6.db }]} {} do_catchsql_test 42.1 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb | 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 5d 69 7a 65 uild....opti]ize | end 8cfba7fbb67e48de92c6.db }]} {} do_catchsql_test 42.1 { INSERT INTO t1(t1) VALUES('integrity-check'); } {1 {fts5: checksum mismatch for table "t1"}} #------------------------------------------------------------------------- reset_db do_test 43.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 24576 pagesize 4096 filename 89028ffd2c29b679e250.db |
︙ | ︙ | |||
5809 5810 5811 5812 5813 5814 5815 | INSERT INTO t1_docsize VALUES(1,X'030003'); INSERT INTO t1_docsize VALUES(2,X'030003'); INSERT INTO t1_docsize VALUES(3,X'030003'); } {} do_catchsql_test 44.2 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 | INSERT INTO t1_docsize VALUES(1,X'030003'); INSERT INTO t1_docsize VALUES(2,X'030003'); INSERT INTO t1_docsize VALUES(3,X'030003'); } {} do_catchsql_test 44.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corrupt.*/} do_catchsql_test 44.3 { SELECT snippet(t1, -1, '.', '..', '', 2 ) FROM t1('g h') ORDER BY rank; } {0 {{.g.. .h..} {.g.. h} {.g.. .h..}}} #-------------------------------------------------------------------------- reset_db |
︙ | ︙ | |||
6913 6914 6915 6916 6917 6918 6919 | PRAGMA writable_schema=ON; CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); CREATE TABLE IF NOT EXISTS 't1_data'(id INTEGER PRIMARY KEY, block BLOB); REPLACE INTO t1_data VALUES(1,X'2eb1182424'); REPLACE INTO t1_data VALUES(10,X'000000000102080002010101020107'); INSERT INTO t1_data VALUES(137438953473,X'0000032b0230300102060102060102061f0203010203010203010832303136303630390102070102070102070101340102050102050102050101350102040102040102040207303030303030301c023d010204010204010662696e6172790306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020108636f6d70696c657201020201020201020201066462737461740702030102030102030204656275670402020102020102020107656e61626c6507020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020202087874656e73696f6e1f02040102040102040104667473340a02030102030102030401350d020301020301020301036763630102030102030102030206656f706f6c7910020301020301020301056a736f6e3113020301020301020301046c6f61641f020301020301020301036d61781c02020102020102020205656d6f72791c020301020301020304047379733516020301020301020301066e6f6361736502060102020306010202030601020213060102020306010202030601020203060102020306010202030601020203060102020306010202030601020201046f6d69741f0202010202010202010572747265651902030102030102030402696d010601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202010a7468726561647361666522020201020201020201047674616207020401020401020401017801060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102ad060101020106010102010601010201060101020106010101010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020415130c0c124413110f47130efc0e11100f0e100f440f1040150f'); INSERT INTO t1_data VALUES(274877906945,X'00000e96023030011a042319320d3b123d812b5a31120110446e581b66814a05010a4537814274010e8102815c810f3d0104846d01081581204401103741043c59416b44010a404655265301103f73811a11114213010a821235820f020135030484320201360104816a020162020484550302390301710a04824a020166030483690201670704837d0201690404822602016a0504825c02026b620504817502016f0904810d0303e79c88060482760201700a04826302017204048155020373c2be050481130201770204846202027962050482710202c2ba010482140203e58496070483330204e8b2b879010483710101310110545c0c814b0e3a6501082c815d5b011a2a0e2f0d765c3d686014061d0d0112810733112c2e82141101048313010e5c6f632e813e42010c811882370548010e19158146822f1f01104d364a708146135a010a237b0a55210201610904841703027678090481270201620304810002026374060484660202657a0704827602016601048351090483540301660704814b02016b03025f0304c582caba0204816602016c01025f0302cebc0904843e02016e0804821802016f0a04817503016f070483100201720304822c020484380201740404842e0102460201770104812f0204836c02027a6f040483110202cebc02048267040161020484650205d5bd62cebc0604845b0204f2a580880204842a0206f38184a179670502750204f696a3aa0a04814601013201063330390110812281378114600d010c03716c5e822d010e81226b542a814d010a72740f83000108813a1e0b010c5681046f812c010c07814a777328011664244219531b1a2f811e4a010c4d81557c7f1b0201300704810702013307048230010484050202367807048175020239710804832502016204026b0204814d020363306108048262020265650504817602026667070483150201690704832f0301360a04814d02016c08024702016d0304843e0303cfb2630204814002016e0804837503016203048416030370c2be0304821b02016f0604834b0201700504816b030175070210020273660604841c020676c2bac2b2640604830a02017704027d02017808048141010482700201790504811d0202c2ba0502470206ca8d73ecbab9010483340204f09e9ab504048367010133010c3e04814f82250114812e814b2e0411811305010c811337811e6e010c82085e2b0e5d010c61812054811c01148122451b0781050c813d010c17823762643e011e080c1720814a10364306143b0d33260112810f0c2a810c816b13010a8163810e470201370404811102056176c2aa36050481530202646e0904846202026a730404827402016b0a020c02036f616b0404830a0201750504820d02017605025e0201770a04820702027a73050482460202c2ba0604824a020483330203cba434040483200203cebc790304847e01013401124181442c1d091f81580108601d8336011081320a2b8125820001123b0b81158116811f070110078112817a817308010e6682410d810e2601122d0d6413378147351e01105081021d3525812d01128246510a622204054101105c1b620e81302b05020130020483480104822702013102027e020132030483270201350304844802023770030207020261710604823f0201640802570204830a020265770304831f020168070483210201690204825b02016f020481280704835402057037e18b8d0904810802017304048439030172020481440303c2bd6b0a02630201760202490804815e0201770304816e050483550201780704816902017a070483280207c2b2f093aabc780a0482240301b303024e0301bc0604837a0202cb800204834a0202cebc04048201040484410203d3ad770a04814f0202d5a508048371010135011630817e0f81040d2c041552010c813d3b7e8115010c40692182693a01121f810d810d0a32814701101d1d1f642281742e01068229240110811231810a387f4c01100f50810f8165810d0114811f26443152593c104a010e641e1a3357820e020132030481540201340204815402023778040207020163060481020204815b020164020483010201670a0481540304f0948f870904811a0201690704835502016d0604832203027b01022803017a0a025102016e020484260404816002026f690502680301720104834e02017208024f02021d020475e69c8e0504814c0202767602025f0302de870a04837b020178090483200104835003026a72090484400201790504837204022302017a0104836b0202c2aa0a0481070303bcc2b3090484370203c7866403027501013601087c158303011212814305813e7b0e090118141a1c49713a211e0c74630f010a59826d8113011203328166037781561a01101d7f1d2a1f822533010e820e070f7b40160110811f40292c813226010a2d20824a32010a81418158670201300304840a0201660404817d02016d0804826902016e080626817f0104820b02016f0404825a02017003023b020272750804840c0301760a04844d02017403025b020175080484200202766e060482360303c2ba6c030482220202c2aa0204810e0301b20204835703048421040484240301bc0802410202d2a1010482630204e1b18f3704048354010137010c08816337812f01101382211532424d39010881248123010e7724810267815f011081236029813e273301101b7b29812a5b813b01128150810324814b220b01060c8417010e165b6c81708117010a1782346f6c0201380804816803016b0604840102013908023f0201610204816c0201630302760201640304832604023e0204833902016502048203020266770804821a0201670a04830002026964080484500304f29e9eb70802250201700204811b0201710904832d0201730304826b05048403020174010481000205776a62c2b2050482630201790202260206c2b2eaaeb464050485020301b3080482480303bac7af0a0484550203c695650804822a0202ceb90a0481170202dbae05023f010138011819814a2703390a61090c6912011a21181304812523811b5f164e050114110f35128123423f810c010c817573817c03010e7182590c812b0401142503597e6e0e2f3a3759011252813a811a2b75091a010882162a31010e17450a81048279010858658208020231670a048205020361c2b906023b02016301048236020164050482520201650904833d0201670904811b0201690604825002026a7a0604837c02016e0204832002017002026d0302c789010481020201720504835e0201740604810002017502020a0702630302676306025f0303e4a0a70102640203786a75010484440201790104841402047ac2be72070481340207c2ba3766673576090482790301bd07048142010481600202c7b309027a0401740604823b0202d2bf0304830f0204e989a6300a02600204f4bd91b60702120101390106518369010e19254641823711010c258267288121010e817c810d2b17250110810a578133812f4c0110415681067b288121010e0881208119347101140b8131543c8100343d1101088203813e01100d742e3230820f3802013006048107020134080481440202356501021a02013808048147020162020482230201630304833c030162050483390206656cf093b5bd070484140202677303048502020769e3ad9669c2b90304847402016b0804836402016c0404841f02016d010481250904825202016e06025402016f0704842a0201700a04834a0201720a0483530201750304822e020676f097b18374030482140201780604833d0202c2b9010481550301be070483720204826f0202ca80060481630202d5a80504833f0101610114551047810e130a78660c011a364611206c0b13080705733d5501240f08070c090b0c20813d1471042e4351131e011204412d814f0913104201263036110d060b1f811a301b0f4e1a29092f181c012808071e221a2a81075b320503065a0f140c1a0a26011c07231d0e6f3715063b760c6b091501121111303e3a71566d6d010e0867814d816a0c01181e18240d41724d221b3f384b0201300204830b060483080302c2b30204837f0201310a026e020134050481560301730902690201360406827c0f0201370204825d06020a0201390904815b0304f3bfb2a70a04822c0201610404810e020262660604841a03017608025b02016309088112825f020164090482310201650a0484480302396f01025d02026774010482090302df9b06048321020168070661813303016f03048248020169030483610504814001048401010483460301300704824203016a0204824402016a0504813303021d03017209048412030277380804824502016c0104814c02036ec2ba0804835702016f0204811d030176020238020270360a04840d02017107048201030469ca99690602350201720304812d0104845e02017304022c02017409022b020175050484140302caaf0402410201760404831f020177010484180704845203026f6d04024b02017a030482660202c2aa0204810a0301b30a04817b0302bd76020483780302be6a0302440202c58207025e0202c69901027a0302ad77010483200206c993f099b183070484270203caa1660204841a0204f29788ac0804831d0204f4ba9f950504843c010162011c0e33810216341c2413042130780501184d373e53131f2f052907423e010c830e3781390e011c1320461f81041b811b041e15243d011e241b10816c310b130c3133033b0741011a11816d3139100c13140b395848011c580e411a06304306810a3138330d011a441707092c70140c1643813920010c73653581374f010c826c81210f0402013803024f07048172020161020481650204810c020162030483470301370404813602016307048379020483280201640304815501048176010481060201650104812a0104841f0201660504821f0201670302700201680804846403016b0a04831d0301700904845502016908025c02016a010483560904827602026b6306023402016c0404832602016d040484410204825702016e0504831603027831020482160302c2be0504827d02026f6a05048121020171030232020483220304845402023a0201720204845c0304846e03013607048224020174060484480201780704844303016f0604814f045807070a0707070707080709070709070808090a5c07080708080b07060a06080707070b0a0b0808070b0a0b0a55070b08080a0908080707060709070709070706080c060b07070c0a66070b08080609070607080c0909660b06070707080a0807070b0b0707080a0b07070d0607080c0908630707070b07070a070d060b0707090a07080b080a070809085f0707070c0706080706070809080f06080a5807070607060e070807080907070b070b060c0709090807690808070707070708070608070709070809070a0d0b07070809095b070707070707070c080d07070b06070707070c07080b0808811a0b08060706080a070a07080609070707080808071307070a0708070907060807090b06060707070b0707080708070707080c090a0a81080a0b07070b0f0b0706070707060b07070b07080808110b070707'); | < | 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 | PRAGMA writable_schema=ON; CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); CREATE TABLE IF NOT EXISTS 't1_data'(id INTEGER PRIMARY KEY, block BLOB); REPLACE INTO t1_data VALUES(1,X'2eb1182424'); REPLACE INTO t1_data VALUES(10,X'000000000102080002010101020107'); INSERT INTO t1_data VALUES(137438953473,X'0000032b0230300102060102060102061f0203010203010203010832303136303630390102070102070102070101340102050102050102050101350102040102040102040207303030303030301c023d010204010204010662696e6172790306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020108636f6d70696c657201020201020201020201066462737461740702030102030102030204656275670402020102020102020107656e61626c6507020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020201020202087874656e73696f6e1f02040102040102040104667473340a02030102030102030401350d020301020301020301036763630102030102030102030206656f706f6c7910020301020301020301056a736f6e3113020301020301020301046c6f61641f020301020301020301036d61781c02020102020102020205656d6f72791c020301020301020304047379733516020301020301020301066e6f6361736502060102020306010202030601020213060102020306010202030601020203060102020306010202030601020203060102020306010202030601020201046f6d69741f0202010202010202010572747265651902030102030102030402696d010601020203060102020306010202030601020203060102020306010202030601020203060102020306010202030601020203060102020306010202010a7468726561647361666522020201020201020201047674616207020401020401020401017801060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102ad060101020106010102010601010201060101020106010101010601010201060101020106010102010601010201060101020106010102010601010201060101020106010102010601010201060101020415130c0c124413110f47130efc0e11100f0e100f440f1040150f'); INSERT INTO t1_data VALUES(274877906945,X'00000e96023030011a042319320d3b123d812b5a31120110446e581b66814a05010a4537814274010e8102815c810f3d0104846d01081581204401103741043c59416b44010a404655265301103f73811a11114213010a821235820f020135030484320201360104816a020162020484550302390301710a04824a020166030483690201670704837d0201690404822602016a0504825c02026b620504817502016f0904810d0303e79c88060482760201700a04826302017204048155020373c2be050481130201770204846202027962050482710202c2ba010482140203e58496070483330204e8b2b879010483710101310110545c0c814b0e3a6501082c815d5b011a2a0e2f0d765c3d686014061d0d0112810733112c2e82141101048313010e5c6f632e813e42010c811882370548010e19158146822f1f01104d364a708146135a010a237b0a55210201610904841703027678090481270201620304810002026374060484660202657a0704827602016601048351090483540301660704814b02016b03025f0304c582caba0204816602016c01025f0302cebc0904843e02016e0804821802016f0a04817503016f070483100201720304822c020484380201740404842e0102460201770104812f0204836c02027a6f040483110202cebc02048267040161020484650205d5bd62cebc0604845b0204f2a580880204842a0206f38184a179670502750204f696a3aa0a04814601013201063330390110812281378114600d010c03716c5e822d010e81226b542a814d010a72740f83000108813a1e0b010c5681046f812c010c07814a777328011664244219531b1a2f811e4a010c4d81557c7f1b0201300704810702013307048230010484050202367807048175020239710804832502016204026b0204814d020363306108048262020265650504817602026667070483150201690704832f0301360a04814d02016c08024702016d0304843e0303cfb2630204814002016e0804837503016203048416030370c2be0304821b02016f0604834b0201700504816b030175070210020273660604841c020676c2bac2b2640604830a02017704027d02017808048141010482700201790504811d0202c2ba0502470206ca8d73ecbab9010483340204f09e9ab504048367010133010c3e04814f82250114812e814b2e0411811305010c811337811e6e010c82085e2b0e5d010c61812054811c01148122451b0781050c813d010c17823762643e011e080c1720814a10364306143b0d33260112810f0c2a810c816b13010a8163810e470201370404811102056176c2aa36050481530202646e0904846202026a730404827402016b0a020c02036f616b0404830a0201750504820d02017605025e0201770a04820702027a73050482460202c2ba0604824a020483330203cba434040483200203cebc790304847e01013401124181442c1d091f81580108601d8336011081320a2b8125820001123b0b81158116811f070110078112817a817308010e6682410d810e2601122d0d6413378147351e01105081021d3525812d01128246510a622204054101105c1b620e81302b05020130020483480104822702013102027e020132030483270201350304844802023770030207020261710604823f0201640802570204830a020265770304831f020168070483210201690204825b02016f020481280704835402057037e18b8d0904810802017304048439030172020481440303c2bd6b0a02630201760202490804815e0201770304816e050483550201780704816902017a070483280207c2b2f093aabc780a0482240301b303024e0301bc0604837a0202cb800204834a0202cebc04048201040484410203d3ad770a04814f0202d5a508048371010135011630817e0f81040d2c041552010c813d3b7e8115010c40692182693a01121f810d810d0a32814701101d1d1f642281742e01068229240110811231810a387f4c01100f50810f8165810d0114811f26443152593c104a010e641e1a3357820e020132030481540201340204815402023778040207020163060481020204815b020164020483010201670a0481540304f0948f870904811a0201690704835502016d0604832203027b01022803017a0a025102016e020484260404816002026f690502680301720104834e02017208024f02021d020475e69c8e0504814c0202767602025f0302de870a04837b020178090483200104835003026a72090484400201790504837204022302017a0104836b0202c2aa0a0481070303bcc2b3090484370203c7866403027501013601087c158303011212814305813e7b0e090118141a1c49713a211e0c74630f010a59826d8113011203328166037781561a01101d7f1d2a1f822533010e820e070f7b40160110811f40292c813226010a2d20824a32010a81418158670201300304840a0201660404817d02016d0804826902016e080626817f0104820b02016f0404825a02017003023b020272750804840c0301760a04844d02017403025b020175080484200202766e060482360303c2ba6c030482220202c2aa0204810e0301b20204835703048421040484240301bc0802410202d2a1010482630204e1b18f3704048354010137010c08816337812f01101382211532424d39010881248123010e7724810267815f011081236029813e273301101b7b29812a5b813b01128150810324814b220b01060c8417010e165b6c81708117010a1782346f6c0201380804816803016b0604840102013908023f0201610204816c0201630302760201640304832604023e0204833902016502048203020266770804821a0201670a04830002026964080484500304f29e9eb70802250201700204811b0201710904832d0201730304826b05048403020174010481000205776a62c2b2050482630201790202260206c2b2eaaeb464050485020301b3080482480303bac7af0a0484550203c695650804822a0202ceb90a0481170202dbae05023f010138011819814a2703390a61090c6912011a21181304812523811b5f164e050114110f35128123423f810c010c817573817c03010e7182590c812b0401142503597e6e0e2f3a3759011252813a811a2b75091a010882162a31010e17450a81048279010858658208020231670a048205020361c2b906023b02016301048236020164050482520201650904833d0201670904811b0201690604825002026a7a0604837c02016e0204832002017002026d0302c789010481020201720504835e0201740604810002017502020a0702630302676306025f0303e4a0a70102640203786a75010484440201790104841402047ac2be72070481340207c2ba3766673576090482790301bd07048142010481600202c7b309027a0401740604823b0202d2bf0304830f0204e989a6300a02600204f4bd91b60702120101390106518369010e19254641823711010c258267288121010e817c810d2b17250110810a578133812f4c0110415681067b288121010e0881208119347101140b8131543c8100343d1101088203813e01100d742e3230820f3802013006048107020134080481440202356501021a02013808048147020162020482230201630304833c030162050483390206656cf093b5bd070484140202677303048502020769e3ad9669c2b90304847402016b0804836402016c0404841f02016d010481250904825202016e06025402016f0704842a0201700a04834a0201720a0483530201750304822e020676f097b18374030482140201780604833d0202c2b9010481550301be070483720204826f0202ca80060481630202d5a80504833f0101610114551047810e130a78660c011a364611206c0b13080705733d5501240f08070c090b0c20813d1471042e4351131e011204412d814f0913104201263036110d060b1f811a301b0f4e1a29092f181c012808071e221a2a81075b320503065a0f140c1a0a26011c07231d0e6f3715063b760c6b091501121111303e3a71566d6d010e0867814d816a0c01181e18240d41724d221b3f384b0201300204830b060483080302c2b30204837f0201310a026e020134050481560301730902690201360406827c0f0201370204825d06020a0201390904815b0304f3bfb2a70a04822c0201610404810e020262660604841a03017608025b02016309088112825f020164090482310201650a0484480302396f01025d02026774010482090302df9b06048321020168070661813303016f03048248020169030483610504814001048401010483460301300704824203016a0204824402016a0504813303021d03017209048412030277380804824502016c0104814c02036ec2ba0804835702016f0204811d030176020238020270360a04840d02017107048201030469ca99690602350201720304812d0104845e02017304022c02017409022b020175050484140302caaf0402410201760404831f020177010484180704845203026f6d04024b02017a030482660202c2aa0204810a0301b30a04817b0302bd76020483780302be6a0302440202c58207025e0202c69901027a0302ad77010483200206c993f099b183070484270203caa1660204841a0204f29788ac0804831d0204f4ba9f950504843c010162011c0e33810216341c2413042130780501184d373e53131f2f052907423e010c830e3781390e011c1320461f81041b811b041e15243d011e241b10816c310b130c3133033b0741011a11816d3139100c13140b395848011c580e411a06304306810a3138330d011a441707092c70140c1643813920010c73653581374f010c826c81210f0402013803024f07048172020161020481650204810c020162030483470301370404813602016307048379020483280201640304815501048176010481060201650104812a0104841f0201660504821f0201670302700201680804846403016b0a04831d0301700904845502016908025c02016a010483560904827602026b6306023402016c0404832602016d040484410204825702016e0504831603027831020482160302c2be0504827d02026f6a05048121020171030232020483220304845402023a0201720204845c0304846e03013607048224020174060484480201780704844303016f0604814f045807070a0707070707080709070709070808090a5c07080708080b07060a06080707070b0a0b0808070b0a0b0a55070b08080a0908080707060709070709070706080c060b07070c0a66070b08080609070607080c0909660b06070707080a0807070b0b0707080a0b07070d0607080c0908630707070b07070a070d060b0707090a07080b080a070809085f0707070c0706080706070809080f06080a5807070607060e070807080907070b070b060c0709090807690808070707070708070608070709070809070a0d0b07070809095b070707070707070c080d07070b06070707070c07080b0808811a0b08060706080a070a07080609070707080808071307070a0708070907060807090b06060707070b0707080708070707080c090a0a81080a0b07070b0f0b0706070707060b07070b07080808110b070707'); INSERT INTO t1_data VALUES(274877906947,X'00080e7f073c23110a1a18392f66090524183704276d6703306a320404824e030164080483520305c2bd7ac2bc0604815a0201360704833202016106021f020482400201630304822a0708817e8204030173040483500201640404824803016d0804824a03017709023002016606048367020268680a04815802016902088339811804027f0302656e0704834e0303d5a5370604816702036a3366090484470303c2ba660904826e02016b0904837c02016c07021403026c610604835802016d0204816802016e0104831202016f0104822f020270720602060201710704822202017206048174020273690204824602017409020c020175090482140201760a0482720301660404824403016a090484290201790404845703025d0203c2bc33040484620301bd0304824c020484540202c78607022403019a010482380202ca87070484390202d39d030485050203e184940404831b0203e6a881060483480203e8b18c0a04816d0203ee8d850104814801016b0110467257393c81272c011a053e815d3b190517064524521f011c3823590a8115372004313b1f3216011a5a20780b102d0804426916112c011a182f810781082d12137026161501221a180516811611051c131207811515173501180320112581062e05621c1407011c2d0e0617811522062208065a21520114582841621e6c203f1e2001161647411a272533815b1c2602013009048309020232630104835a0301720104817f0201330604836f0302ddb5080482560202347a07048102020135020483460104827b02043678ca800a04835f0201370404814b0104846002016103048246010482220301700204833f0201620404824d060481150201650304824f02016606088110834c0201670604821d0303c2be66010481790201680404843b030176050482270201690a04830e02016e0904844202016f040481010301630304822f020270640204822f03016e0704845802027177090482710206736ec2b2796a0104832e0306dab1d485377004048304020174050481700201750a0212020378627604048164030173080483190201790704833d0204823a02017a0506820e67030178070484530202c2b2060481500104823f020483030301b3020484310301bc04027e0402caaf0a026a0301be040482590204842e0202540202c79f0804824d0202cfa30804815a0204f29a92970204823301016c01140f63351a0a653b650d22011c09117a3e1538123537046a15043101141310082f49052f772b0c011c11121781583c2a5010133228241301287f3e0a2b1244080503060a100f413b4f0d070e2a01103e4e1f04814e7b1601183d0404052877111f230f811d01123a100f053e5c076910011a031732102381243d1b1727507301180e5d273e810803812e0f192a02013301048271070481330204821d020134080263020135060481280201610104830a0201640604826d020165060483050201670204841c0504841c0304841b0201680a04845602016a0104811c01024f030481080204813102016b0204837008024502016d0404836c04068207780301670704842302016f0404821203016d040484490301720404837e0201700104821d03048407030165050483050201720a04811602017307023502017407020503016f080484240302c2b90504821b020175090484090201770a088119822503026d6905048300020178030482680604812a0201790104830c0204833a0303d9a06806022002017a060482600203c2aa33030481560301b904020a0301bd0504820f0202d0b90904817c0202d3820202200202daa9080482030203de966e02024b0202df9d080484350204f098b0a20604845e01016d01220304456608322258060a031d4c38340f090112310c070e4238626e6601124a318109030513812f0118240d561e533742188113101b01160b24444b224d44814d4806011c05774e483410330d23541b28090401141f29062581131e221b6d011e81053a037a03320b0e4c24360d2310011a0e321d3c141825111d54637a1c0114093d3c2e58571a35293a0201350104840a03017701048330020136060217020138030483370201610a0482650201620504815e0201630704827701048201020164080483690201660804846703016904048113020167070483080201680504837d05022c0302cdb10a04815f0201690104833a0404824302026a360a04823b02016b0a04813502016d0504831a0204833803021a02026e360404825e02016f080484140201720304844b0404816603056ff09d899b0304823f020275390204816e0301780a04824202017604088308812703027902027770050482040201790104827e040482750204812902017a060483030304c2bdc2b30104836f0203c2aa62040484040301b903021c0302bd6b090484300301be0704814d0202c99402025603049a65656b090484020202ca92090482060203d19a730504844a0203d49f690804836e0202dfa8020482710204f09180860704822901016e011a0c0b8104243647521f43231f36011a2e1b33432c3d0b414905054d17011010573a6c0a816c1801160e063582340a5239050b06011a4481063d1b67250f2044200839012044591d1857291214135814101a1b361d011225067e8147111a4a4301166b13362e17195f3812186f01141c465b032b290406373301182a152a2281300f8107054e3f02023274080481770305c2bacf8168020481450201340604832f0201350704842e02013605020e0201380404841d0201610404810d020483750201620304812b020484230301610804834503026c6a0304816d0201630102380305613577337405048359020165040482720201660904826202066736f094b0af0a0482250201680104811f02016b0304847202016c0404822403016f0904822c0302c2b301025002016d0504817b01023f02016e020483090802040303e7bda10804832d02036f6b740404811402017005048419020484220202716506026303026b760904830a020172080482430304706c73620504825f02017308048413020174080481070201760104827f0204836e020477e7b89a0104840e02017a030483700206c2aa35657065050482740301b30804842b04046cc2be78090481040301b903020d0301bc010484260904813f0203c7a5620302330203c99f36050481010301a30704815b0202ca8b090483250202cdbb0604820a0202cebc0102170401380304842b0207eca2a6f29c87950904824001016f01221d17052b58101241060e3a201f1021633a0114816919811c142443100801280426080e2620042a812c531a490e121707131710011273432e493347811a340112195f671f46721c325e0118380c052b812822478107600b0116021c21821b2019263433040126021b05351b2a286b05181f071b5628111a330a012014533e073d0c0e5469141d1e2734050901220318051b44412803632e0642370e0a3a2b020131070481770201320a04812f0202346e04022b020136030483590304f09a81b60404834702016105048210020162030205030167010268020163010481540604820202048300020264310902420201650804834b02016703048247030365c6b602048205030573f098b890030481450201690204832802016a0a04826703016c0104825e02016b0604815e03016c03048334030677c2aa74c2bc09023d02016c0304823903027777060484540303df866c0104815b02016d0204811f0303796f7704020302016e0204814d07024a02016f0902680201700604840a0104831a0204835a020172070484440201730a023703026b660604830e030278790304815b0201750904822402017704025b020178030482350307f4b2a3896a343407026b0201790902720302633409020402017a020484590302dea004025f0202c2b20204816b050481200202de900402160204ee85a5770204822c0101700114143a0d391a60812d4e09011a2f313104201c372c3a3411321b011a268140144226334145050d1c4d01164e081f20671f088107237901186b123c1f6d07261e2b732e210116511116342a3d32376e083001106882257a0a17141101163039192b0c05812d735f3b01262a3e0841030b17181411051e0a18530e272b6d01182f322b260e24581d5381050f02013104048353020132050482370301690204843e02013302020d0201340104841f0201350a048139020137050482770201380204833a02016105025a0504832f0201620304836d020163050484100304832003016c030481290201640304837e020482490304822b010482290201660a04827002046964dc960204833102016c0704814502016d010482000201700104817e02037176760904821f020473eb91a708048152020174090482770201750404831e01063a825d03017a0904826a020276730a0254020177080260030277630104815c020178070481220202020301720804841202017a0204834c0202c2aa040484010301ba080482580202c6a3020481320203cdbf690502790202ce90070483140301bc030481470205d1a371cebc060481590203d2976a0404830c0203dfba6e0604814b01017101163732393b8120422f054b0e010e030b211d815d1c01165641757c080d81311d090e0112816581542d2313054301224e07121706516606080e39102d231c4b39010a2d81402d5e011a132527428114080d6e1111721c011a814a1a341538251023100d1c4c011e22182622623712411e38162a182d3b01142b67611981470f1f1f250201310a04824e0202336207048217020238730204815a0303cf886d06025a02033962620404833803016f0a04814e020161060483140302726d050483450301790904810c02036376690504811c02016403024d020165010483280802550301650904827f0304ebb8b561070482340201670302670301660804810e020168040482340201690704844d0302616404020f02016a030481060301700704827802016b070481240104814b0302c2bd0504816102016c0604837f03017a0404837902036dc2b90804810002016e0904821602016f0304812c03016401024b02017103048233060483600303e5848e04023a020172040481050305f3978aa06c070481151708070b070a0d0707070607080c080909090706080707070707070806070707070a090b070708080909090981140708070708080b0a0b0b070b070907090707070707070807080c0c070609070b0807100706070e08080a81110f06070707070f07120a0c070707070b0707060607080709080b0b080709060708070808080a810f0707060707070b070707070a080b08070e08070b0b08070c080f070a09060807070a080909080a810b080b070706070b0b0708060b07070c07070707070a0a09090b0708070a07070b0a070c070a060b080907080807070d8123070707070a0706060f070707090b07070707070b07080907080a060f070608080706070c060707070c070a810f07070706070707070a070b0713070a070707090a070c070706080a07070807080808070b0909810607080808090707080709060a070a060707070707070b080707090707060b0807'); INSERT INTO t1_data VALUES(274877906948,X'00000e8a0330717304048359030134050481100203756371070482190201760704817b0301770804821d0201770204844d0201780204836c0404826103017504026a0202c2aa020482420301b305022c040267390602570301b9080481540301bc0102290206c99cf6b5aa80080481430202cebc02026e02048120010172011a1c2f15158108048125463f251d010811811539011412423105812181171549011847284a30234e5b33042632120118351e8113817d0f2b220d111901264f104a211004061d0a2a0b35121a0a2118341f011c81160a1b030d2a0610243e445f0c011c6f0c1e3b1768141e322717500b140110537f810169811625011a492847203e210f532c16480627020135020481780302caae0104811a020261330904846c0201620804812d0201630404814a0201650704837503017301048276020168050213020169010484540604842b0302796f0504833302016a0304831b02016b0604701302016d0604815302016e070483630204815202027071020481520201710104835b02037266700704843002027362040481490201740904817d020175020481040304f59e9c9407048218020176060484060204776dc2aa020483070201780504812503016601048159020279790704840502027a730904826c030178030482740202c2aa04023d010483540301bd06026b0203cab877010483290202cdbf060482410202cebc04025c0401690204827f04016c0904840e0202cf880104835d0203dfbe6c01025b0204f0aeb7b2030481680205f1a7b5bb390504826a010173011a22810d12415003071f81181839011a3220221511546d810012052b57011a0c4274300d154e81111f041e10011e293f4213051b2276560817312811170120092136122418370e4e782b3912080f3201262b3b340f222b0c09142a0822116a135c1c130c0114320c4e385a0d0415075f01163543340f06362381133c0c012224180981742048191d110e180e180d310f011a20632450281f043027114b034e0203316a61030482160201360104826e0201380a0484570201610104844d0504814a0201620904820f020164010481630304810403027761040258020165080481550302c9b70204827a0204677367690102660201680104831b020169020483760301720a04814502016a04020c02016b04023405023c030269630504840502016c08048463020170030482670202716d080482000201720304835c03016507024d020174030482520504821503016505048207020175040208030137060481710201760a04833d0201780404832302027a6f080481200202c2ba0204812c0301bd0404821e0205c3a66865730702540202c7890804816f0205cebcc7af730504815c0202d2930202540202db89020481160203e8b8a00304825d0205f0958db331070481620305989b8569780a04813d0204f69299a5020210010174011a7b3829100a4e511f1a281c17140114812626032c372634234c01140a520e815a810815200501123e4f3531042d57615b011a041f3e64070f1f1913274a20770114811d0f5d743e0634161c01162c2782130c1b810520280d01164a513110480b402b810d13011e522d08042c1146137012201e810512011a290903182c05301e5d811944290201390a04836d0301610104836e02016208027803036cc2bc07048261020263640a0481480301730704813602016408022b020165050484310301720702260301780402500203666d73070484470201670104825b02016a040481590304836702016c0304835601025e02016d060484110301340204813702016f04021802017006068336280201710304813507025902017201026508022903016d0604812f0201740304827e03016a010482440201750404834b02017604021a010484150504836a02057773c2b2380602520201780204823e0302cebc080484040303d2956403048171020179020484240204813c0202c2b303048307020484410301be0204816f030484250203c798680104843d03019c030482570204e19ea86a020482350302a0950a0482280204e5a4bc780304810e0101750126090a35030a03220a1731630f31252f0c4b1e31011e39200e3715282a03103b56090f6b1501121d4916246e6d460d6501162609380406361e816d203f011a22166008124f58202e182025150114390f3a25713f0e3f715c011a5a11191123466025710c313312011e3c191326811c1444055f1f5109051201143b106f1181000d068155012043381381020d81080d0603171824260a0201300404844a02013207024203026b390204833803066eeebabb35660604842102013308020302023f02013503048243020436716b66040481440201380a04843d020261690704836002016203048209030484670201630a04841d020264790104822b0201650502340302c2bd060484300201670202620201680704810d020169010484430104843402026b67040481540306eea3ad77c2aa0a04836702016c020258040482270104830a02016d0404824102036e716a0604843e02016f0104832a04020c0204836803036530650a04817402017005025b0301630604843d020171070275020273720404827002017504048133010484120301370102270201760104814f03026203016d0904844802017701048375080481220301660202330301700a04827f020378c2b2030484710202796806023c0301730704813d02017a0404815f0104817202048407010483390202c2b204026802048254040266640204831e0301b3090482230302b963060482010401750a0483290306ba35f2999dac09020f0203ca926e090483350203cdb4780302350202cebc0a020f0204d7a7696d010483100206f097bc996d71040481480101760114185b2258291610821c0e01160272173107154f5b813722011a81020c200e1826250d39811f07011a7911152a2a45131504422c81070120050d3f5b23342e3e4139032a3813042d0116592d1c15630c0c0a814649011c1a362f5c4a35511f0804033e372b01102981262a352e8205010e0b4b6282388106011e26810a2d125f361a12170d1721311e0201300204832b0201320104811b050483790201350204832202016404024c0202657a090483710202666307022703016c07048362030277750604842f0201670304843d0104844c0203686f7a07027202016a0102430204847502046ce0a2b20704810302016d0204827b02026e330804826c02016f0104835502017102027606026c020172060483490202736505048371020174030484130302387602025d02017502048345020376346b0904825c0201770904814b0303c2bd720804812b020178040483600201790804816402017a08026e0202c2b90704811c0301bd0504821e0204cdbcc7a108021a0202cfb8080481490204f09f96a50204842101017701180207232d37812d0c045c4a0a011a06163b3408171c52213a26592201206d08581605811a171e0c0a1347104914011282181324082b73320f01122f6e811d2c3d410a44011e551414206a092f133f333d150a3e0f011e235b170e37060627471b13373b3e27011a0e1e816b270c10102d53381045011a060e1e254d044932651234691e011a158138300a04810c0a8121071802013003027707048214020131080481370201320a04835502013304048271020538ceb369650802310201390a0481440202616c0502570302c7a104026c0201620804811c02016301048168020241020164040481560104820b020165080484460102400202686c060232020269670604827302016a0108810c826e0704824e02026b6c0604816902016c0304831c02016d0304811903016407022b02016e01022e0604845a030237780702040301710804815102016f0104842903017a0704826902017003048445020482080202713002024e0201720804822003016202022302017303048111010482790204812d03067479c39f66700a0210020174020229020175090484430301690604820402017606020202017a01021b0104843a0202c2b90604842b0301bd030484570202c69b0504815d0202c8a30a02240202ceb8090484690301bc0404832f0202df85020481230101780116812b0a16810e4b045a3b2a01205b1305811134092f62072343100f0f05011e5734152612030b4c4134123009361601121781653207780a6a0d01164a25210824138107738139011481341f088158060c8133010e5920193a4c2331011a0510358101231a1b3609702732011a2f07631610033436810256174c011a1342040a58110721378139101602033067750802720201320604834303017109048244020133090481700203366f79010483520201390404810902016301048411050483420201640a048432020265310704832b02026774040481000302d5b2010259020369756c0504832902016c07048365030233700904824102016d010482670404834c0504830c02016e0104831604048120030169090481750303eba6990104835f02016f0604834c030379c2ba0a0481560201700404815e06048256020174040482370201760a04820d0201770604811c02017a0404812e06020b0202c2b9030481660301bd0a04816c0301be030483620206c99b6d7777750304835b0206ceb0646b66610402490202d8bf030482250206e8bfbc626964080482510204f09c9a9e0404830f010179010e2081335661371c01220e4e2718124f0d0649812b0b0a063b040b011402741d1235810805211a011409161d732b8106325f6a01182e330325068107703728302b011e3723081c0d0a3f810c183e061b067f0106834a12011a044030185a1e810704220a0541011245602b0e421441817801144b03811a1a29614e224b02013003048139020132050485050304f09caba6010482230201350104822708048413020138020483430201610402230201620902440108812181070301300304815e020263710404831002016403048226010483660604823c020165010484510201670104816407048418030334c2b20a0481120201690404814c02016a010481500904810f02036b75610304836402016d01027902016f0304817b03056f6373cebc0a0483010201700104817d020171050482680104843b0302383203048128040807090707070b0608060707060c0b810e07080807070707060b080707070b0807090807070a070a07070808070b06090807070708080a0b81230907070b070b0707080907070706090807070807060b07060707070808070a080b0708090b0b09810a0707060908070607060609070b0a070706080a09070707070e0a0708090b0c0b09070a080a811a0706080c09070a07080b0708060806070b080c0e07090e09060706080b060a070b0607090707130b080708070b0908070a0c810d070b0706080707080b080a0a070807090708070707090709070706080709080a81170a0707070a070707070a0b0a07080d080707060a070707070b0707060f0b060707060a08070807080708810d0807070709070b070808070907080f0b070907090b0707070a0807070c0b080c0a810107070a0b07060c07080f070b09070b0906070b070b'); INSERT INTO t1_data VALUES(274877906949,X'00000e5c033079720404826c0404833002021b03026f6b020482100201740904842e010484150303c2b36f0204840e0201760704826b02017708048273020578f48ba5b50a0481400201790904845902017a050483280304c2bac2bd0404841e0203c2aa680904843a0301bc070481100301be0304820304016a050481630202ca8103027b0202cb860604840d0204ceb56e370204832e0302bc740202520202cf8d07027e0205d8ae39c2aa0104813c0204e887b3770404816a0204f1bfb0970204832f01017a0118101e282f07045961813a193e011e69162f0d2b051c060f084460063053011e06810c20330d0733815c220515220c011210290a7e07810c3a18011a1f2f064a19155212472781047c010a123e45825501166c6062182718167131092f0112331b812c0b6e81470b01184f3a230d45261e271c36111701140a8128456b291248391a0201300104840d0204812502013401048318020137070483070201380904823b03016704026402013907023403016e060481380201610204812f0404824504045243020162050481150104824003016a0804827a020163070484590204817903017a02048209020164020484200203653077030482610302737601048424020166070481730201670304841e0504840e03016b0504825302016901048235010484400404841002016a010483680404845f02046bc2b97407023302026c7a0704812d02027161070209030378cebc0a021f020172040483750404815f0201730304813c030131020482040201740704824d0302793901027502017604048423020177040620813103048313020179030484540204833c04022503017a0904826302017a050483530203c2b2660404840f0307ba6272f397bd92010483070301be020482760202c6b9050482410203c9a3650604812c0202cbae020482180202d38c0704812f0204f096adb7070483490204f6a69c8b030484390102c2aa010c815e81147969010c811c827f0417010e81077a4c03815f010a2e8100820c010a810d148140010c0a7481201a13010c0b831525323d010a8206358129010c21637a33812701083c8340390301300504820a0304326939770404841c03016107048334030165030484150302696c0704810103016c0704812a03027178090481620301730504830e0301750504846303017802021c0301790304836803017a0604834e040135030482650302cdbf010483330304ceb23169070484090303e4849a0504817d0201b201088219744601082210832c010629846001121c8137182211816232010a81668122690108817281080110816a433581102f3e010e7481001b3481190106814e1b010e3646823a810e070301310504840b030161010481720301660604822f0301680804821003016a0704844803016b0104845b03016c0504823403026f700802340301710804826004026d3106024a03017509068458070301770a04836c04016b01021f0301790a0482790302c2b20a02270401b3040482130303ceae6e010484330302df9e040482100201b3010881656e750106820b50010e81434a27048153010a812b068122010843810c0401048211010a50817d812e010c811a8163810801061e832c010c811f81418101030163030481210301640504831102048104030482440301680a048202040271300404841303066b6576cebc6a0104843603026f7a08026d0303756a7808023e030176040483610301770704814403027973020484360302c2b906020c0401bc010484490401bd0804835c0302d38c0304846f0304eaae96750a0484020201b9010c3b824018322d010e0468315a5c817901067d583401060b810e010865118169010c0e07826b813a01066f8265010c3b8239633852010e61161e7030821b01068241210301350804843d0301620302480301690402610403e7a1910704812103016d080269030673c2bac2b36c090483070301760504821d02048454030278350702620302c2ba010483320304ca897a750804813b0401b5070482350303cebc6d050483120302d199020483020402ad660604840c0302d2a1010482550302daa30202340201ba01026d01085119826a010c2f5e82008110010882028221010481090108821b812d01068128460208810b8264010c810971812d440301310304820e0301320504825e05048221030333756d010482720301340502700301640604813d03016607020c0301690204823a03016b0104812203016c0704842103016d0304835f03016e0a04813c03016f0304834d030173060482660401710604810f0301740104843c0303d48174040482690201bc010482690108813c83290114090f816045242e148111010a810616822701048456010e2c81167a638115010a3a3b83204001067a8367010c8114127a2265010a824f7f5c230301300604833e0302616f020483560301640104827d090481280301650502150301660804841a03016804048221030169030481120301720104827803017606023d04016e020481700302c2aa0904836c0401ba090484100201bd01088240224f010843813674020a81185068620106822a44010e14154a8101825e010c19814a1b826c010c81221f81651b010a815a4d812c01082d7281160301300804843c030231300304836703013509048353030365c2bc0304814d0302667504027a0301670604831503016c09025d03016d03048178030172020483620301730104816b0402c2b30404823203017401027204016a08048451030175090237040177090481690301770302190301780a04823d03027a350a0481260302c2aa060481620401b3090481090304f098a1a30a04825d0201be010a0d730b816f010c821d81236c2b010c6f8208358119010681236801087d4e831e0108823c8235010667794b010683165e010e05812e3d3c820d010c81148123817403043531c2ba0204824c03083875c2bceba7957a03020803016302020804036dcebc0304814e0301640304843704033379790504823203016b08023603016d070481090304825804013707027a03016f080484530301710a04842203017809025e0304c2aa6135010481460401b90a04836b0401bc0704814f0306c6ab66e3afb9080482660103c39f350304821f0201b0050481110301680602030201b8040481310604810403016c0a024803017108024b0201be06048323030482650301300504812d0304f48990ae060482740103c491680a0483700301760a0481290201a7010484090202b177020482380201b3030482280102c5800602090301360104826a02018202048173040483780301370104814102018b090482730201930504810f0102c680020483790404830c020183020228020185030484400704820b02028d7a0a04821c0201920404835e02019507048437010484070301760204836102019a020214080483100303d795680504820602019e030481050201a30404820a05048436030177070484290201a50704843b0201a8060482690304816f03027735020483630202ab79050484430201b6060481050201b904024003016d070481130201bd090484350201bf06048361030163020481580102c781040484560201830604833a020286650404842a0301750a04821a020189070483370303e0b9b30904836602018c0104816c04020602021d030171050484570201960a04842d03016b0204821903016c04021e03016e0204845002019a0a04844402019d0704835103013103021702039f77750704827e0201a1090483340201a301022b0404831d0304616363750502520302cfb2040483720201a50a0481530202ad760902310201af0104811d0908816281390301640404843c0201b3080483240201bb030483480201bd040484290304840a0203bf646a0404843f03017a040482450102c89d05020f0201a1090483550201a3060483550201ab0904813203017a04024a0201ad030482210201b10204824302025d0303656577030483600202b46e010482240201b6090484410204bce39f9d020484570102c9870604813202018b0804843603017a06027102018d080481130204840c02018f0104836309026202029164020484430201930504816d0201970304843402039c6c73070483700201a0070483470201a203048262030364d7960a0484010201a80304832a060484390202a96a080481170303c69532090481440201ac040214020481180202ae770604832c0201b0090482300201b40804845a0201b5070482110302716f010482160201ba0504837b0201bb02048149030165050483250201bc07088105833002067f824d0302d19f0402330201bd04024d03017a0904814f0102ca800a048321020181040481580201820604821e020383693707048417020287630704840002018a0904834c0104835c02018b06022f02018c0704814702018d0704810a0104831a020490e7b38308048423020191020482510201920304832f030135030483710201950304833207026802019902026b02019b0904832a02019d09024c02019f0802210201a4010484080202a5710a0481680203a777670804831e0301790902100201ae0402700104834e0201af040484650202b673080484190201b705048221010483520201b808048465030167010484400104cb81cab90104834802018602048317020689777568cf920804842602018b0404817b020191050484200202a0720304833e0201a3040625827f0201a4030485080102cdb1070881408205020483700201b30404840e0202b735080482640201b80504815a0201b90a0482370206bb31cebc6c730304842f030133070483010103ce80370304826d0201900202770201ae0504844e0201b1050484080201b20904815f0201b3040483430201b40702600201b50804823b0201b90304846e0302c9a1070483300201ba0404844d0104847e0201bb050482780201bc010882378223010e811105814d8134010a8142823f2d0106811c52010a6e1814816b02088168824b010a438137812d011019060c6b812f811c010a81314e811b03033366660404825503013502048263030238620904820703016303048120040f080b0907070b07070a0907070707080a07070b0a0a81060b0707070606070f0b070b07070908070b070f0b090807080b07070707070c0e0707090d07080908080a0a50070a0707080708070706070707080a094d07070707070707070707080706070707090844070f07080c0708070708070707080a4707060609060c0b07080a07090808080737070b09060706070707070707070707094807080b0607070707060708074107080709070706070707080607060706070808070a460a0d06090709060b060707060a07070c0907060b06060b070a090707080707070b0707070c060b08070b070a09070b07070b08080706070707070807080707090d070707060707070609070a090807070d0707070b09070707070706070a0908070a0807060b0a080707090707090b08090a08070707080707070e07060708070709080b06070b0a0707070a06070606070809060a07080b07070a070c07070808070e070807070c07090607070707060707080b0743090708'); INSERT INTO t1_data VALUES(274877906950,X'00040e1807020e0830cebc66f09f97b60604840703016b06021003016c0804835103016d0a0484050301710602560301730304822d030275770904834e0301770204824d0302797707022e0302c2b2070482640402bc6d0a025e0303c3a6370602530305cebc7768690a04823f0201be0504816f0301780a0482780201bf0a04833a0305f09e919a790a0483440103cf80340604827e0201810404823e0201830304843a0504837f0301780704834c02018407048139020186030881038372030178010231020187010481100201880204835b0204845a0104825a0201890204825c0604831802018a0704841502028c340304845e02018e0602180301390204833c0203936e770104820f0201940704823702039765630304847b020199080484110301710704821402029b650704827102019d0304845802019f0504845c0303e7ba880502690202a163090484160201a3060483020301680102470201a90a0482480201ab0104837f030482570201af050482190201b20a0481020201b30504842903026f64040483650203b873780704826d0201bb0704831c030177020481410102d0b0070482560202b17a050484460201b2040483400201b40402390202b671020484220202b777090483510201ba030481750202bb6301021e0202bc620a0484080201bd0204815d0201be060482470201bf040483340102d1800904825002028470050482290202876f06022202048872c5820104826202028b680504845d02018c0a027302018d0a0205020197090483210202986b0a02780201a3030481580201a70604835e020483670201a901048379060483780201ad0a04816b0201af010482310201b1080482020201b3060484610202b5640804814c03026e690304847c0201bb080482710201bd020482020201bf06048435010482590107d28b37c2ba61640104831702018d0704810b020393c5890204836e0201950602070305f6a5989a74040484450201970104813702029f790a04843f0202a57407027f0201a90504835b0202ab750502490202b9760a04827d0301780304826e0202bb6f060481780203bd7130050483630103d3866f09023602028a6c0604825302018c0304845302028e650404833a02028f6f0104821302039d356d090484320201a5020481130404813f0201ab0704835b0201b90a0482380201bd0904833c0201bf060484450302307604027f0102d491050483300201930a024603036bd291070483060201970704826702079b72c2b3356f730904844f02019d010482610201a10404814d0202a36b0502250203a5c7b3080483780201ab02023d0103d5a1640102260201a206026a0301660804813c0201a5030481180201a7050483360201a9040483510201aa060482020201ab0504811e0201bb090481680202bd740702160202be700304846d0102d6840a027d02068534f0988d910a0483730102d78f0404832804048462020390766601027802019202027405024b0201940a04834d020298770904815702039a6c6b0304846802049c73616e080483420201b0010481050202b565050481290206b67376c2aa640a0483280201b80704830e0102d89d0202150802720201a60602480202b073090481480201ba0204836f0102d9a50202670201b40a04822a030337c2b20a04820f0102da800604831c0201840604842802038636380804811e020188090484190201920504815402019a0304830c0201a301023d0201a6040481460201a8020484100201af0104842a0204825f0201b50304827c0201bb0804830f0105dbb878c2bc0502580107dc97e69eaf6764020259020299610104812902029d680502110202a0690a0483270203a56372030483540202a96a0204842c0205acf094abac0704821c0102dd92020483410203946d790304814f020395d7ac090228020296300404830302039b397809020a02029c770504833d0202a2700504821a0201ab010483400202b0760a04813a0201b2040483130203b3c7a10104833d0204b4e8a5a40604816f0201b90604830d0201ba090483630102de800904810a020281740a02380201880704826802018f030481670201900202790203916e710404833502019206048418020399ddba080481240202a3630a02250202b86e070481670204830d0201b90604811f0201bc070481530102df820102390201830304830102038e367901024f02039134620a0482080201920104814b020198030484790202a06b060481240201ba0802090201be08022f03023670010482170202bf6f01022d0103e0a1960304831d0302bb75060483700202a2900804817c0202a49e050485010202a6b2040482030202aa80040481720202abb30304843c0301ba0204833b0203aca677010481120206ae9f613566730504841e0202afa001020a0302a979080484060202b1a1010483730203b2a46a070482460301ba020484580203b39b610804834a0202b6a60304813b0202bfae0404837c0103e185930304845f02038889780a04826802028a85070484620301b90304826c020298a3070483270203af8962050484620202b5b7070481170202b8970602190202bd8f0a0482620103e2848f04021b0203afa861020484010301b70704824a0103e3828f05048214020284a50304812f0202909e0904824d020292b907026302049ba0336604020602029c8e0204840d0202ad860202750302a16a0802180202ae880602040202b480010483150202b7b1090483780202bdbf070482050103e480ab06020f0202889605024f020293b9030483310204968fdc93080483110202a295010484150202a69a0804844d0202a78e0a02080202aa9b0a04825f0203b2b8670402720203b5b764060482550204babacf87070481270202bd9b010481780206be9a6878696805021e0103e58bba0304821202049eab6a630a04827702029faf08024d0202a2b50a02400202a3af0704827c0203a4bd6f0504840c0202ad9d030485010202b1be040483780202b5b9060484500103e689b10404844602028abc0704811902038e98690802320203968b35090482680203979971010483060202b6a4030484050301be0a04833e0103e780a601048171020282be0304824d020286b105021b02028f960a048266020291be0804831c020299900204815502029ea70702400202a0ba040481410204a69e3870030481220202a9800602310202afb8020482170203b1af6d0802140203b5a06a0702740104e88c9a6c06048426020295bc05048326020296af0304846b02059cad72d4aa060484780205baa97364680404837b0103e983840104843902029a8a010481490203a1ac770504812c0301ba050483410202af8c0302620202b1af0302500103ea8fa60a023e020297b50904812e020298a90704825702039ea76b0304847f0202a59e080481460202a68e080482590204a9b1c6a8010481350203b38d75040482750203b89e6f0a0484030103eb828f0704824e020384837109048178020397b6690104821a02039e9e330704837f0203a68b73030484440203b980320804822c0103ec8fa80204814302039588760a04826902029bb80a024e0203afb6630802710203b4a268060483000103ed8cb50104811602029982060481550104ee8085760304834502028a870904845702028f8b04027602039da470030483040202a1a20504813c0202a8ae0504837f0202af9d0402570205b1b773d8b4080482120202bd880904832c0202be930104827b0104ef88ae680704835d0205a8ab63c2be06022e0203aaa16c080481090204adb779660804823f0202b8ae080484220203bb9165030481340106f08798b1636a0604824f0203908ea80404826203029f880402530303b4ad740a04833302039184b6090484650302acb3080483340302b1b703048272020a9281a23578f098b1893001048210030291a50404816803029d8f070483200302afa5080484440302b49f020481010303bd833603026a020393839a07024c0304a3ad6e300504842d0303abb16d0502660302adae0904830e02039481a406048164030386a16c070483530302b2a8050484320302bfb9080483170204958eb8720304832b0302b1ba090481200302babe05048209020496888b6708048358030293b4050483400304b4927a6f050483770204978b93320104810a03048fb9c7890704822803029ba702022a0302a39d060484490302a4be0a0484530302adaa0a026b0302af92040483700302b9bc0404821b02049884b56404048352030486b1716f0904827a030296b80904811d03049d9e797a060483390302a5a00a04844a0303b5856d0a04822e0302bcbd040483310303bd91740704845102039983a20a04816503039d8a330a02140303b9826b0404814e02069a8b8438687403026b0302a599010481740302a6ac0704840f0303b6896d0404831a0302b785010484370302bfac08027d02059b86b770610404845203028fbd020483550303a0be75090483620302a295040482390302b6970404813002039c97bb0a04841103059d8976c2be0604824e0302afbc05023c02039d87b40504825903028daf03048172030292be040482310302a0ab0502290303b2a16b03025d02039e929d050483040302a69f060484150302aa8607025502049f9f8b66020483160302a3be060481120203a8afad0904835e0204acb1af640204845b0204b282a47a040481610203baa68a010482490204bb9f8366060483130203bfa48f0704817c0104f18191920802220204828cad360a0482730203859c9a050481670204888eb23408025f020492ba9c3202026502049bb0bf7008021f02039f94a60104835c0203a6b496030482760203a98c960504824e0203acb7b8030483240203afa0b703023d0206b3a38c683972060483340203bbaaad0902070105f282848f790804833a020384b79f0a048170020590a98c616a0804843b02049a92be730904822f02039da18b080482530203a28f8f06048309070d06070706070807070807080b0707070b09070b07070906070f0b07080607090709070708070708080706070b070707080907070808070608080707080707070808070a0806060707070b0b07070707080807070b0d0709060b0708070707080708090808070808090b0707070707080609070d07070709060806070707070707070708070c0c08090708090a07080c070a0608070707090807090707070607070b07070a0c08070809080b08090808080808070807090a07070807070706090709070c070707070809070708060608070908080808080807090c07080809070908080909080708090807080809070908080709080707070808080807080a0808070808090a080b090a070708090808080908080909080709080708080807080a070808080a08080b0b0908090707070808080908080a0909090909090909090907080909080a0807090808070b08080a0a090a08090c090709090808100808080808080a0808090908080a08080a080a0a0a0708080708080a0a080a080908090908090b08080908070b08090808090b0709080807080908070a08090a0a090a09090a0909090909090909080c080b090b0a09'); INSERT INTO t1_data VALUES(274877906951,X'000002020630f2abab907a060481130204b381af77040481790203bea6a6070484250108f380b5a33633737701048229020383be9f0404837102048495bf73070481060204938c9a6e0904823502039eb39201022302049fbb9f6c0a0481500204a3909e620404837d0204a9ac9a75020483110203bd8c850a048111030293ad0a048247030294b9040483550203bea4ac0702220105f483b5ab66030482440302bda306048141020584b2bb643804048142020586b1a8677a0204831d0205878c916c770804821f02038da1bf0704824302038f81bd0304825102039e91b20302420203b29b9403021f0203b3a1b10704825a0203b5afb4040481210204b98da0780a02060104f582b1b00404811002038f9fbc010482200302b8a406048419020394b7b80404834c02039bb5b005022b0203aa88b9060481390203aba48f0604842a0205af969438680602360203b88d8903026c0104f68386ad0904846702049aae8f79030483520203a8989a0604836c0203b18cb4070482260203b9a98d050483730203bebc870104824c0104f78283840804816703028db20302600303a8b46106020b020389b2a80104835002048e809339010481190205929193d0b409048253020393aebc0204816202059787b96f690704817202079b949dc78934620404817f02039db28b020483750205a288a7c7a3080482780203a5948d0204811a040b0a090e090a0a080a0a0a090808080b080b0b0b090908080909090a0908090809090a080a0a090909090a0708090a0b090b0d090b'); CREATE TABLE IF NOT EXISTS 't1_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID; INSERT INTO t1_idx VALUES(2,X'',2); |
︙ | ︙ | |||
6972 6973 6974 6975 6976 6977 6978 | INSERT INTO t2 VALUES('integrity-check'); PRAGMA writable_schema=OFF; COMMIT; } {} do_catchsql_test 51.1 { SELECT max(rowid)==0 FROM t1('e*'); | | | 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 | INSERT INTO t2 VALUES('integrity-check'); PRAGMA writable_schema=OFF; COMMIT; } {} do_catchsql_test 51.1 { SELECT max(rowid)==0 FROM t1('e*'); } {/.*fts5: corrupt.*/} #-------------------------------------------------------------------------- reset_db do_test 52.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 40960 pagesize 4096 filename crash-2b92f77ddfe191.db |
︙ | ︙ | |||
8748 8749 8750 8751 8752 8753 8754 | | 4048: 00 00 00 00 00 00 5d 03 00 00 00 00 00 00 00 00 ......]......... | end crash-c77b90b929dc92.db }]} {} do_catchsql_test 60.2 { SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*e' | | | 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 | | 4048: 00 00 00 00 00 00 5d 03 00 00 00 00 00 00 00 00 ......]......... | end crash-c77b90b929dc92.db }]} {} do_catchsql_test 60.2 { SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*e' } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- do_test 61.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb | size 28672 pagesize 4096 filename crash-e5fa281edabddf.db |
︙ | ︙ | |||
9769 9770 9771 9772 9773 9774 9775 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-37cecb4e784e9f.db }]} {} do_catchsql_test 66.1 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end crash-37cecb4e784e9f.db }]} {} do_catchsql_test 66.1 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- # reset_db do_test 67.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
10319 10320 10321 10322 10323 10324 10325 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 00 00 00 00 00 00 ity-check....... | end crash-31c462b8b665d0.db }]} {} do_catchsql_test 69.2 { SELECT * FROM t1 WHERE a MATCH 'fx*' | | | 10318 10319 10320 10321 10322 10323 10324 10325 10326 10327 10328 10329 10330 10331 10332 | | 4064: 69 74 79 2d 63 68 65 63 6b 09 00 00 00 00 00 00 ity-check....... | end crash-31c462b8b665d0.db }]} {} do_catchsql_test 69.2 { SELECT * FROM t1 WHERE a MATCH 'fx*' } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 70.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ | |||
10502 10503 10504 10505 10506 10507 10508 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end sql025294.txt.db }]} {} do_catchsql_test 71.2 { INSERT INTO t1(t1) VALUES('integrity-check'); | | | 10501 10502 10503 10504 10505 10506 10507 10508 10509 10510 10511 10512 10513 10514 10515 | | 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c | 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize | end sql025294.txt.db }]} {} do_catchsql_test 71.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 72.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ | |||
10629 10630 10631 10632 10633 10634 10635 | | end crash-77b86d070d0ac6.db }]} {} do_catchsql_test 72.1 { INSERT INTO ttt(ttt) VALUES('integrity-check'); } {1 {database disk image is malformed}} | | | | 10628 10629 10630 10631 10632 10633 10634 10635 10636 10637 10638 10639 10640 10641 10642 10643 10644 | | end crash-77b86d070d0ac6.db }]} {} do_catchsql_test 72.1 { INSERT INTO ttt(ttt) VALUES('integrity-check'); } {1 {database disk image is malformed}} do_catchsql_test 72.2 { SELECT 1 FROM ttt('e* NOT ee*'); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 73.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ | |||
10757 10758 10759 10760 10761 10762 10763 | | 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. | end crash-b02ca2cc4d7dda.db }]} {} do_catchsql_test 73.1 { SELECT snippet(ttt,ttt, NOT 54 ), * FROM ttt('e* NOT ee*e* NOT ee* NOT ee*e* NOT e*') ; | | | 10756 10757 10758 10759 10760 10761 10762 10763 10764 10765 10766 10767 10768 10769 10770 | | 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. | end crash-b02ca2cc4d7dda.db }]} {} do_catchsql_test 73.1 { SELECT snippet(ttt,ttt, NOT 54 ), * FROM ttt('e* NOT ee*e* NOT ee* NOT ee*e* NOT e*') ; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 74.0 { sqlite3 db {} sqlite3_fts5_register_matchinfo db db deserialize [decode_hexdb { |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt5.test.
︙ | ︙ | |||
233 234 235 236 237 238 239 | | 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................ | end crash-0f47112aa7520c.db }] } {} do_catchsql_test 1.1 { SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC; | | | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | | 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................ | end crash-0f47112aa7520c.db }] } {} do_catchsql_test 1.1 { SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- # reset_db do_test 2.0 { sqlite3 db {} db deserialize [decode_hexdb { |
︙ | ︙ | |||
446 447 448 449 450 451 452 | | 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................ | end sql047467.txt.db }]} {} do_catchsql_test 2.1 { SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC; | | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | | 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ | 4080: 00 00 03 03 02 01 03 03 02 02 01 00 00 00 00 00 ................ | end sql047467.txt.db }]} {} do_catchsql_test 2.1 { SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 3.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ | |||
565 566 567 568 569 570 571 | | 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ | 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. | end crash-c69fcaceff1e50.db }]} {} do_catchsql_test 3.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T'; | | | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | | 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ | 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. | end crash-c69fcaceff1e50.db }]} {} do_catchsql_test 3.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T'; } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 4.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ | |||
874 875 876 877 878 879 880 | }]} {} do_execsql_test 5.1 { INSERT INTO t1(t1,rank) VALUES('secure-delete',1); } do_catchsql_test 5.4 { UPDATE t1 SET content=randomblob(500); | | | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | }]} {} do_execsql_test 5.1 { INSERT INTO t1(t1,rank) VALUES('secure-delete',1); } do_catchsql_test 5.4 { UPDATE t1 SET content=randomblob(500); } {/.*fts5: corrupt.*/} #------------------------------------------------------------------------- reset_db do_test 6.0 { sqlite3 db {} db deserialize [decode_hexdb { .open --hexdb |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt7.test.
︙ | ︙ | |||
119 120 121 122 123 124 125 | UPDATE t1_data SET block=X'0000001A04306162630102025501620202020101640206030303040806' WHERE id>10 } do_catchsql_test 2.3 { DELETE FROM t1 WHERE rowid = 1 | | | 119 120 121 122 123 124 125 126 127 128 | UPDATE t1_data SET block=X'0000001A04306162630102025501620202020101640206030303040806' WHERE id>10 } do_catchsql_test 2.3 { DELETE FROM t1 WHERE rowid = 1 } {/.*fts5: corrupt.*/} finish_test |
Changes to ext/fts5/test/fts5corrupt8.test.
︙ | ︙ | |||
28 29 30 31 32 33 34 | } db close sqlite3 db test.db do_catchsql_test 1.2 { SELECT * FROM t1 | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | } db close sqlite3 db test.db do_catchsql_test 1.2 { SELECT * FROM t1 } {1 {fts5: corrupt structure record for table "t1"}} do_catchsql_test 1.3 { DROP TABLE t1 } {0 {}} do_execsql_test 1.4 { SELECT * FROM sqlite_schema } |
︙ | ︙ |
Changes to ext/fts5/test/fts5faultI.test.
︙ | ︙ | |||
320 321 322 323 324 325 326 327 328 329 | execsql { SELECT 123 } faultsim_test_result \ {1 {FOREIGN KEY constraint failed}} \ {1 {out of memory}} \ {1 {constraint failed}} } } finish_test | > > > > > > > > > > > > > > > > > > > > | 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | execsql { SELECT 123 } faultsim_test_result \ {1 {FOREIGN KEY constraint failed}} \ {1 {out of memory}} \ {1 {constraint failed}} } } #------------------------------------------------------------------------- reset_db do_execsql_test 13.0 { CREATE VIRTUAL TABLE t1 USING fts5(a, b); INSERT INTO t1 VALUES('abc def', X'123456'); } faultsim_save_and_close do_faultsim_test 13 -faults oom* -prep { faultsim_restore_and_reopen } -body { execsql { UPDATE t1 SET a='def abc' } } -test { faultsim_test_result {0 {}} } finish_test |
Changes to ext/fts5/test/fts5rebuild.test.
︙ | ︙ | |||
42 43 44 45 46 47 48 | sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.5 { DELETE FROM f1_data; } {} do_catchsql_test 1.6 { INSERT INTO f1(f1) VALUES('integrity-check'); | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.5 { DELETE FROM f1_data; } {} do_catchsql_test 1.6 { INSERT INTO f1(f1) VALUES('integrity-check'); } {/.*fts5: corrupt.*/} do_execsql_test 1.7 { INSERT INTO f1(f1) VALUES('rebuild'); INSERT INTO f1(f1) VALUES('integrity-check'); } {} |
︙ | ︙ |
Changes to ext/fts5/test/fts5unicode4.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 | do_execsql_test 1.0 { CREATE VIRTUAL TABLE sss USING fts5(a, prefix=3); } do_execsql_test 1.1 { INSERT INTO sss VALUES('まりや'); } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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 | do_execsql_test 1.0 { CREATE VIRTUAL TABLE sss USING fts5(a, prefix=3); } do_execsql_test 1.1 { INSERT INTO sss VALUES('まりや'); } foreach {tn enc tok} { 1 utf-8 ascii 2 utf-16 ascii 3 utf-8 unicode61 4 utf-16 unicode61 } { reset_db do_execsql_test 1.$tn.0 " PRAGMA encoding = '$enc'; CREATE VIRTUAL TABLE vt2 USING fts5(c0, c1, tokenize=$tok); " do_execsql_test 1.$tn.1 { INSERT INTO vt2(c0, c1) VALUES ('bhal', x'17db'); } do_execsql_test 1.$tn.2 { UPDATE vt2 SET c0='bhal'; } do_execsql_test 1.$tn.3 { INSERT INTO vt2(vt2) VALUES('integrity-check') } do_execsql_test 1.$tn.4 { SELECT quote(c1) FROM vt2 } {X'17DB'} } finish_test |
Changes to ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java.
︙ | ︙ | |||
116 117 118 119 120 121 122 | To be called from the implementation's xStep() method, as well as the xValue() and xInverse() methods of the {@link WindowFunction} subclass, to fetch the current per-call UDF state. On the first call to this method for any given sqlite3_context argument, the context is set to the given initial value. On all other calls, the 2nd argument is ignored. | | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | To be called from the implementation's xStep() method, as well as the xValue() and xInverse() methods of the {@link WindowFunction} subclass, to fetch the current per-call UDF state. On the first call to this method for any given sqlite3_context argument, the context is set to the given initial value. On all other calls, the 2nd argument is ignored. @see AggregateFunction.PerContextState#getAggregateState */ protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){ return map.getAggregateState(cx, initialValue); } /** To be called from the implementation's xFinal() method to fetch the final state of the UDF and remove its mapping. see AggregateFunction.PerContextState#takeAggregateState */ protected final T takeAggregateState(sqlite3_context cx){ return map.takeAggregateState(cx); } } |
Changes to ext/misc/fileio.c.
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | ** ** name: Path to file or directory (text value). ** mode: Value of stat.st_mode for directory entry (an integer). ** mtime: Value of stat.st_mtime for directory entry (an integer). ** data: For a regular file, a blob containing the file data. For a ** symlink, a text value containing the text of the link. For a ** directory, NULL. ** ** If a non-NULL value is specified for the optional $dir parameter and ** $path is a relative path, then $path is interpreted relative to $dir. ** And the paths returned in the "name" column of the table are also ** relative to directory $dir. ** ** Notes on building this extension for Windows: | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | ** ** name: Path to file or directory (text value). ** mode: Value of stat.st_mode for directory entry (an integer). ** mtime: Value of stat.st_mtime for directory entry (an integer). ** data: For a regular file, a blob containing the file data. For a ** symlink, a text value containing the text of the link. For a ** directory, NULL. ** level: Directory hierarchy level. Topmost is 1. ** ** If a non-NULL value is specified for the optional $dir parameter and ** $path is a relative path, then $path is interpreted relative to $dir. ** And the paths returned in the "name" column of the table are also ** relative to directory $dir. ** ** Notes on building this extension for Windows: |
︙ | ︙ | |||
88 89 90 91 92 93 94 95 | #include <sys/stat.h> #include <fcntl.h> #if !defined(_WIN32) && !defined(WIN32) # include <unistd.h> # include <dirent.h> # include <utime.h> # include <sys/time.h> #else | > | < < < | | | > > | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | #include <sys/stat.h> #include <fcntl.h> #if !defined(_WIN32) && !defined(WIN32) # include <unistd.h> # include <dirent.h> # include <utime.h> # include <sys/time.h> # define STRUCT_STAT struct stat #else # include "windirent.h" # include <direct.h> # define STRUCT_STAT struct _stat # define chmod(path,mode) fileio_chmod(path,mode) # define mkdir(path,mode) fileio_mkdir(path) #endif #include <time.h> #include <errno.h> /* When used as part of the CLI, the sqlite3_stdio.h module will have ** been included before this one. In that case use the sqlite3_stdio.h ** #defines. If not, create our own for fopen(). */ #ifndef _SQLITE3_STDIO_H_ # define sqlite3_fopen fopen #endif /* ** Structure of the fsdir() table-valued function */ /* 0 1 2 3 4 5 6 */ #define FSDIR_SCHEMA "(name,mode,mtime,data,level,path HIDDEN,dir HIDDEN)" #define FSDIR_COLUMN_NAME 0 /* Name of the file */ #define FSDIR_COLUMN_MODE 1 /* Access mode */ #define FSDIR_COLUMN_MTIME 2 /* Last modification time */ #define FSDIR_COLUMN_DATA 3 /* File content */ #define FSDIR_COLUMN_LEVEL 4 /* Level. Topmost is 1 */ #define FSDIR_COLUMN_PATH 5 /* Path to top of search */ #define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */ /* ** UTF8 chmod() function for Windows */ #if defined(_WIN32) || defined(WIN32) static int fileio_chmod(const char *zPath, int pmode){ sqlite3_int64 sz = strlen(zPath); |
︙ | ︙ | |||
285 286 287 288 289 290 291 | /* ** This function attempts to normalize the time values found in the stat() ** buffer to UTC. This is necessary on Win32, where the runtime library ** appears to return these values as local times. */ static void statTimesToUtc( const char *zPath, | | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | /* ** This function attempts to normalize the time values found in the stat() ** buffer to UTC. This is necessary on Win32, where the runtime library ** appears to return these values as local times. */ static void statTimesToUtc( const char *zPath, STRUCT_STAT *pStatBuf ){ HANDLE hFindFile; WIN32_FIND_DATAW fd; LPWSTR zUnicodeName; extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); if( zUnicodeName ){ |
︙ | ︙ | |||
313 314 315 316 317 318 319 | /* ** This function is used in place of stat(). On Windows, special handling ** is required in order for the included time to be returned as UTC. On all ** other systems, this function simply calls stat(). */ static int fileStat( const char *zPath, | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | /* ** This function is used in place of stat(). On Windows, special handling ** is required in order for the included time to be returned as UTC. On all ** other systems, this function simply calls stat(). */ static int fileStat( const char *zPath, STRUCT_STAT *pStatBuf ){ #if defined(_WIN32) sqlite3_int64 sz = strlen(zPath); wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) ); int rc; if( b1==0 ) return 1; sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz); |
︙ | ︙ | |||
337 338 339 340 341 342 343 | /* ** This function is used in place of lstat(). On Windows, special handling ** is required in order for the included time to be returned as UTC. On all ** other systems, this function simply calls lstat(). */ static int fileLinkStat( const char *zPath, | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | /* ** This function is used in place of lstat(). On Windows, special handling ** is required in order for the included time to be returned as UTC. On all ** other systems, this function simply calls lstat(). */ static int fileLinkStat( const char *zPath, STRUCT_STAT *pStatBuf ){ #if defined(_WIN32) return fileStat(zPath, pStatBuf); #else return lstat(zPath, pStatBuf); #endif } |
︙ | ︙ | |||
370 371 372 373 374 375 376 | if( zCopy==0 ){ rc = SQLITE_NOMEM; }else{ int nCopy = (int)strlen(zCopy); int i = 1; while( rc==SQLITE_OK ){ | | | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | if( zCopy==0 ){ rc = SQLITE_NOMEM; }else{ int nCopy = (int)strlen(zCopy); int i = 1; while( rc==SQLITE_OK ){ STRUCT_STAT sStat; int rc2; for(; zCopy[i]!='/' && i<nCopy; i++); if( i==nCopy ) break; zCopy[i] = '\0'; rc2 = fileStat(zCopy, &sStat); |
︙ | ︙ | |||
420 421 422 423 424 425 426 | { if( S_ISDIR(mode) ){ if( mkdir(zFile, mode) ){ /* The mkdir() call to create the directory failed. This might not ** be an error though - if there is already a directory at the same ** path and either the permissions already match or can be changed ** to do so using chmod(), it is not an error. */ | | | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | { if( S_ISDIR(mode) ){ if( mkdir(zFile, mode) ){ /* The mkdir() call to create the directory failed. This might not ** be an error though - if there is already a directory at the same ** path and either the permissions already match or can be changed ** to do so using chmod(), it is not an error. */ STRUCT_STAT sStat; if( errno!=EEXIST || 0!=fileStat(zFile, &sStat) || !S_ISDIR(sStat.st_mode) || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777)) ){ return 1; } |
︙ | ︙ | |||
616 617 618 619 620 621 622 623 624 625 626 627 628 | char *zDir; /* Name of directory (nul-terminated) */ }; struct fsdir_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ int nLvl; /* Number of entries in aLvl[] array */ int iLvl; /* Index of current entry */ FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ const char *zBase; int nBase; | > | | 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | char *zDir; /* Name of directory (nul-terminated) */ }; struct fsdir_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ int nLvl; /* Number of entries in aLvl[] array */ int mxLvl; /* Maximum level */ int iLvl; /* Index of current entry */ FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ const char *zBase; int nBase; STRUCT_STAT sStat; /* Current lstat() results */ char *zPath; /* Path to current entry */ sqlite3_int64 iRowid; /* Current rowid */ }; typedef struct fsdir_tab fsdir_tab; struct fsdir_tab { sqlite3_vtab base; /* Base class - must be first */ |
︙ | ︙ | |||
734 735 736 737 738 739 740 | ** Advance an fsdir_cursor to its next row of output. */ static int fsdirNext(sqlite3_vtab_cursor *cur){ fsdir_cursor *pCur = (fsdir_cursor*)cur; mode_t m = pCur->sStat.st_mode; pCur->iRowid++; | | | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | ** Advance an fsdir_cursor to its next row of output. */ static int fsdirNext(sqlite3_vtab_cursor *cur){ fsdir_cursor *pCur = (fsdir_cursor*)cur; mode_t m = pCur->sStat.st_mode; pCur->iRowid++; if( S_ISDIR(m) && pCur->iLvl+3<pCur->mxLvl ){ /* Descend into this directory */ int iNew = pCur->iLvl + 1; FsdirLevel *pLvl; if( iNew>=pCur->nLvl ){ int nNew = iNew+1; sqlite3_int64 nByte = nNew*sizeof(FsdirLevel); FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte); |
︙ | ︙ | |||
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); if( aBuf!=aStatic ) sqlite3_free(aBuf); #endif }else{ readFileContents(ctx, pCur->zPath); } } case FSDIR_COLUMN_PATH: default: { /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ** always return their values as NULL */ break; } } | > > > > | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); if( aBuf!=aStatic ) sqlite3_free(aBuf); #endif }else{ readFileContents(ctx, pCur->zPath); } break; } case FSDIR_COLUMN_LEVEL: sqlite3_result_int(ctx, pCur->iLvl+2); break; case FSDIR_COLUMN_PATH: default: { /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ** always return their values as NULL */ break; } } |
︙ | ︙ | |||
876 877 878 879 880 881 882 | fsdir_cursor *pCur = (fsdir_cursor*)cur; return (pCur->zPath==0); } /* ** xFilter callback. ** | | | > > > > | > > | | > > > > > > > > | 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | fsdir_cursor *pCur = (fsdir_cursor*)cur; return (pCur->zPath==0); } /* ** xFilter callback. ** ** idxNum bit Meaning ** 0x01 PATH=N ** 0x02 DIR=N ** 0x04 LEVEL<N ** 0x08 LEVEL<=N */ static int fsdirFilter( sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ const char *zDir = 0; fsdir_cursor *pCur = (fsdir_cursor*)cur; int i; (void)idxStr; fsdirResetCursor(pCur); if( idxNum==0 ){ fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); return SQLITE_ERROR; } assert( (idxNum & 0x01)!=0 && argc>0 ); zDir = (const char*)sqlite3_value_text(argv[0]); if( zDir==0 ){ fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument"); return SQLITE_ERROR; } i = 1; if( (idxNum & 0x02)!=0 ){ assert( argc>i ); pCur->zBase = (const char*)sqlite3_value_text(argv[i++]); } if( (idxNum & 0x0c)!=0 ){ assert( argc>i ); pCur->mxLvl = sqlite3_value_int(argv[i++]); if( idxNum & 0x08 ) pCur->mxLvl++; if( pCur->mxLvl<=0 ) pCur->mxLvl = 1000000000; }else{ pCur->mxLvl = 1000000000; } if( pCur->zBase ){ pCur->nBase = (int)strlen(pCur->zBase)+1; pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir); }else{ pCur->zPath = sqlite3_mprintf("%s", zDir); } |
︙ | ︙ | |||
930 931 932 933 934 935 936 | ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. ** ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** | | | | > > > > | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | > > | | | 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 | ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. ** ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** ** The query plan is represented by bits in idxNum: ** ** 0x01 The path value is supplied by argv[0] ** 0x02 dir is in argv[1] ** 0x04 maxdepth is in argv[1] or [2] */ static int fsdirBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop over constraints */ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ int idxLevel = -1; /* Index in pIdxInfo->aConstraint of LEVEL< or <= */ int idxLevelEQ = 0; /* 0x08 for LEVEL<= or LEVEL=. 0x04 for LEVEL< */ int omitLevel = 0; /* omit the LEVEL constraint */ int seenPath = 0; /* True if an unusable PATH= constraint is seen */ int seenDir = 0; /* True if an unusable DIR= constraint is seen */ const struct sqlite3_index_constraint *pConstraint; (void)tab; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ switch( pConstraint->iColumn ){ case FSDIR_COLUMN_PATH: { if( pConstraint->usable ){ idxPath = i; seenPath = 0; }else if( idxPath<0 ){ seenPath = 1; } break; } case FSDIR_COLUMN_DIR: { if( pConstraint->usable ){ idxDir = i; seenDir = 0; }else if( idxDir<0 ){ seenDir = 1; } break; } case FSDIR_COLUMN_LEVEL: { if( pConstraint->usable && idxLevel<0 ){ idxLevel = i; idxLevelEQ = 0x08; omitLevel = 0; } break; } } }else if( pConstraint->iColumn==FSDIR_COLUMN_LEVEL && pConstraint->usable && idxLevel<0 ){ if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){ idxLevel = i; idxLevelEQ = 0x08; omitLevel = 1; }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){ idxLevel = i; idxLevelEQ = 0x04; omitLevel = 1; } } } if( seenPath || seenDir ){ /* If input parameters are unusable, disallow this plan */ return SQLITE_CONSTRAINT; } if( idxPath<0 ){ pIdxInfo->idxNum = 0; /* The pIdxInfo->estimatedCost should have been initialized to a huge ** number. Leave it unchanged. */ pIdxInfo->estimatedRows = 0x7fffffff; }else{ pIdxInfo->aConstraintUsage[idxPath].omit = 1; pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; pIdxInfo->idxNum = 0x01; pIdxInfo->estimatedCost = 1.0e9; i = 2; if( idxDir>=0 ){ pIdxInfo->aConstraintUsage[idxDir].omit = 1; pIdxInfo->aConstraintUsage[idxDir].argvIndex = i++; pIdxInfo->idxNum |= 0x02; pIdxInfo->estimatedCost /= 1.0e4; } if( idxLevel>=0 ){ pIdxInfo->aConstraintUsage[idxLevel].omit = omitLevel; pIdxInfo->aConstraintUsage[idxLevel].argvIndex = i++; pIdxInfo->idxNum |= idxLevelEQ; pIdxInfo->estimatedCost /= 1.0e4; } } return SQLITE_OK; } /* |
︙ | ︙ |
Added ext/misc/windirent.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 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 36 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | /* ** 2025-06-05 ** ** 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. ** ************************************************************************* ** ** An implementation of opendir(), readdir(), and closedir() for Windows, ** based on the FindFirstFile(), FindNextFile(), and FindClose() APIs ** of Win32. ** ** #include this file inside any C-code module that needs to use ** opendir()/readdir()/closedir(). This file is a no-op on non-Windows ** machines. On Windows, static functions are defined that implement ** those standard interfaces. */ #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) #define SQLITE_WINDIRENT_H #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <windows.h> #include <io.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #ifndef FILENAME_MAX # define FILENAME_MAX (260) #endif #ifndef S_ISREG #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISLNK #define S_ISLNK(m) (0) #endif typedef unsigned short mode_t; /* The dirent object for Windows is abbreviated. The only field really ** usable by applications is d_name[]. */ struct dirent { int d_ino; /* Inode number (synthesized) */ unsigned d_attributes; /* File attributes */ char d_name[FILENAME_MAX]; /* Null-terminated filename */ }; /* The internals of DIR are opaque according to standards. So it ** does not matter what we put here. */ typedef struct DIR DIR; struct DIR { intptr_t d_handle; /* Handle for findfirst()/findnext() */ struct dirent cur; /* Current entry */ }; /* Ignore hidden and system files */ #define WindowsFileToIgnore(a) \ ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) /* ** Close a previously opened directory */ static int closedir(DIR *pDir){ int rc = 0; if( pDir==0 ){ return EINVAL; } if( pDir->d_handle!=0 && pDir->d_handle!=(-1) ){ rc = _findclose(pDir->d_handle); } sqlite3_free(pDir); return rc; } /* ** Open a new directory. The directory name should be UTF-8 encoded. ** appropriate translations happen automatically. */ static DIR *opendir(const char *zDirName){ DIR *pDir; wchar_t *b1; sqlite3_int64 sz; struct _wfinddata_t data; pDir = sqlite3_malloc64( sizeof(DIR) ); if( pDir==0 ) return 0; memset(pDir, 0, sizeof(DIR)); memset(&data, 0, sizeof(data)); sz = strlen(zDirName); b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) ); if( b1==0 ){ closedir(pDir); return NULL; } sz = MultiByteToWideChar(CP_UTF8, 0, zDirName, sz, b1, sz); b1[sz++] = '\\'; b1[sz++] = '*'; b1[sz] = 0; if( sz+1>sizeof(data.name)/sizeof(data.name[0]) ){ closedir(pDir); sqlite3_free(b1); return NULL; } memcpy(data.name, b1, (sz+1)*sizeof(b1[0])); sqlite3_free(b1); pDir->d_handle = _wfindfirst(data.name, &data); if( pDir->d_handle<0 ){ closedir(pDir); return NULL; } while( WindowsFileToIgnore(data) ){ memset(&data, 0, sizeof(data)); if( _wfindnext(pDir->d_handle, &data)==-1 ){ closedir(pDir); return NULL; } } pDir->cur.d_ino = 0; pDir->cur.d_attributes = data.attrib; WideCharToMultiByte(CP_UTF8, 0, data.name, -1, pDir->cur.d_name, FILENAME_MAX, 0, 0); return pDir; } /* ** Read the next entry from a directory. ** ** The returned struct-dirent object is managed by DIR. It is only ** valid until the next readdir() or closedir() call. Only the ** d_name[] field is meaningful. The d_name[] value has been ** translated into UTF8. */ static struct dirent *readdir(DIR *pDir){ struct _wfinddata_t data; if( pDir==0 ) return 0; if( (pDir->cur.d_ino++)==0 ){ return &pDir->cur; } do{ memset(&data, 0, sizeof(data)); if( _wfindnext(pDir->d_handle, &data)==-1 ){ return NULL; } }while( WindowsFileToIgnore(data) ); pDir->cur.d_attributes = data.attrib; WideCharToMultiByte(CP_UTF8, 0, data.name, -1, pDir->cur.d_name, FILENAME_MAX, 0, 0); return &pDir->cur; } #endif /* defined(_WIN32) && defined(_MSC_VER) */ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else #include "sqlite3.h" #endif int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */ /* ** If building separately, we will need some setup that is normally ** found in sqliteInt.h */ #if !defined(SQLITE_AMALGAMATION) #include "sqlite3rtree.h" typedef sqlite3_int64 i64; | > > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else #include "sqlite3.h" #endif int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */ #include <stddef.h> /* ** If building separately, we will need some setup that is normally ** found in sqliteInt.h */ #if !defined(SQLITE_AMALGAMATION) #include "sqlite3rtree.h" typedef sqlite3_int64 i64; |
︙ | ︙ | |||
91 92 93 94 95 96 97 | # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #ifndef offsetof | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #ifndef offsetof # define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY #else # define FLEXARRAY 1 #endif #endif /* !defined(SQLITE_AMALGAMATION) */ |
︙ | ︙ |
Changes to ext/wasm/GNUmakefile.
︙ | ︙ | |||
256 257 258 259 260 261 262 | -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_MATH_FUNCTIONS \ -DSQLITE_ENABLE_OFFSET_SQL_FUNC \ -DSQLITE_ENABLE_PREUPDATE_HOOK \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_SESSION \ -DSQLITE_ENABLE_STMTVTAB \ | | > | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_MATH_FUNCTIONS \ -DSQLITE_ENABLE_OFFSET_SQL_FUNC \ -DSQLITE_ENABLE_PREUPDATE_HOOK \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_SESSION \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \ -DSQLITE_ENABLE_COLUMN_METADATA ifeq (0,$(wasm-bare-bones)) # The so-called canonical build is full-featured: SQLITE_OPT := \ $(SQLITE_OPT.common) \ $(SQLITE_OPT.full-featured) else |
︙ | ︙ | |||
406 407 408 409 410 411 412 | # # Note that the SQLITE_... build flags used here have NO EFFECT on the # JS/WASM build. They are solely for use with $(bin.c-pp) itself. # # -D... flags which should be included in all invocations should be # appended to $(SQLITE.CALL.C-PP.FILTER.global). bin.c-pp := ./c-pp | | | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | # # Note that the SQLITE_... build flags used here have NO EFFECT on the # JS/WASM build. They are solely for use with $(bin.c-pp) itself. # # -D... flags which should be included in all invocations should be # appended to $(SQLITE.CALL.C-PP.FILTER.global). bin.c-pp := ./c-pp $(bin.c-pp): c-pp.c $(sqlite3.c) # $(MAKEFILE) $(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \ -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \ -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=3 DISTCLEAN_FILES += $(bin.c-pp) SQLITE.CALL.C-PP.FILTER.global ?= ifeq (1,$(SQLITE_C_IS_SEE)) |
︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | ######################################################################## # emcc flags for .c/.o/.wasm/.js. emcc.flags := ifeq (1,$(emcc.verbose)) emcc.flags += -v # -v is _very_ loud but also informative about what it's doing endif ######################################################################## # emcc flags for .c/.o. emcc.cflags := emcc.cflags += -std=c99 -fPIC # -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily # for variadic macros and snprintf() to implement # sqlite3_wasm_enum_json(). emcc.cflags += -I. -I$(dir.top) ######################################################################## # emcc flags specific to building .js/.wasm files... emcc.jsflags := -fPIC emcc.jsflags += --no-entry emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT) emcc.jsflags += -sMODULARIZE emcc.jsflags += -sDYNAMIC_EXECUTION=0 emcc.jsflags += -sNO_POLYFILL emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api) emcc.exportedRuntimeMethods := \ | > | | > | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 | ######################################################################## # emcc flags for .c/.o/.wasm/.js. emcc.flags := ifeq (1,$(emcc.verbose)) emcc.flags += -v # -v is _very_ loud but also informative about what it's doing endif ######################################################################## # emcc flags for .c/.o. emcc.cflags := emcc.cflags += -std=c99 -fPIC # -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily # for variadic macros and snprintf() to implement # sqlite3_wasm_enum_json(). emcc.cflags += -I. -I$(dir.top) ######################################################################## # emcc flags specific to building .js/.wasm files... emcc.jsflags := -fPIC emcc.jsflags += --no-entry emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT) emcc.jsflags += -sMODULARIZE emcc.jsflags += -sDYNAMIC_EXECUTION=0 emcc.jsflags += -sNO_POLYFILL emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api) emcc.exportedRuntimeMethods := \ -sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAP64,HEAPU64 # wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY # Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default emcc.jsflags += $(emcc.exportedRuntimeMethods) emcc.jsflags += -sUSE_CLOSURE_COMPILER=0 emcc.jsflags += -sIMPORTED_MEMORY ifeq (,$(filter -O0,$(emcc_opt))) emcc.assert ?= 0 else emcc.assert ?= 2 |
︙ | ︙ |
Changes to ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras.
1 | _sqlite3_create_window_function | > > > > > | | > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | _sqlite3_column_database_name _sqlite3_column_origin_name _sqlite3_column_table_name _sqlite3_create_module _sqlite3_create_module_v2 _sqlite3_create_window_function _sqlite3_declare_vtab _sqlite3_drop_modules _sqlite3_preupdate_blobwrite _sqlite3_preupdate_count _sqlite3_preupdate_depth _sqlite3_preupdate_hook _sqlite3_preupdate_new _sqlite3_preupdate_old _sqlite3_progress_handler _sqlite3_set_authorizer _sqlite3_vtab_collation _sqlite3_vtab_distinct _sqlite3_vtab_in _sqlite3_vtab_in_first _sqlite3_vtab_in_next _sqlite3_vtab_nochange _sqlite3_vtab_on_conflict _sqlite3_vtab_rhs_value _sqlite3changegroup_add _sqlite3changegroup_add_strm _sqlite3changegroup_delete _sqlite3changegroup_new _sqlite3changegroup_output _sqlite3changegroup_output_strm _sqlite3changeset_apply |
︙ | ︙ | |||
45 46 47 48 49 50 51 | _sqlite3session_indirect _sqlite3session_isempty _sqlite3session_memory_used _sqlite3session_object_config _sqlite3session_patchset _sqlite3session_patchset_strm _sqlite3session_table_filter | < < < < < < < < < < < < | 60 61 62 63 64 65 66 | _sqlite3session_indirect _sqlite3session_isempty _sqlite3session_memory_used _sqlite3session_object_config _sqlite3session_patchset _sqlite3session_patchset_strm _sqlite3session_table_filter |
Changes to ext/wasm/api/sqlite3-api-glue.c-pp.js.
︙ | ︙ | |||
16 17 18 19 20 21 22 | initializes the main API pieces so that the downstream components (e.g. sqlite3-api-oo1.js) have all of the infrastructure that they need. */ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ 'use strict'; const toss = (...args)=>{throw new Error(args.join(' '))}; | < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | initializes the main API pieces so that the downstream components (e.g. sqlite3-api-oo1.js) have all of the infrastructure that they need. */ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ 'use strict'; const toss = (...args)=>{throw new Error(args.join(' '))}; const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; globalThis.WhWasmUtilInstaller(wasm); delete globalThis.WhWasmUtilInstaller; if(0){ /** Please keep this block around as a maintenance reminder |
︙ | ︙ | |||
363 364 365 366 367 368 369 370 371 372 373 374 375 376 | } } }), "*"/*pUserData*/ ]] ); }/* sqlite3_set_authorizer() */ if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an optional feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } | > > > > > > > > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | } } }), "*"/*pUserData*/ ]] ); }/* sqlite3_set_authorizer() */ if( !!wasm.exports.sqlite3_column_origin_name ){ wasm.bindingSignatures.push( ["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"], ["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"], ["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"] ); } if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an optional feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-oo1.c-pp.js.
︙ | ︙ | |||
12 13 14 15 16 17 18 | *********************************************************************** This file contains the so-called OO #1 API wrapper for the sqlite3 WASM build. It requires that sqlite3-api-glue.js has already run and it installs its deliverable as globalThis.sqlite3.oo1. */ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ | < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | *********************************************************************** This file contains the so-called OO #1 API wrapper for the sqlite3 WASM build. It requires that sqlite3-api-glue.js has already run and it installs its deliverable as globalThis.sqlite3.oo1. */ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)}; const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; /* What follows is colloquially known as "OO API #1". It is a binding of the sqlite3 API which is designed to be run within the same thread (main or worker) as the one in which the sqlite3 WASM binding was initialized. This wrapper cannot use |
︙ | ︙ | |||
1057 1058 1059 1060 1061 1062 1063 | another connection, may invalidate the column count and names. */) ? 0 : 1; evalFirstResult = false; if(arg.cbArg || resultRows){ const cbArgCache = Object.create(null) /* 2nd arg for arg.cbArg, used by (at least) row-to-object converter */; | | | | | 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | another connection, may invalidate the column count and names. */) ? 0 : 1; evalFirstResult = false; if(arg.cbArg || resultRows){ const cbArgCache = Object.create(null) /* 2nd arg for arg.cbArg, used by (at least) row-to-object converter */; for( ; stmt.step(); __execLock.delete(stmt) ){ if(0===gotColNames++){ stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || [])); } __execLock.add(stmt); const row = arg.cbArg(stmt,cbArgCache); if(resultRows) resultRows.push(row); if(callback && false === callback.call(opt, row, stmt)){ break; } } __execLock.delete(stmt); } if(0===gotColNames){ /* opt.columnNames was provided but we visited no result rows */ stmt.getColumnNames(opt.columnNames); } }else{ stmt.step(); |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 | }/*prepare() loop*/ }/*catch(e){ sqlite3.config.warn("DB.exec() is propagating exception",opt,e); throw e; }*/finally{ wasm.scopedAllocPop(stack); if(stmt){ | | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | }/*prepare() loop*/ }/*catch(e){ sqlite3.config.warn("DB.exec() is propagating exception",opt,e); throw e; }*/finally{ wasm.scopedAllocPop(stack); if(stmt){ __execLock.delete(stmt); stmt.finalize(); } } return arg.returnVal(); }/*exec()*/, /** |
︙ | ︙ | |||
1384 1385 1386 1387 1388 1389 1390 | */ openStatementCount: function(){ return this.pointer ? Object.keys(__stmtMap.get(this)).length : 0; }, /** Starts a transaction, calls the given callback, and then either | | | 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 | */ openStatementCount: function(){ return this.pointer ? Object.keys(__stmtMap.get(this)).length : 0; }, /** Starts a transaction, calls the given callback, and then either rolls back or commits the transaction, depending on whether the callback throws. The callback is passed this db object as its only argument. On success, returns the result of the callback. Throws on error. Note that transactions may not be nested, so this will throw if it is called recursively. For nested transactions, use the savepoint() method or manually manage SAVEPOINTs using exec(). |
︙ | ︙ | |||
1507 1508 1509 1510 1511 1512 1513 | toss3("Invalid bind() parameter name: "+key); } else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range."); return n; }; /** | > > > > > > > > > > > > > > > > > > > > > > > | | | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 | toss3("Invalid bind() parameter name: "+key); } else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range."); return n; }; /** Each Stmt object which is "locked" by DB.exec() gets an entry here to note that "lock". The reason this is in place is because exec({callback:...})'s callback gets access to the Stmt objects created internally by exec() but it must not use certain Stmt APIs. */ const __execLock = new Set(); /** This is a Stmt.get() counterpart of __execLock. Each time Stmt.step() returns true, the statement is added to this set, indicating that Stmt.get() is legal. Stmt APIs which invalidate that status remove the Stmt object from this set, which will cause Stmt.get() to throw with a descriptive error message instead of a more generic "API misuse" if we were to allow that call to reach the C API. */ const __stmtMayGet = new Set(); /** Stmt APIs which are prohibited on locked objects must call affirmNotLockedByExec() before doing any work. If __execLock.has(stmt) is truthy, this throws an exception complaining that the 2nd argument (an operation name, e.g. "bind()") is not legal while the statement is "locked". Locking happens before an exec()-like callback is passed a statement, to ensure that the callback does not mutate or finalize the statement. If it does not throw, it returns stmt. */ const affirmNotLockedByExec = function(stmt,currentOpName){ if(__execLock.has(stmt)){ toss3("Operation is illegal when statement is locked:",currentOpName); } return stmt; }; /** Binds a single bound parameter value on the given stmt at the |
︙ | ︙ | |||
1600 1601 1602 1603 1604 1605 1606 | break; } default: sqlite3.config.warn("Unsupported bind() argument type:",val); toss3("Unsupported bind() argument type: "+(typeof val)); } if(rc) DB.checkRc(stmt.db.pointer, rc); | < | 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 | break; } default: sqlite3.config.warn("Unsupported bind() argument type:",val); toss3("Unsupported bind() argument type: "+(typeof val)); } if(rc) DB.checkRc(stmt.db.pointer, rc); return stmt; }; Stmt.prototype = { /** "Finalizes" this statement. This is a no-op if the statement has already been finalized. Returns the result of |
︙ | ︙ | |||
1623 1624 1625 1626 1627 1628 1629 | */ finalize: function(){ if(this.pointer){ affirmNotLockedByExec(this,'finalize()'); const rc = capi.sqlite3_finalize(this.pointer); delete __stmtMap.get(this.db)[this.pointer]; __ptrMap.delete(this); | | > < | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 | */ finalize: function(){ if(this.pointer){ affirmNotLockedByExec(this,'finalize()'); const rc = capi.sqlite3_finalize(this.pointer); delete __stmtMap.get(this.db)[this.pointer]; __ptrMap.delete(this); __execLock.delete(this); __stmtMayGet.delete(this); delete this.parameterCount; delete this.db; return rc; } }, /** Clears all bound values. Returns this object. Throws if this statement has been finalized or if modification of the statement is currently illegal (e.g. in the per-row callback of a DB.exec() call). */ clearBindings: function(){ affirmNotLockedByExec(affirmStmtOpen(this), 'clearBindings()') capi.sqlite3_clear_bindings(this.pointer); __stmtMayGet.delete(this); return this; }, /** Resets this statement so that it may be step()ed again from the beginning. Returns this object. Throws if this statement has been finalized, if it may not legally be reset because it is currently being used from a DB.exec() callback, or if the |
︙ | ︙ | |||
1665 1666 1667 1668 1669 1670 1671 | https://sqlite.org/forum/forumpost/36f7a2e7494897df */ reset: function(alsoClearBinds){ affirmNotLockedByExec(this,'reset()'); if(alsoClearBinds) this.clearBindings(); const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); | | | 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | https://sqlite.org/forum/forumpost/36f7a2e7494897df */ reset: function(alsoClearBinds){ affirmNotLockedByExec(this,'reset()'); if(alsoClearBinds) this.clearBindings(); const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); __stmtMayGet.delete(this); checkSqlite3Rc(this.db, rc); return this; }, /** Binds one or more values to its bindable parameters. It accepts 1 or 2 arguments: |
︙ | ︙ | |||
1752 1753 1754 1755 1756 1757 1758 | but this approach simplifies certain client-side uses when passing on arguments between 2+ levels of functions. */ return this; }else if(!this.parameterCount){ toss3("This statement has no bindable parameters."); } | | | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 | but this approach simplifies certain client-side uses when passing on arguments between 2+ levels of functions. */ return this; }else if(!this.parameterCount){ toss3("This statement has no bindable parameters."); } __stmtMayGet.delete(this); if(null===arg){ /* bind NULL */ return bindOne(this, ndx, BindTypes.null, arg); } else if(Array.isArray(arg)){ /* bind each entry by index */ if(1!==arguments.length){ |
︙ | ︙ | |||
1817 1818 1819 1820 1821 1822 1823 | row of data is available, a falsy value is returned. Throws on error. */ step: function(){ affirmNotLockedByExec(this, 'step()'); const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer); switch(rc){ | | > > | > > | | | | | | | 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 | row of data is available, a falsy value is returned. Throws on error. */ step: function(){ affirmNotLockedByExec(this, 'step()'); const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer); switch(rc){ case capi.SQLITE_DONE: __stmtMayGet.delete(this); return false; case capi.SQLITE_ROW: __stmtMayGet.add(this); return true; default: __stmtMayGet.delete(this); sqlite3.config.warn("sqlite3_step() rc=",rc, capi.sqlite3_js_rc_str(rc), "SQL =", capi.sqlite3_sql(this.pointer)); DB.checkRc(this.db.pointer, rc); } }, /** Functions exactly like step() except that... 1) On success, it calls this.reset() and returns this object. |
︙ | ︙ | |||
1909 1910 1911 1912 1913 1914 1915 | Potential TODO: add type ID SQLITE_JSON, which fetches the result as a string and passes it (if it's not null) to JSON.parse(), returning the result of that. Until then, getJSON() can be used for that. */ get: function(ndx,asType){ | | | 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 | Potential TODO: add type ID SQLITE_JSON, which fetches the result as a string and passes it (if it's not null) to JSON.parse(), returning the result of that. Until then, getJSON() can be used for that. */ get: function(ndx,asType){ if(!__stmtMayGet.has(affirmStmtOpen(this))){ toss3("Stmt.step() has not (recently) returned true."); } if(Array.isArray(ndx)){ let i = 0; const n = this.columnCount; while(i<n){ ndx[i] = this.get(i++); |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-wasm.c.
︙ | ︙ | |||
131 132 133 134 135 136 137 | /* SQLITE_EXTRA_INIT vs SQLITE_EXTRA_INIT_MUTEXED: ** see https://sqlite.org/forum/forumpost/14183b98fc0b1dea */ # define SQLITE_EXTRA_INIT_MUTEXED sqlite3_wasm_extra_init #endif /* ** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE | | > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* SQLITE_EXTRA_INIT vs SQLITE_EXTRA_INIT_MUTEXED: ** see https://sqlite.org/forum/forumpost/14183b98fc0b1dea */ # define SQLITE_EXTRA_INIT_MUTEXED sqlite3_wasm_extra_init #endif /* ** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE ** macros. This will, when using the canonical makefile, also elide ** any C functions from the WASM exports which are listed in ** ./EXPORT_FUNCTIONS.sqlite3-extras. */ #ifdef SQLITE_WASM_BARE_BONES # undef SQLITE_ENABLE_COLUMN_METADATA # undef SQLITE_ENABLE_DBPAGE_VTAB # undef SQLITE_ENABLE_DBSTAT_VTAB # undef SQLITE_ENABLE_EXPLAIN_COMMENTS # undef SQLITE_ENABLE_FTS5 # undef SQLITE_ENABLE_OFFSET_SQL_FUNC # undef SQLITE_ENABLE_PREUPDATE_HOOK # undef SQLITE_ENABLE_RTREE |
︙ | ︙ | |||
1153 1154 1155 1156 1157 1158 1159 | typedef struct { int argvIndex; unsigned char omit; } sqlite3_index_constraint_usage; { /* Validate that the above struct sizeof()s match ** expectations. We could improve upon this by ** checking the offsetof() for each member. */ | | | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 | typedef struct { int argvIndex; unsigned char omit; } sqlite3_index_constraint_usage; { /* Validate that the above struct sizeof()s match ** expectations. We could improve upon this by ** checking the offsetof() for each member. */ const sqlite3_index_info siiCheck = {0}; #define IndexSzCheck(T,M) \ (sizeof(T) == sizeof(*siiCheck.M)) if(!IndexSzCheck(sqlite3_index_constraint,aConstraint) || !IndexSzCheck(sqlite3_index_orderby,aOrderBy) || !IndexSzCheck(sqlite3_index_constraint_usage,aConstraintUsage)){ assert(!"sizeof mismatch in sqlite3_index_... struct(s)"); return 0; |
︙ | ︙ |
Changes to ext/wasm/mkwasmbuilds.c.
︙ | ︙ | |||
324 325 326 327 328 329 330 | pf("\t$(bin.emcc) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n"); pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode); pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM); pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM); pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n" "\t\t$(cflags.%s) $(cflags.%s.%s) \\\n" "\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM); | | | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | pf("\t$(bin.emcc) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n"); pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode); pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM); pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM); pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n" "\t\t$(cflags.%s) $(cflags.%s.%s) \\\n" "\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM); if( (LIBMODE_ESM & flags) || (LIBMODE_NODEJS & flags) ){ /* TODO? Replace this $(call) with the corresponding makefile ** code. OTOH, we also use this $(call) in the speedtest1-wasmfs ** build, which is not part of the rules emitted by this ** program. */ pf("\t@$(call SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT,1,%d)\n", (LIBMODE_WASMFS & flags) ? 1 : 0); } |
︙ | ︙ |
Changes to ext/wasm/speedtest1-worker.html.
︙ | ︙ | |||
275 276 277 278 279 280 281 | const opt = document.createElement('option'); eFlags.appendChild(opt); const lbl = nbspPad(f)+flags[f]; //opt.innerText = lbl; opt.innerHTML = lbl; opt.value = f; if(preselectedFlags.indexOf(f) >= 0) opt.selected = true; | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | const opt = document.createElement('option'); eFlags.appendChild(opt); const lbl = nbspPad(f)+flags[f]; //opt.innerText = lbl; opt.innerHTML = lbl; opt.value = f; if(preselectedFlags.indexOf(f) >= 0) opt.selected = true; }); const cbReverseLog = E('#cb-reverse-log-order'); const lblReverseLog = E('#lbl-reverse-log-order'); if(cbReverseLog.checked){ lblReverseLog.classList.add('warning'); eOut.classList.add('reverse'); } cbReverseLog.addEventListener('change', function(){ |
︙ | ︙ |
Changes to ext/wasm/speedtest1.html.
︙ | ︙ | |||
114 115 116 117 118 119 120 | if(!pVfs){ log2('error',"Unknown VFS:",vfs); return; } argv.push("--vfs", vfs); log2('',"Using VFS:",vfs); if('kvvfs' === vfs){ | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | if(!pVfs){ log2('error',"Unknown VFS:",vfs); return; } argv.push("--vfs", vfs); log2('',"Using VFS:",vfs); if('kvvfs' === vfs){ forceSize = 2 /* 5 uses approx. 4.96mb */; dbFile = 'session'; log2('warning',"kvvfs VFS: forcing --size",forceSize, "and filename '"+dbFile+"'."); capi.sqlite3_js_kvvfs_clear(dbFile); } } if(forceSize){ |
︙ | ︙ |
Changes to ext/wasm/tester1.c-pp.js.
︙ | ︙ | |||
1259 1260 1261 1262 1263 1264 1265 | T.assert(wasm.isPtr(st.pointer)) .mustThrowMatching(()=>st.pointer=1, /read-only/) .assert(1===this.db.openStatementCount()) .assert( capi.sqlite3_stmt_status( st, capi.SQLITE_STMTSTATUS_RUN, 0 ) === 0) | < | 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 | T.assert(wasm.isPtr(st.pointer)) .mustThrowMatching(()=>st.pointer=1, /read-only/) .assert(1===this.db.openStatementCount()) .assert( capi.sqlite3_stmt_status( st, capi.SQLITE_STMTSTATUS_RUN, 0 ) === 0) .assert('a' === st.getColumnName(0)) .mustThrowMatching(()=>st.columnCount=2, /columnCount property is read-only/) .assert(1===st.columnCount) .assert(0===st.parameterCount) .mustThrow(()=>st.bind(1,null)) .assert(true===st.step()) |
︙ | ︙ | |||
1283 1284 1285 1286 1287 1288 1289 | .assert(3 === st.get({}).a) .assert(3 === st.get([])[0]) .assert(3 === st.getJSON(0)) .assert(st.get(0,capi.SQLITE_BLOB) instanceof Uint8Array) .assert(1===st.get(0,capi.SQLITE_BLOB).length) .assert(st.getBlob(0) instanceof Uint8Array) .assert('3'.charCodeAt(0) === st.getBlob(0)[0]) | < | > | < < < < | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 | .assert(3 === st.get({}).a) .assert(3 === st.get([])[0]) .assert(3 === st.getJSON(0)) .assert(st.get(0,capi.SQLITE_BLOB) instanceof Uint8Array) .assert(1===st.get(0,capi.SQLITE_BLOB).length) .assert(st.getBlob(0) instanceof Uint8Array) .assert('3'.charCodeAt(0) === st.getBlob(0)[0]) .assert(false===st.step()) .mustThrowMatching(()=>st.get(0), "Stmt.step() has not (recently) returned true.") .assert( capi.sqlite3_stmt_status( st, capi.SQLITE_STMTSTATUS_RUN, 0 ) > 0); T.assert(this.progressHandlerCount>0 || wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'), "Expecting progress callback."); }finally{ rc = st.finalize(); } T.assert(!st.pointer) .assert(0===this.db.openStatementCount()) .assert(0===rc); |
︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 | pVfsDflt = capi.sqlite3_vfs_find(0), pVfsDb = capi.sqlite3_js_db_vfs(db.pointer); T.assert(pVfsMem > 0) .assert(pVfsDflt > 0) .assert(pVfsDb > 0) .assert(pVfsMem !== pVfsDflt /* memdb lives on top of the default vfs */) | | | 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 | pVfsDflt = capi.sqlite3_vfs_find(0), pVfsDb = capi.sqlite3_js_db_vfs(db.pointer); T.assert(pVfsMem > 0) .assert(pVfsDflt > 0) .assert(pVfsDb > 0) .assert(pVfsMem !== pVfsDflt /* memdb lives on top of the default vfs */) .assert(pVfsDb === pVfsDflt || pVfsDb === pVfsMem) ; /*const vMem = new capi.sqlite3_vfs(pVfsMem), vDflt = new capi.sqlite3_vfs(pVfsDflt), vDb = new capi.sqlite3_vfs(pVfsDb);*/ const duv = capi.sqlite3_js_db_uses_vfs; T.assert(pVfsDflt === duv(db.pointer, 0) || pVfsMem === duv(db.pointer,0)) |
︙ | ︙ | |||
2189 2190 2191 2192 2193 2194 2195 | }else{ log("No BigInt support. Skipping related tests."); log("\"The problem\" here is that we can manipulate, at the byte level,", "heap memory to set 64-bit values, but we can't get those values", "back into JS because of the lack of 64-bit integer support."); } }finally{ | | | 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 | }else{ log("No BigInt support. Skipping related tests."); log("\"The problem\" here is that we can manipulate, at the byte level,", "heap memory to set 64-bit values, but we can't get those values", "back into JS because of the lack of 64-bit integer support."); } }finally{ //const x = w.scopedAlloc(1), y = w.scopedAlloc(1), z = w.scopedAlloc(1); //log("x=",x,"y=",y,"z=",z); // just looking at the alignment w.scopedAllocPop(stack); } } }/* jaccwabyt-specific tests */) //////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
2669 2670 2671 2672 2673 2674 2675 | //#if enable-see .t({ name: 'kvvfs with SEE encryption', predicate: ()=>(isUIThread() || "Only available in main thread."), test: function(sqlite3){ this.kvvfsUnlink(); | > > | > | > | > | < < < | > > | < | > | | > | < | | > | | | < < < | | | | | | | | | | | > > | < > | < > | > | | | < | > > > > > > > > > > > > > > > > | 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 | //#if enable-see .t({ name: 'kvvfs with SEE encryption', predicate: ()=>(isUIThread() || "Only available in main thread."), test: function(sqlite3){ this.kvvfsUnlink(); let initDb = true; const tryKey = function(keyKey, key, expectCount){ let db; //console.debug('tryKey()',arguments); const ctoropt = { filename: this.kvvfsDbFile //vfs: 'kvvfs' //,flags: 'ct' }; try { if (initDb) { initDb = false; db = new this.JDb({ ...ctoropt, [keyKey]: key }); db.exec([ "drop table if exists t;", "create table t(a);" ]); db.close(); // Ensure that it's actually encrypted... let err; try { db = new this.JDb(ctoropt); T.assert(db, 'db opened') /* opening is fine, but... */; db.exec("select 1 from sqlite_schema"); console.warn("(should not be reached) sessionStorage =", sessionStorage); } catch (e) { err = e; } finally { db.close() } T.assert(err, "Expecting an exception") .assert(sqlite3.capi.SQLITE_NOTADB == err.resultCode, "Expecting NOTADB"); }/*initDb*/ //console.debug('tryKey()',arguments); db = new sqlite3.oo1.DB({ ...ctoropt, vfs: 'kvvfs', [keyKey]: key }); db.exec("insert into t(a) values (1),(2)"); T.assert(expectCount === db.selectValue('select sum(a) from t')); } finally { if (db) db.close(); } }.bind(this); const hexFoo = new Uint8Array([0x66,0x6f,0x6f]/*=="foo"*/); tryKey('textkey', 'foo', 3); T.assert( !initDb ); tryKey('textkey', 'foo', 6); this.kvvfsUnlink(); initDb = true; tryKey('key', 'foo', 3); T.assert( !initDb ); tryKey('key', hexFoo, 6); this.kvvfsUnlink(); initDb = true; tryKey('hexkey', hexFoo, 3); T.assert( !initDb ); tryKey('hexkey', hexFoo, 6); this.kvvfsUnlink(); } })/*kvvfs with SEE*/ //#endif enable-see ;/* end kvvfs tests */ //////////////////////////////////////////////////////////////////////// T.g('Hook APIs') |
︙ | ︙ | |||
2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 | T.assert('number' === typeof capi.sqlite3_preupdate_old_js(pDb, 0)); break; default: toss("Unexpected hook operator:",op); } }, 9 ); db.transaction((d)=>{ d.exec([ "create table t(a);", "insert into t(a) values(1);", "update t set a=2;", "update t set a=3;", "delete from t where a=3" ]); }); T.assert(1 === countHook[capi.SQLITE_INSERT]) .assert(2 === countHook[capi.SQLITE_UPDATE]) .assert(1 === countHook[capi.SQLITE_DELETE]); //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true; | > | > > | 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 | T.assert('number' === typeof capi.sqlite3_preupdate_old_js(pDb, 0)); break; default: toss("Unexpected hook operator:",op); } }, 9 ); T.assert( 0==rc ); db.transaction((d)=>{ d.exec([ "create table t(a);", "insert into t(a) values(1);", "update t set a=2;", "update t set a=3;", "delete from t where a=3" ]); }); T.assert(1 === countHook[capi.SQLITE_INSERT]) .assert(2 === countHook[capi.SQLITE_UPDATE]) .assert(1 === countHook[capi.SQLITE_DELETE]); //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true; T.assert( !!capi.sqlite3_preupdate_hook(db, 0, 0) ); //wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false; T.assert( !capi.sqlite3_preupdate_hook(db, 0, 0) ); db.close(); } })/*pre-update hooks*/ ;/*end hook API tests*/ //////////////////////////////////////////////////////////////////////// T.g('Auto-extension API') .t({ |
︙ | ︙ | |||
3047 3048 3049 3050 3051 3052 3053 | const exp = this.opfsDbExport; delete this.opfsDbExport; this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(filename, exp); db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); T.assert(6 === db.selectValue('select count(*) from p')). assert( this.opfsImportSize == exp.byteLength ); db.close(); | | | 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 | const exp = this.opfsDbExport; delete this.opfsDbExport; this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(filename, exp); db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); T.assert(6 === db.selectValue('select count(*) from p')). assert( this.opfsImportSize == exp.byteLength ); db.close(); this.opfsUnlink = (fn=filename)=>sqlite3.util.sqlite3__wasm_vfs_unlink("opfs",fn); this.opfsUnlink(filename); T.assert(!(await sqlite3.opfs.entryExists(filename))); // Try again with a function as an input source: let cursor = 0; const blockSize = 512, end = exp.byteLength; const reader = async function(){ |
︙ | ︙ | |||
3298 3299 3300 3301 3302 3303 3304 | const P3b = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e); T.assert(undefined === cErr) .assert(P3b === u3) .assert(P3b === await inst(conf2)) .assert(true === await u3.removeVfs()) .assert(false === await P3b.removeVfs()); } | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 | const P3b = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e); T.assert(undefined === cErr) .assert(P3b === u3) .assert(P3b === await inst(conf2)) .assert(true === await u3.removeVfs()) .assert(false === await P3b.removeVfs()); } }/*OPFS SAH Pool sanity checks*/); //////////////////////////////////////////////////////////////////////// T.g('Misc. APIs') .t('bind_parameter_...', function(sqlite3){ const db = new sqlite3.oo1.DB(); db.exec("create table t(a)"); const stmt = db.prepare("insert into t(a) values($a)"); T.assert( 1===capi.sqlite3_bind_parameter_count(stmt) ) .assert( 1===capi.sqlite3_bind_parameter_index(stmt, "$a") ) .assert( 0===capi.sqlite3_bind_parameter_index(stmt, ":a") ) .assert( 1===stmt.getParamIndex("$a") ) .assert( 0===stmt.getParamIndex(":a") ) .assert( "$a"===capi.sqlite3_bind_parameter_name(stmt, 1) ) .assert( null===capi.sqlite3_bind_parameter_name(stmt, 0) ) .assert( "$a"===stmt.getParamName(1) ) .assert( null===stmt.getParamName(0) ); stmt.finalize(); db.close(); }) /** Ensure that certain Stmt members throw when called via DB.exec(). */ .t('locked-by-exec() APIs', function(sqlite3){ const db = new sqlite3.oo1.DB(); db.exec("create table t(a);insert into t(a) values(1);"); let checkCount = 0; const checkOp = function(op){ ++checkCount; T.mustThrowMatching(() => { db.exec({ sql: "select ?1", bind: op, callback: (row, stmt) => { switch (row[0]) { case 'bind': stmt.bind(1); break; case 'finalize': case 'clearBindings': case 'reset': case 'step': stmt[op](); break; } } }); }, /^Operation is illegal when statement is locked.*/) }; try{ checkOp('bind'); checkOp('finalize'); checkOp('clearBindings'); checkOp('reset'); checkOp('step'); T.assert(5===checkCount); }finally{ db.close(); } }) //////////////////////////////////////////////////////////////////// .t("Misc. stmt_...", function(sqlite3){ const db = new sqlite3.oo1.DB(); db.exec("create table t(a doggiebiscuits); insert into t(a) values(123)"); const stmt = db.prepare("select a, a+1 from t"); T.assert( stmt.isReadOnly() ) |
︙ | ︙ | |||
3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 | T.assert( 123===capi.sqlite3_value_int(sv) ) .assert( "doggiebiscuits"===capi.sqlite3_column_decltype(stmt,0) ) .assert( null===capi.sqlite3_column_decltype(stmt,1) ); } T.assert( 1===n ) .assert( 0===capi.sqlite3_stmt_busy(stmt) ) .assert( !stmt.isBusy() ); stmt.finalize(); db.close(); }) //////////////////////////////////////////////////////////////////// .t("interrupt", function(sqlite3){ const db = new sqlite3.oo1.DB(); T.assert( 0===capi.sqlite3_is_interrupted(db) ); capi.sqlite3_interrupt(db); T.assert( 0!==capi.sqlite3_is_interrupted(db) ); db.close(); | > > > > > > > > > > | | | | 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | T.assert( 123===capi.sqlite3_value_int(sv) ) .assert( "doggiebiscuits"===capi.sqlite3_column_decltype(stmt,0) ) .assert( null===capi.sqlite3_column_decltype(stmt,1) ); } T.assert( 1===n ) .assert( 0===capi.sqlite3_stmt_busy(stmt) ) .assert( !stmt.isBusy() ); if( wasm.exports.sqlite3_column_origin_name ){ log("Column metadata APIs enabled"); T.assert( "t" === capi.sqlite3_column_table_name(stmt, 0)) .assert("a" === capi.sqlite3_column_origin_name(stmt, 0)) .assert("main" === capi.sqlite3_column_database_name(stmt, 0)) }else{ log("Column metadata APIs not enabled"); } // column metadata APIs stmt.finalize(); db.close(); }) //////////////////////////////////////////////////////////////////// .t("interrupt", function(sqlite3){ const db = new sqlite3.oo1.DB(); T.assert( 0===capi.sqlite3_is_interrupted(db) ); capi.sqlite3_interrupt(db); T.assert( 0!==capi.sqlite3_is_interrupted(db) ); db.close(); }); //////////////////////////////////////////////////////////////////////// T.g('Bug Reports') .t({ name: 'Delete via bound parameter in subquery', predicate: ()=>wasm.compileOptionUsed('ENABLE_FTS5') || "Missing FTS5", test: function(sqlite3){ // Testing https://sqlite.org/forum/forumpost/40ce55bdf5 // with the exception that that post uses "external content" // for the FTS index. const db = new sqlite3.oo1.DB();//(':memory:','wt'); db.exec([ "create virtual table f using fts5 (path);", "insert into f(path) values('abc'),('def'),('ghi');" ]); const fetchEm = ()=> db.exec({ sql: "SELECT * FROM f order by path", rowMode: 'array' }); /*const dump = function(lbl){ let rc = fetchEm(); log((lbl ? (lbl+' results') : ''),rc); };*/ //dump('Full fts table'); let rc = fetchEm(); T.assert(3===rc.length); db.exec(` delete from f where rowid in ( select rowid from f where path = :path )`, |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
768 769 770 771 772 773 774 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vdbecov.c \ $(TOP)/src/test_vfs.c \ | < | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 | $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vdbecov.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_window.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ $(TOP)/ext/fts3/fts3_test.c \ $(TOP)/ext/session/test_session.c \ $(TOP)/ext/session/sqlite3changebatch.c \ $(TOP)/ext/recover/sqlite3recover.c \ |
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | # It took half an hour to figure that out. # T.tcl.env.sh = ./.tclenv.sh $(T.tcl.env.sh): $(TCLSH_CMD) $(TCL_CONFIG_SH) $(MAKEFILE_LIST) @if [ x = "x$(TCL_CONFIG_SH)" ]; then \ echo 'TCL_CONFIG_SH must be set to point to a "tclConfig.sh"' 1>&2; exit 1; \ fi; \ | | > > > > | | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 | # It took half an hour to figure that out. # T.tcl.env.sh = ./.tclenv.sh $(T.tcl.env.sh): $(TCLSH_CMD) $(TCL_CONFIG_SH) $(MAKEFILE_LIST) @if [ x = "x$(TCL_CONFIG_SH)" ]; then \ echo 'TCL_CONFIG_SH must be set to point to a "tclConfig.sh"' 1>&2; exit 1; \ fi; \ if [ x != "x$(TCLLIBDIR)" ]; then \ echo "# generated by main.mk"; \ echo TCLLIBDIR="$(TCLLIBDIR)"; \ else \ ld= ; \ for d in `echo "puts stdout \\$$auto_path" | $(TCLSH_CMD)`; do \ if [ -d "$$d" ]; then ld=$$d; break; fi; \ done; \ if [ x = "x$$ld" ]; then echo "Cannot determine TCLLIBDIR" 1>&2; exit 1; fi; \ echo "# generated by main.mk"; \ echo "TCLLIBDIR=$$ld/sqlite3$(PACKAGE_VERSION)"; \ fi > $@; \ echo ". \"$(TCL_CONFIG_SH)\" || exit \$$?" >> $@; \ echo "Created $@" # # $(T.tcl.env.source) is shell code to be run as part of any # compilation or link step which requires vars from |
︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | # # Install C header files # install-headers: sqlite3.h $(install-dir.include) $(INSTALL.noexec) sqlite3.h "$(TOP)/src/sqlite3ext.h" "$(install-dir.include)" install: install-headers # # libtclsqlite3... # | > > > > > > > > > > > > > > | | | | 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 | # # Install C header files # install-headers: sqlite3.h $(install-dir.include) $(INSTALL.noexec) sqlite3.h "$(TOP)/src/sqlite3ext.h" "$(install-dir.include)" install: install-headers # # If TCL_EXT_DLL_BASENAME is not set then guess the Tcl extension's # DLL name depending on the Tcl version. This does not account for # Cygwin's naming - the canonical build will usually set it, but # static makefiles importing this one will need to account for that on # their own. They can do that by setting libtclsqlite3.basename-[89] # to appropriate names (cygsqlite resp. cygtcl9sqlite). # TCL_MAJOR_VERSION ?= 0 libtclsqlite3.basename-8 ?= libsqlite libtclsqlite3.basename-9 ?= libtcl9sqlite TCL_EXT_DLL_BASENAME ?= $(libtclsqlite3.basename-$(TCL_MAJOR_VERSION)) libtclsqlite3.DLL ?= $(TCL_EXT_DLL_BASENAME)$(PACKAGE_VERSION)$(T.dll) # # libtclsqlite3... # pkgIndex.tcl: $(TOP)/main.mk echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir $(libtclsqlite3.DLL)] Sqlite3]' > $@ pkgIndex.tcl-1: pkgIndex.tcl pkgIndex.tcl-0 pkgIndex.tcl-: tcl: pkgIndex.tcl-$(HAVE_TCL) $(libtclsqlite3.DLL): $(T.tcl.env.sh) tclsqlite.o $(LIBOBJ) $(T.tcl.env.source); \ $(T.link.shared) -o $@ tclsqlite.o \ $$TCL_INCLUDE_SPEC $$TCL_STUB_LIB_SPEC $(LDFLAGS.libsqlite3) \ $(LIBOBJ) -Wl,-rpath,$$TCLLIBDIR # ^^^ that rpath bit is defined as TCL_LD_SEARCH_FLAGS in # tclConfig.sh, but it's defined in such a way as to be useless for a |
︙ | ︙ | |||
1670 1671 1672 1673 1674 1675 1676 | CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS) # # Build the SQLite TCL extension in a way that make it compatible # with whatever version of TCL is running as $TCLSH_CMD, possibly defined # by --with-tclsh= # tclextension: tclsqlite3.c | | > | > | > | > | > > > > > > > > > | 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 | CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS) # # Build the SQLite TCL extension in a way that make it compatible # with whatever version of TCL is running as $TCLSH_CMD, possibly defined # by --with-tclsh= # tclextension: tclsqlite3.c $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \ --tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension) # # Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD # to find it. # tclextension-install: tclsqlite3.c $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \ --tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension) # # Uninstall the SQLite TCL extension that is used by $TCLSH_CMD. # tclextension-uninstall: $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall \ --tclConfig.sh $(TCL_CONFIG_SH) # # List all installed the SQLite TCL extensions that is are accessible # by $TCLSH_CMD, including prior versions. # tclextension-list: @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info \ --tclConfig.sh $(TCL_CONFIG_SH) # Verify that the SQLite TCL extension that is loaded by default # in $(TCLSH_CMD) is the same as the version of SQLite for the # current source tree # tclextension-verify: sqlite3.h @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --version-check \ --tclConfig.sh $(TCL_CONFIG_SH) # Run all of the tclextension targets in order, ending with uninstall. tclextension-all: $(MAKE) tclextension $(MAKE) tclextension-install $(MAKE) tclextension-list $(MAKE) tclextension-verify $(MAKE) tclextension-uninstall # # FTS5 things # FTS5_SRC = \ $(TOP)/ext/fts5/fts5.h \ $(TOP)/ext/fts5/fts5Int.h \ |
︙ | ︙ | |||
1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | $(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS) mdevtest: srctree-check has_tclsh85 $(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS) sdevtest: has_tclsh85 $(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS) # # Validate that various generated files in the source tree # are up-to-date. # srctree-check: $(TOP)/tool/srctree-check.tcl $(TCLSH_CMD) $(TOP)/tool/srctree-check.tcl | > > > > > > | 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | $(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS) mdevtest: srctree-check has_tclsh85 $(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS) sdevtest: has_tclsh85 $(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS) # Like releasetest, except it omits srctree-check and verify-source so # that it can be used on a modified source tree. # xdevtest: has_tclsh85 $(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS) # # Validate that various generated files in the source tree # are up-to-date. # srctree-check: $(TOP)/tool/srctree-check.tcl $(TCLSH_CMD) $(TOP)/tool/srctree-check.tcl |
︙ | ︙ | |||
2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 | $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/sha1.c \ $(TOP)/ext/misc/shathree.c \ $(TOP)/ext/misc/sqlar.c \ $(TOP)/ext/misc/uint.c \ $(TOP)/ext/misc/vfstrace.c \ $(TOP)/ext/misc/zipfile.c \ $(TOP)/ext/recover/dbdata.c \ $(TOP)/ext/recover/sqlite3recover.c \ | > | | < | 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 | $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/sha1.c \ $(TOP)/ext/misc/shathree.c \ $(TOP)/ext/misc/sqlar.c \ $(TOP)/ext/misc/uint.c \ $(TOP)/ext/misc/vfstrace.c \ $(TOP)/ext/misc/windirent.h \ $(TOP)/ext/misc/zipfile.c \ $(TOP)/ext/recover/dbdata.c \ $(TOP)/ext/recover/sqlite3recover.c \ $(TOP)/ext/recover/sqlite3recover.h shell.c: $(SHELL_DEP) $(TOP)/tool/mkshellc.tcl $(B.tclsh) $(B.tclsh) $(TOP)/tool/mkshellc.tcl shell.c # # Rules to build the extension objects. # |
︙ | ︙ |
Changes to src/bitvec.c.
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 | /* For a BITVEC_SZ of 512, this would be 34,359,739. */ union { BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ u32 aHash[BITVEC_NINT]; /* Hash table representation */ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ } u; }; /* ** Create a new bitmap object able to handle bits between 0 and iSize, ** inclusive. Return a pointer to the new object. Return NULL if ** malloc fails. */ Bitvec *sqlite3BitvecCreate(u32 iSize){ | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | /* For a BITVEC_SZ of 512, this would be 34,359,739. */ union { BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ u32 aHash[BITVEC_NINT]; /* Hash table representation */ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ } u; }; /* ** Create a new bitmap object able to handle bits between 0 and iSize, ** inclusive. Return a pointer to the new object. Return NULL if ** malloc fails. */ Bitvec *sqlite3BitvecCreate(u32 iSize){ |
︙ | ︙ | |||
218 219 220 221 222 223 224 | int rc; u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); if( aiValues==0 ){ return SQLITE_NOMEM_BKPT; }else{ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); memset(p->u.apSub, 0, sizeof(p->u.apSub)); | | > > | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | int rc; u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); if( aiValues==0 ){ return SQLITE_NOMEM_BKPT; }else{ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); memset(p->u.apSub, 0, sizeof(p->u.apSub)); p->iDivisor = p->iSize/BITVEC_NPTR; if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++; if( p->iDivisor<BITVEC_NBIT ) p->iDivisor = BITVEC_NBIT; rc = sqlite3BitvecSet(p, i); for(j=0; j<BITVEC_NINT; j++){ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); } sqlite3StackFree(0, aiValues); return rc; } |
︙ | ︙ | |||
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | /* ** Return the value of the iSize parameter specified when Bitvec *p ** was created. */ u32 sqlite3BitvecSize(Bitvec *p){ return p->iSize; } #ifndef SQLITE_UNTESTABLE /* ** Let V[] be an array of unsigned characters sufficient to hold ** up to N bits. Let I be an integer between 0 and N. 0<=I<N. ** Then the following macros can be used to set, clear, or test ** individual bits within V. */ #define SETBIT(V,I) V[I>>3] |= (1<<(I&7)) #define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7)) #define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 /* ** This routine runs an extensive test of the Bitvec code. ** ** The input is an array of integers that acts as a program ** to test the Bitvec. The integers are opcodes followed ** by 0, 1, or 3 operands, depending on the opcode. Another ** opcode follows immediately after the last operand. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > > > > > > > > | | > | > > > > > > > > > > > > > > > > > > | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | /* ** Return the value of the iSize parameter specified when Bitvec *p ** was created. */ u32 sqlite3BitvecSize(Bitvec *p){ return p->iSize; } #ifdef SQLITE_DEBUG /* ** Show the content of a Bitvec option and its children. Indent ** everything by n spaces. Add x to each bitvec value. ** ** From a debugger such as gdb, one can type: ** ** call sqlite3ShowBitvec(p) ** ** For some Bitvec p and see a recursive view of the Bitvec's content. */ static void showBitvec(Bitvec *p, int n, unsigned x){ int i; if( p==0 ){ printf("NULL\n"); return; } printf("Bitvec 0x%p iSize=%u", p, p->iSize); if( p->iSize<=BITVEC_NBIT ){ printf(" bitmap\n"); printf("%*s bits:", n, ""); for(i=1; i<=BITVEC_NBIT; i++){ if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i); } printf("\n"); }else if( p->iDivisor==0 ){ printf(" hash with %u entries\n", p->nSet); printf("%*s bits:", n, ""); for(i=0; i<BITVEC_NINT; i++){ if( p->u.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]); } printf("\n"); }else{ printf(" sub-bitvec with iDivisor=%u\n", p->iDivisor); for(i=0; i<BITVEC_NPTR; i++){ if( p->u.apSub[i]==0 ) continue; printf("%*s apSub[%d]=", n, "", i); showBitvec(p->u.apSub[i], n+4, i*p->iDivisor); } } } void sqlite3ShowBitvec(Bitvec *p){ showBitvec(p, 0, 0); } #endif #ifndef SQLITE_UNTESTABLE /* ** Let V[] be an array of unsigned characters sufficient to hold ** up to N bits. Let I be an integer between 0 and N. 0<=I<N. ** Then the following macros can be used to set, clear, or test ** individual bits within V. */ #define SETBIT(V,I) V[I>>3] |= (1<<(I&7)) #define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7)) #define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 /* ** This routine runs an extensive test of the Bitvec code. ** ** The input is an array of integers that acts as a program ** to test the Bitvec. The integers are opcodes followed ** by 0, 1, or 3 operands, depending on the opcode. Another ** opcode follows immediately after the last operand. ** ** There are opcodes numbered starting with 0. 0 is the ** "halt" opcode and causes the test to end. ** ** 0 Halt and return the number of errors ** 1 N S X Set N bits beginning with S and incrementing by X ** 2 N S X Clear N bits beginning with S and incrementing by X ** 3 N Set N randomly chosen bits ** 4 N Clear N randomly chosen bits ** 5 N S X Set N bits from S increment X in array only, not in bitvec ** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far ** 7 X Show compile-time parameters and the hash of X ** ** The opcodes 1 through 4 perform set and clear operations are performed ** on both a Bitvec object and on a linear array of bits obtained from malloc. ** Opcode 5 works on the linear array only, not on the Bitvec. ** Opcode 5 is used to deliberately induce a fault in order to ** confirm that error detection works. Opcodes 6 and greater are ** state output opcodes. Opcodes 6 and greater are no-ops unless ** SQLite has been compiled with SQLITE_DEBUG. ** ** At the conclusion of the test the linear array is compared ** against the Bitvec object. If there are any differences, ** an error is returned. If they are the same, zero is returned. ** ** If a memory allocation error occurs, return -1. ** ** sz is the size of the Bitvec. Or if sz is negative, make the size ** 2*(unsigned)(-sz) and disabled the linear vector check. */ int sqlite3BitvecBuiltinTest(int sz, int *aOp){ Bitvec *pBitvec = 0; unsigned char *pV = 0; int rc = -1; int i, nx, pc, op; void *pTmpSpace; /* Allocate the Bitvec to be tested and a linear array of ** bits to act as the reference */ if( sz<=0 ){ pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) ); pV = 0; }else{ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 ); } pTmpSpace = sqlite3_malloc64(BITVEC_SZ); if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end; /* NULL pBitvec tests */ sqlite3BitvecSet(0, 1); sqlite3BitvecClear(0, 1, pTmpSpace); /* Run the program */ pc = i = 0; while( (op = aOp[pc])!=0 ){ if( op>=6 ){ #ifdef SQLITE_DEBUG if( op==6 ){ sqlite3ShowBitvec(pBitvec); }else if( op==7 ){ printf("BITVEC_SZ = %d (%d by sizeof)\n", BITVEC_SZ, (int)sizeof(Bitvec)); printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE); printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM); printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT); printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT); printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH); printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR); } #endif pc++; continue; } switch( op ){ case 1: case 2: case 5: { nx = 4; i = aOp[pc+2] - 1; aOp[pc+2] += aOp[pc+3]; |
︙ | ︙ | |||
378 379 380 381 382 383 384 | break; } } if( (--aOp[pc+1]) > 0 ) nx = 0; pc += nx; i = (i & 0x7fffffff)%sz; if( (op & 1)!=0 ){ | | | > | | | | | | | | > > > | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | break; } } if( (--aOp[pc+1]) > 0 ) nx = 0; pc += nx; i = (i & 0x7fffffff)%sz; if( (op & 1)!=0 ){ if( pV ) SETBIT(pV, (i+1)); if( op!=5 ){ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; } }else{ if( pV ) CLEARBIT(pV, (i+1)); sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); } } /* Test to make sure the linear array exactly matches the ** Bitvec object. Start with the assumption that they do ** match (rc==0). Change rc to non-zero if a discrepancy ** is found. */ if( pV ){ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + sqlite3BitvecTest(pBitvec, 0) + (sqlite3BitvecSize(pBitvec) - sz); for(i=1; i<=sz; i++){ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ rc = i; break; } } }else{ rc = 0; } /* Free allocated structure */ bitvec_end: sqlite3_free(pTmpSpace); sqlite3_free(pV); sqlite3BitvecDestroy(pBitvec); return rc; } #endif /* SQLITE_UNTESTABLE */ |
Changes to src/btree.c.
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 | UnpackedRecord *pIdxKey; /* Unpacked index key */ if( pKey ){ KeyInfo *pKeyInfo = pCur->pKeyInfo; assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; | | | 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 | UnpackedRecord *pIdxKey; /* Unpacked index key */ if( pKey ){ KeyInfo *pKeyInfo = pCur->pKeyInfo; assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); } sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); }else{ |
︙ | ︙ | |||
3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 | sqlite3_mutex_free(pBt->mutex); } removed = 1; } sqlite3_mutex_leave(pMainMtx); return removed; #else return 1; #endif } /* ** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child | > | 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 | sqlite3_mutex_free(pBt->mutex); } removed = 1; } sqlite3_mutex_leave(pMainMtx); return removed; #else UNUSED_PARAMETER( pBt ); return 1; #endif } /* ** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child |
︙ | ︙ | |||
3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 | int rc = SQLITE_OK; int x; BtShared *pBt = p->pBt; assert( nReserve>=0 && nReserve<=255 ); sqlite3BtreeEnter(p); pBt->nReserveWanted = (u8)nReserve; x = pBt->pageSize - pBt->usableSize; if( nReserve<x ) nReserve = x; if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; } assert( nReserve>=0 && nReserve<=255 ); if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && | > > > > | 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 | int rc = SQLITE_OK; int x; BtShared *pBt = p->pBt; assert( nReserve>=0 && nReserve<=255 ); sqlite3BtreeEnter(p); pBt->nReserveWanted = (u8)nReserve; x = pBt->pageSize - pBt->usableSize; if( x==nReserve && (pageSize==0 || (u32)pageSize==pBt->pageSize) ){ sqlite3BtreeLeave(p); return SQLITE_OK; } if( nReserve<x ) nReserve = x; if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; } assert( nReserve>=0 && nReserve<=255 ); if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && |
︙ | ︙ | |||
3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 | } } if( rc!=SQLITE_OK ){ (void)sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); sqlite3PagerWalDb(pPager, 0); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; #endif | > > > > > > > | 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 | } } if( rc!=SQLITE_OK ){ (void)sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } #if defined(SQLITE_ENABLE_SETLK_TIMEOUT) if( rc==SQLITE_BUSY_TIMEOUT ){ /* If a blocking lock timed out, break out of the loop here so that ** the busy-handler is not invoked. */ break; } #endif }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); sqlite3PagerWalDb(pPager, 0); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; #endif |
︙ | ︙ | |||
6351 6352 6353 6354 6355 6356 6357 | moveto_table_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } /* | | | | < | 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 | moveto_table_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } /* ** Compare the "idx"-th cell on the page pPage against the key ** pointing to by pIdxKey using xRecordCompare. Return negative or ** zero if the cell is less than or equal pIdxKey. Return positive ** if unknown. ** ** Return value negative: Cell at pCur[idx] less than pIdxKey ** ** Return value is zero: Cell at pCur[idx] equals pIdxKey ** ** Return value positive: Nothing is known about the relationship ** of the cell at pCur[idx] and pIdxKey. ** ** This routine is part of an optimization. It is always safe to return ** a positive value as that will cause the optimization to be skipped. */ static int indexCellCompare( MemPage *pPage, int idx, UnpackedRecord *pIdxKey, RecordCompare xRecordCompare ){ int c; int nCell; /* Size of the pCell cell in bytes */ u8 *pCell = findCellPastPtr(pPage, idx); nCell = pCell[0]; if( nCell<=pPage->max1bytePayload ){ /* This branch runs if the record-size field of the cell is a |
︙ | ︙ | |||
6481 6482 6483 6484 6485 6486 6487 | */ if( pCur->eState==CURSOR_VALID && pCur->pPage->leaf && cursorOnLastPage(pCur) ){ int c; if( pCur->ix==pCur->pPage->nCell-1 | | | | 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 | */ if( pCur->eState==CURSOR_VALID && pCur->pPage->leaf && cursorOnLastPage(pCur) ){ int c; if( pCur->ix==pCur->pPage->nCell-1 && (c = indexCellCompare(pCur->pPage,pCur->ix,pIdxKey,xRecordCompare))<=0 && pIdxKey->errCode==SQLITE_OK ){ *pRes = c; return SQLITE_OK; /* Cursor already pointing at the correct spot */ } if( pCur->iPage>0 && indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0 && pIdxKey->errCode==SQLITE_OK ){ pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast); if( !pCur->pPage->isInit ){ return SQLITE_CORRUPT_BKPT; } goto bypass_moveto_root; /* Start search on the current page */ |
︙ | ︙ | |||
6706 6707 6708 6709 6710 6711 6712 | ** opcode and the OP_Count opcode with P3=1. In either case, ** the cursor will always be valid unless the btree is empty. */ if( pCur->eState!=CURSOR_VALID ) return 0; if( NEVER(pCur->pPage->leaf==0) ) return -1; n = pCur->pPage->nCell; for(i=0; i<pCur->iPage; i++){ | | | 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 | ** opcode and the OP_Count opcode with P3=1. In either case, ** the cursor will always be valid unless the btree is empty. */ if( pCur->eState!=CURSOR_VALID ) return 0; if( NEVER(pCur->pPage->leaf==0) ) return -1; n = pCur->pPage->nCell; for(i=0; i<pCur->iPage; i++){ n *= pCur->apPage[i]->nCell+1; } return n; } /* ** Advance the cursor to the next entry in the database. ** Return value: |
︙ | ︙ | |||
9172 9173 9174 9175 9176 9177 9178 | assert( apNew[nNew-1]!=0 ); put4byte(pRight, apNew[nNew-1]->pgno); /* If the sibling pages are not leaves, ensure that the right-child pointer ** of the right-most new sibling page is set to the value that was ** originally in the same field of the right-most old sibling page. */ if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ | | > > > > > | 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 | assert( apNew[nNew-1]!=0 ); put4byte(pRight, apNew[nNew-1]->pgno); /* If the sibling pages are not leaves, ensure that the right-child pointer ** of the right-most new sibling page is set to the value that was ** originally in the same field of the right-most old sibling page. */ if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ MemPage *pOld; if( nNew>nOld ){ pOld = apNew[nOld-1]; }else{ pOld = 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: |
︙ | ︙ | |||
11815 11816 11817 11818 11819 11820 11821 11822 11823 11824 11825 11826 11827 11828 | /* ** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared ** btree as the argument handle holds an exclusive lock on the ** sqlite_schema table. Otherwise SQLITE_OK. */ int sqlite3BtreeSchemaLocked(Btree *p){ int rc; assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); sqlite3BtreeLeave(p); return rc; } | > | 11831 11832 11833 11834 11835 11836 11837 11838 11839 11840 11841 11842 11843 11844 11845 | /* ** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared ** btree as the argument handle holds an exclusive lock on the ** sqlite_schema table. Otherwise SQLITE_OK. */ int sqlite3BtreeSchemaLocked(Btree *p){ int rc; UNUSED_PARAMETER(p); /* only used in DEBUG builds */ assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); sqlite3BtreeLeave(p); return rc; } |
︙ | ︙ |
Changes to src/dbpage.c.
︙ | ︙ | |||
223 224 225 226 227 228 229 | ** 1 schema=main, pgno=?1 ** 2 schema=?1, full table scan ** 3 schema=?1, pgno=?2 ** ** idxStr is not used */ static int dbpageFilter( | | | > | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | ** 1 schema=main, pgno=?1 ** 2 schema=?1, full table scan ** 3 schema=?1, pgno=?2 ** ** idxStr is not used */ static int dbpageFilter( sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ DbpageCursor *pCsr = (DbpageCursor *)pCursor; DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; int rc; sqlite3 *db = pTab->db; Btree *pBt; UNUSED_PARAMETER(idxStr); UNUSED_PARAMETER(argc); /* Default setting is no rows of result */ pCsr->pgno = 1; pCsr->mxPgno = 0; if( idxNum & 2 ){ const char *zSchema; assert( argc>=1 ); zSchema = (const char*)sqlite3_value_text(argv[0]); pCsr->iDb = sqlite3FindDbName(db, zSchema); |
︙ | ︙ | |||
271 272 273 274 275 276 277 | } if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); return rc; } static int dbpageColumn( | | | | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | } if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); return rc; } static int dbpageColumn( sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i ){ DbpageCursor *pCsr = (DbpageCursor *)pCursor; int rc = SQLITE_OK; switch( i ){ case 0: { /* pgno */ sqlite3_result_int(ctx, pCsr->pgno); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
69 70 71 72 73 74 75 | assert( pExpr->iColumn < pExpr->iTable ); assert( pExpr->iColumn >= 0 ); assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } | | > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | assert( pExpr->iColumn < pExpr->iTable ); assert( pExpr->iColumn >= 0 ); assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } if( op==TK_VECTOR || (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER) ){ assert( ExprUseXList(pExpr) ); return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); } if( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) ); |
︙ | ︙ | |||
262 263 264 265 266 267 268 | } break; } if( op==TK_CAST || op==TK_UPLUS ){ p = p->pLeft; continue; } | | > > | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | } break; } if( op==TK_CAST || op==TK_UPLUS ){ p = p->pLeft; continue; } if( op==TK_VECTOR || (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER) ){ assert( ExprUseXList(p) ); p = p->x.pList->a[0].pExpr; continue; } if( op==TK_COLLATE ){ assert( !ExprHasProperty(p, EP_IntValue) ); pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); |
︙ | ︙ | |||
4261 4262 4263 4264 4265 4266 4267 | assert( pParse->iSelfTab!=0 ); if( pParse->iSelfTab>0 ){ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); }else{ iAddr = 0; } sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); | > > > > > | | 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 | assert( pParse->iSelfTab!=0 ); if( pParse->iSelfTab>0 ){ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); }else{ iAddr = 0; } sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0 && (pTab->tabFlags & TF_Strict)!=0 ){ int p3 = 2+(int)(pCol - pTab->aCol); sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE); }else if( pCol->affinity>=SQLITE_AFF_TEXT ){ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); } if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); if( pParse->nErr>nErr ) pParse->db->errByteOffset = -1; } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ |
︙ | ︙ | |||
7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 | static void findOrCreateAggInfoColumn( Parse *pParse, /* Parsing context */ AggInfo *pAggInfo, /* The AggInfo object to search and/or modify */ Expr *pExpr /* Expr describing the column to find or insert */ ){ struct AggInfo_col *pCol; int k; assert( pAggInfo->iFirstReg==0 ); pCol = pAggInfo->aCol; for(k=0; k<pAggInfo->nColumn; k++, pCol++){ if( pCol->pCExpr==pExpr ) return; if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn && pExpr->op!=TK_IF_NULL_ROW ){ goto fix_up_expr; } } k = addAggInfoColumn(pParse->db, pAggInfo); if( k<0 ){ /* OOM on resize */ assert( pParse->db->mallocFailed ); return; } pCol = &pAggInfo->aCol[k]; assert( ExprUseYTab(pExpr) ); pCol->pTab = pExpr->y.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iSorterColumn = -1; | > > > > > > | 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 | static void findOrCreateAggInfoColumn( Parse *pParse, /* Parsing context */ AggInfo *pAggInfo, /* The AggInfo object to search and/or modify */ Expr *pExpr /* Expr describing the column to find or insert */ ){ struct AggInfo_col *pCol; int k; int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; assert( mxTerm <= SMXV(i16) ); assert( pAggInfo->iFirstReg==0 ); pCol = pAggInfo->aCol; for(k=0; k<pAggInfo->nColumn; k++, pCol++){ if( pCol->pCExpr==pExpr ) return; if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn && pExpr->op!=TK_IF_NULL_ROW ){ goto fix_up_expr; } } k = addAggInfoColumn(pParse->db, pAggInfo); if( k<0 ){ /* OOM on resize */ assert( pParse->db->mallocFailed ); return; } if( k>mxTerm ){ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); k = mxTerm; } pCol = &pAggInfo->aCol[k]; assert( ExprUseYTab(pExpr) ); pCol->pTab = pExpr->y.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iSorterColumn = -1; |
︙ | ︙ | |||
7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 | fix_up_expr: ExprSetVVAProperty(pExpr, EP_NoReduce); assert( pExpr->pAggInfo==0 || pExpr->pAggInfo==pAggInfo ); pExpr->pAggInfo = pAggInfo; if( pExpr->op==TK_COLUMN ){ pExpr->op = TK_AGG_COLUMN; } pExpr->iAgg = (i16)k; } /* ** This is the xExprCallback for a tree walker. It is used to ** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates ** for additional information. | > | 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 | fix_up_expr: ExprSetVVAProperty(pExpr, EP_NoReduce); assert( pExpr->pAggInfo==0 || pExpr->pAggInfo==pAggInfo ); pExpr->pAggInfo = pAggInfo; if( pExpr->op==TK_COLUMN ){ pExpr->op = TK_AGG_COLUMN; } assert( k <= SMXV(pExpr->iAgg) ); pExpr->iAgg = (i16)k; } /* ** This is the xExprCallback for a tree walker. It is used to ** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates ** for additional information. |
︙ | ︙ | |||
7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 | && pWalker->walkerDepth==pExpr->op2 && pExpr->pAggInfo==0 ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; i<pAggInfo->nFunc; i++, pItem++){ if( NEVER(pItem->pFExpr==pExpr) ) break; if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ break; } } | > > > > > > | | 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 | && pWalker->walkerDepth==pExpr->op2 && pExpr->pAggInfo==0 ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; assert( mxTerm <= SMXV(i16) ); for(i=0; i<pAggInfo->nFunc; i++, pItem++){ if( NEVER(pItem->pFExpr==pExpr) ) break; if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ break; } } if( i>mxTerm ){ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); i = mxTerm; assert( i<pAggInfo->nFunc ); }else if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ u8 enc = ENC(pParse->db); i = addAggInfoFunc(pParse->db, pAggInfo); if( i>=0 ){ int nArg; assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
︙ | ︙ | |||
7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 | } } } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(pExpr, EP_NoReduce); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; }else{ return WRC_Continue; } } | > | 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 | } } } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(pExpr, EP_NoReduce); assert( i <= SMXV(pExpr->iAgg) ); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; }else{ return WRC_Continue; } } |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1665 1666 1667 1668 1669 1670 1671 | static void concatFuncCore( sqlite3_context *context, int argc, sqlite3_value **argv, int nSep, const char *zSep ){ | | > | < | 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 | static void concatFuncCore( sqlite3_context *context, int argc, sqlite3_value **argv, int nSep, const char *zSep ){ i64 j, n = 0; int i; char *z; for(i=0; i<argc; i++){ n += sqlite3_value_bytes(argv[i]); } n += (argc-1)*(i64)nSep; z = sqlite3_malloc64(n+1); if( z==0 ){ sqlite3_result_error_nomem(context); return; } j = 0; for(i=0; i<argc; i++){ if( sqlite3_value_type(argv[i])!=SQLITE_NULL ){ int k = sqlite3_value_bytes(argv[i]); const char *v = (const char*)sqlite3_value_text(argv[i]); if( v!=0 ){ if( j>0 && nSep>0 ){ memcpy(&z[j], zSep, nSep); j += nSep; } memcpy(&z[j], v, k); |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
181 182 183 184 185 186 187 188 189 190 191 192 | char *zColAff; if( pTab->tabFlags & TF_Strict ){ if( iReg==0 ){ /* Move the previous opcode (which should be OP_MakeRecord) forward ** by one slot and insert a new OP_TypeCheck where the current ** OP_MakeRecord is found */ VdbeOp *pPrev; sqlite3VdbeAppendP4(v, pTab, P4_TABLE); pPrev = sqlite3VdbeGetLastOp(v); assert( pPrev!=0 ); assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); pPrev->opcode = OP_TypeCheck; | > > > | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | char *zColAff; if( pTab->tabFlags & TF_Strict ){ if( iReg==0 ){ /* Move the previous opcode (which should be OP_MakeRecord) forward ** by one slot and insert a new OP_TypeCheck where the current ** OP_MakeRecord is found */ VdbeOp *pPrev; int p3; sqlite3VdbeAppendP4(v, pTab, P4_TABLE); pPrev = sqlite3VdbeGetLastOp(v); assert( pPrev!=0 ); assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); pPrev->opcode = OP_TypeCheck; p3 = pPrev->p3; pPrev->p3 = 0; sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3); }else{ /* Insert an isolated OP_Typecheck */ sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol); sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } return; } |
︙ | ︙ |
Changes to src/json.c.
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 1288 | szType = a[0]>>4; if( szType<=11 ){ nExtra = 0; }else if( szType==12 ){ nExtra = 1; }else if( szType==13 ){ nExtra = 2; }else{ | > > | | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 | szType = a[0]>>4; if( szType<=11 ){ nExtra = 0; }else if( szType==12 ){ nExtra = 1; }else if( szType==13 ){ nExtra = 2; }else if( szType==14 ){ nExtra = 4; }else{ nExtra = 8; } if( szPayload<=11 ){ nNeeded = 0; }else if( szPayload<=0xff ){ nNeeded = 1; }else if( szPayload<=0xffff ){ nNeeded = 2; |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0); #endif #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms<-1 ) return SQLITE_RANGE; #ifdef SQLITE_ENABLE_SETLK_TIMEOUT db->setlkTimeout = ms; db->setlkFlags = flags; sqlite3BtreeEnterAll(db); for(iDb=0; iDb<db->nDb; iDb++){ Btree *pBt = db->aDb[iDb].pBt; if( pBt ){ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt)); sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC); } } sqlite3BtreeLeaveAll(db); #endif #if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT) UNUSED_PARAMETER(db); UNUSED_PARAMETER(flags); #endif return SQLITE_OK; } | > > | 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 | int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0); #endif #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms<-1 ) return SQLITE_RANGE; #ifdef SQLITE_ENABLE_SETLK_TIMEOUT sqlite3_mutex_enter(db->mutex); db->setlkTimeout = ms; db->setlkFlags = flags; sqlite3BtreeEnterAll(db); for(iDb=0; iDb<db->nDb; iDb++){ Btree *pBt = db->aDb[iDb].pBt; if( pBt ){ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt)); sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC); } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); #endif #if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT) UNUSED_PARAMETER(db); UNUSED_PARAMETER(flags); #endif return SQLITE_OK; } |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
5053 5054 5055 5056 5057 5058 5059 | assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); /* Check that, if this to be a blocking lock, no locks that occur later ** in the following list than the lock being obtained are already held: ** | > | | | < < | | 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 | assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); /* Check that, if this to be a blocking lock, no locks that occur later ** in the following list than the lock being obtained are already held: ** ** 1. Recovery lock (ofst==2). ** 2. Checkpointer lock (ofst==1). ** 3. Write lock (ofst==0). ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). ** ** In other words, if this is a blocking lock, none of the locks that ** occur later in the above list than the lock being obtained may be ** held. */ #if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG) { u16 lockMask = (p->exclMask|p->sharedMask); assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( (ofst!=2 || lockMask==0) && (ofst!=1 || lockMask==0 || lockMask==2) && (ofst!=0 || lockMask<3) && (ofst<3 || lockMask<(1<<ofst)) )); } #endif |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 | */ if( !ret && GetLastError()==ERROR_IO_PENDING ){ DWORD nDelay = (nMs==0 ? INFINITE : nMs); DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay); if( res==WAIT_OBJECT_0 ){ ret = TRUE; }else if( res==WAIT_TIMEOUT ){ rc = SQLITE_BUSY_TIMEOUT; }else{ /* Some other error has occurred */ rc = SQLITE_IOERR_LOCK; } /* If it is still pending, cancel the LockFileEx() call. */ osCancelIo(hFile); | > > > > | 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 | */ if( !ret && GetLastError()==ERROR_IO_PENDING ){ DWORD nDelay = (nMs==0 ? INFINITE : nMs); DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay); if( res==WAIT_OBJECT_0 ){ ret = TRUE; }else if( res==WAIT_TIMEOUT ){ #if SQLITE_ENABLE_SETLK_TIMEOUT==1 rc = SQLITE_BUSY_TIMEOUT; #else rc = SQLITE_BUSY; #endif }else{ /* Some other error has occurred */ rc = SQLITE_IOERR_LOCK; } /* If it is still pending, cancel the LockFileEx() call. */ osCancelIo(hFile); |
︙ | ︙ | |||
4529 4530 4531 4532 4533 4534 4535 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); /* Check that, if this to be a blocking lock, no locks that occur later ** in the following list than the lock being obtained are already held: ** | > | | | < < | | 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); /* Check that, if this to be a blocking lock, no locks that occur later ** in the following list than the lock being obtained are already held: ** ** 1. Recovery lock (ofst==2). ** 2. Checkpointer lock (ofst==1). ** 3. Write lock (ofst==0). ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). ** ** In other words, if this is a blocking lock, none of the locks that ** occur later in the above list than the lock being obtained may be ** held. */ #if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG) { u16 lockMask = (p->exclMask|p->sharedMask); assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( (ofst!=2 || lockMask==0) && (ofst!=1 || lockMask==0 || lockMask==2) && (ofst!=0 || lockMask<3) && (ofst<3 || lockMask<(1<<ofst)) )); } #endif |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
699 700 701 702 703 704 705 706 707 708 709 710 711 712 | int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ #ifndef SQLITE_OMIT_WAL Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ char *zWal; /* File name for write-ahead log */ #endif }; /* ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS ** or CACHE_WRITE to sqlite3_db_status(). */ | > > > | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ #ifndef SQLITE_OMIT_WAL Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ char *zWal; /* File name for write-ahead log */ #endif #ifdef SQLITE_ENABLE_SETLK_TIMEOUT sqlite3 *dbWal; #endif }; /* ** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains ** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS ** or CACHE_WRITE to sqlite3_db_status(). */ |
︙ | ︙ | |||
7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 | ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, pPager->journalSizeLimit, &pPager->pWal ); } pagerFixMaplimit(pPager); return rc; } | > > > > > | 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 | ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, pPager->journalSizeLimit, &pPager->pWal ); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_OK ){ sqlite3WalDb(pPager->pWal, pPager->dbWal); } #endif } pagerFixMaplimit(pPager); return rc; } |
︙ | ︙ | |||
7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 | } /* ** Set the database handle used by the wal layer to determine if ** blocking locks are required. */ void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ if( pagerUseWal(pPager) ){ sqlite3WalDb(pPager->pWal, db); } } #endif #ifdef SQLITE_ENABLE_SNAPSHOT | > | 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 | } /* ** Set the database handle used by the wal layer to determine if ** blocking locks are required. */ void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ pPager->dbWal = db; if( pagerUseWal(pPager) ){ sqlite3WalDb(pPager->pWal, db); } } #endif #ifdef SQLITE_ENABLE_SNAPSHOT |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
412 413 414 415 416 417 418 419 420 421 422 423 424 425 | longvalue = va_arg(ap,unsigned long int); } }else{ longvalue = va_arg(ap,unsigned int); } prefix = 0; } if( longvalue==0 ) flag_alternateform = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); } if( precision<etBUFSIZE-10-etBUFSIZE/3 ){ nOut = etBUFSIZE; zOut = buf; | > > > > > > > > | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | longvalue = va_arg(ap,unsigned long int); } }else{ longvalue = va_arg(ap,unsigned int); } prefix = 0; } #if WHERETRACE_ENABLED if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0; #endif #if TREETRACE_ENABLED if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0; #endif if( longvalue==0 ) flag_alternateform = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); } if( precision<etBUFSIZE-10-etBUFSIZE/3 ){ nOut = etBUFSIZE; zOut = buf; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
592 593 594 595 596 597 598 | ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); | | > > > > | > > > > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){ /* This branch runs if the query contains one or more RIGHT or FULL ** JOINs. If only a single table on the left side of this join ** contains the zName column, then this branch is a no-op. ** But if there are two or more tables on the left side ** of the join, construct a coalesce() function that gathers all ** such tables. Raise an error if more than one of those references ** to zName is not also within a prior USING clause. ** ** We really ought to raise an error if there are two or more ** non-USING references to zName on the left of an INNER or LEFT ** JOIN. But older versions of SQLite do not do that, so we avoid ** adding a new error so as to not break legacy applications. */ ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */ static const Token tkCoalesce = { "coalesce", 8 }; assert( pE1!=0 ); ExprSetProperty(pE1, EP_CanBeNull); while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol, pRight->fg.isSynthUsing)!=0 ){ if( pSrc->a[iLeft].fg.isUsing==0 || sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0 ){ sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()", zName); break; } pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); } if( pFuncArgs ){ pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0); if( pE1 ){ pE1->affExpr = SQLITE_AFF_DEFER; } } }else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){ assert( pE1!=0 ); ExprSetProperty(pE1, EP_CanBeNull); } pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol); sqlite3SrcItemColumnUsed(pRight, iRightCol); pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); assert( pE2!=0 || pEq==0 ); if( pEq ){ ExprSetProperty(pEq, joinType); |
︙ | ︙ | |||
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 | sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else zType = columnType(&sNC, p, 0, 0, 0); #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } /* ** Compute the column names for a SELECT statement. ** | > > > > | 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 | sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else zType = columnType(&sNC, p, 0, 0, 0); #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(pTabList); UNUSED_PARAMETER(pEList); #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } /* ** Compute the column names for a SELECT statement. ** |
︙ | ︙ | |||
4232 4233 4234 4235 4236 4237 4238 | ** (2a) the outer query must not be a join and ** (2b) the outer query must not use subqueries ** other than the one FROM-clause subquery that is a candidate ** for flattening. (This is due to ticket [2f7170d73bf9abf80] ** from 2015-02-09.) ** ** (3) If the subquery is the right operand of a LEFT JOIN then | | | | | 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 | ** (2a) the outer query must not be a join and ** (2b) the outer query must not use subqueries ** other than the one FROM-clause subquery that is a candidate ** for flattening. (This is due to ticket [2f7170d73bf9abf80] ** from 2015-02-09.) ** ** (3) If the subquery is the right operand of a LEFT JOIN then ** (3a) the subquery may not be a join ** (**) Was (3b): "the FROM clause of the subquery may not contain ** a virtual table" ** (**) Was: "The outer query may not have a GROUP BY." This case ** is now managed correctly ** (3d) the outer query may not be DISTINCT. ** See also (26) for restrictions on RIGHT JOIN. ** ** (4) The subquery can not be DISTINCT. ** |
︙ | ︙ | |||
4450 4451 4452 4453 4454 4455 4456 | ** ** which is not at all the same thing. ** ** See also tickets #306, #350, and #3300. */ if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ if( pSubSrc->nSrc>1 /* (3a) */ | | | 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 | ** ** which is not at all the same thing. ** ** See also tickets #306, #350, and #3300. */ if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ if( pSubSrc->nSrc>1 /* (3a) */ /**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */ || (p->selFlags & SF_Distinct)!=0 /* (3d) */ || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ ){ return 0; } isOuterJoin = 1; } |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
883 884 885 886 887 888 889 | const char *z2 = z; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); } /* ** Return the length of a string in characters. Multibyte UTF8 characters | | > | > > > > > > > > | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | const char *z2 = z; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); } /* ** Return the length of a string in characters. Multibyte UTF8 characters ** count as a single character for single-width characters, or as two ** characters for double-width characters. */ static int strlenChar(const char *z){ int n = 0; while( *z ){ if( (0x80&z[0])==0 ){ n++; z++; }else{ int u = 0; int len = decodeUtf8((const u8*)z, &u); z += len; n += cli_wcwidth(u); } } return n; } /* ** Return open FILE * if zFile exists, can be opened for read ** and is an ordinary file or a character stream source. |
︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | ** below by the ../tool/mkshellc.tcl script. Before processing that included ** code, we need to override some macros to make the included program code ** work here in the middle of this regular program. */ #define SQLITE_EXTENSION_INIT1 #define SQLITE_EXTENSION_INIT2(X) (void)(X) | < | < < < | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 | ** below by the ../tool/mkshellc.tcl script. Before processing that included ** code, we need to override some macros to make the included program code ** work here in the middle of this regular program. */ #define SQLITE_EXTENSION_INIT1 #define SQLITE_EXTENSION_INIT2(X) (void)(X) INCLUDE ../ext/misc/windirent.h INCLUDE ../ext/misc/memtrace.c INCLUDE ../ext/misc/pcachetrace.c INCLUDE ../ext/misc/shathree.c INCLUDE ../ext/misc/sha1.c INCLUDE ../ext/misc/uint.c INCLUDE ../ext/misc/decimal.c INCLUDE ../ext/misc/percentile.c |
︙ | ︙ | |||
9319 9320 9321 9322 9323 9324 9325 | } open_db(p, 0); rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_schema UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " | | > | 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 | } open_db(p, 0); rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_schema UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " "WHERE type!='meta' AND sql NOTNULL" " AND name NOT LIKE 'sqlite__%' ESCAPE '_' " "ORDER BY x", callback, &data, 0 ); if( rc==SQLITE_OK ){ sqlite3_stmt *pStmt; rc = sqlite3_prepare_v2(p->db, "SELECT rowid FROM sqlite_schema" |
︙ | ︙ | |||
10795 10796 10797 10798 10799 10800 10801 | if( !bGlob ){ appendText(&sSelect, " ESCAPE '\\' ", 0); } appendText(&sSelect, " AND ", 0); sqlite3_free(zQarg); } if( bNoSystemTabs ){ | | | 10801 10802 10803 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 | if( !bGlob ){ appendText(&sSelect, " ESCAPE '\\' ", 0); } appendText(&sSelect, " AND ", 0); sqlite3_free(zQarg); } if( bNoSystemTabs ){ appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0); } appendText(&sSelect, "sql IS NOT NULL" " ORDER BY snum, rowid", 0); if( bDebug ){ sqlite3_fprintf(p->out, "SQL: %s;\n", sSelect.z); }else{ rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); |
︙ | ︙ | |||
11226 11227 11228 11229 11230 11231 11232 | zSql = "SELECT lower(name) as tname FROM sqlite_schema" " WHERE type='table' AND coalesce(rootpage,0)>1" " UNION ALL SELECT 'sqlite_schema'" " ORDER BY 1 collate nocase"; }else{ zSql = "SELECT lower(name) as tname FROM sqlite_schema" " WHERE type='table' AND coalesce(rootpage,0)>1" | | | 11232 11233 11234 11235 11236 11237 11238 11239 11240 11241 11242 11243 11244 11245 11246 | zSql = "SELECT lower(name) as tname FROM sqlite_schema" " WHERE type='table' AND coalesce(rootpage,0)>1" " UNION ALL SELECT 'sqlite_schema'" " ORDER BY 1 collate nocase"; }else{ zSql = "SELECT lower(name) as tname FROM sqlite_schema" " WHERE type='table' AND coalesce(rootpage,0)>1" " AND name NOT LIKE 'sqlite__%' ESCAPE '_'" " ORDER BY 1 collate nocase"; } sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); initText(&sQuery); initText(&sSql); appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0); zSep = "VALUES("; |
︙ | ︙ | |||
11291 11292 11293 11294 11295 11296 11297 | } #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE) { int lrc; char *zRevText = /* Query for reversible to-blob-to-text check */ "SELECT lower(name) as tname FROM sqlite_schema\n" "WHERE type='table' AND coalesce(rootpage,0)>1\n" | | | 11297 11298 11299 11300 11301 11302 11303 11304 11305 11306 11307 11308 11309 11310 11311 | } #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE) { int lrc; char *zRevText = /* Query for reversible to-blob-to-text check */ "SELECT lower(name) as tname FROM sqlite_schema\n" "WHERE type='table' AND coalesce(rootpage,0)>1\n" "AND name NOT LIKE 'sqlite__%%' ESCAPE '_'%s\n" "ORDER BY 1 collate nocase"; zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : ""); zRevText = sqlite3_mprintf( /* lower-case query is first run, producing upper-case query. */ "with tabcols as materialized(\n" "select tname, cname\n" "from (" |
︙ | ︙ | |||
11487 11488 11489 11490 11491 11492 11493 | appendText(&s, zDbName, '\''); appendText(&s, "||'.'||name FROM ", 0); } appendText(&s, zDbName, '"'); appendText(&s, ".sqlite_schema ", 0); if( c=='t' ){ appendText(&s," WHERE type IN ('table','view')" | | | 11493 11494 11495 11496 11497 11498 11499 11500 11501 11502 11503 11504 11505 11506 11507 | appendText(&s, zDbName, '\''); appendText(&s, "||'.'||name FROM ", 0); } appendText(&s, zDbName, '"'); appendText(&s, ".sqlite_schema ", 0); if( c=='t' ){ appendText(&s," WHERE type IN ('table','view')" " AND name NOT LIKE 'sqlite__%' ESCAPE '_'" " AND name LIKE ?1", 0); }else{ appendText(&s," WHERE type='index'" " AND tbl_name LIKE ?1", 0); } } rc = sqlite3_finalize(pStmt); |
︙ | ︙ | |||
11581 11582 11583 11584 11585 11586 11587 | int ctrlCode; /* Integer code for that option */ int unSafe; /* Not valid unless --unsafe-testing */ const char *zUsage; /* Usage notes */ } aCtrl[] = { {"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" }, {"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" }, /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/ | | | 11587 11588 11589 11590 11591 11592 11593 11594 11595 11596 11597 11598 11599 11600 11601 | int ctrlCode; /* Integer code for that option */ int unSafe; /* Not valid unless --unsafe-testing */ const char *zUsage; /* Usage notes */ } aCtrl[] = { {"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" }, {"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" }, /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/ {"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "SIZE INT-ARRAY"}, {"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" }, {"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" }, {"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..." }, {"fk_no_action", SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN" }, {"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"}, {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" }, {"json_selfcheck", SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN" }, |
︙ | ︙ | |||
11919 11920 11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 | isOk = 1; }else{ rc2 = booleanValue(azArg[2]); isOk = 3; } sqlite3_test_control(testctrl, &rc2); break; case SQLITE_TESTCTRL_FAULT_INSTALL: { int kk; int bShowHelp = nArg<=2; isOk = 3; for(kk=2; kk<nArg; kk++){ const char *z = azArg[kk]; if( z[0]=='-' && z[1]=='-' ) z++; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 11925 11926 11927 11928 11929 11930 11931 11932 11933 11934 11935 11936 11937 11938 11939 11940 11941 11942 11943 11944 11945 11946 11947 11948 11949 11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961 11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979 11980 11981 | isOk = 1; }else{ rc2 = booleanValue(azArg[2]); isOk = 3; } sqlite3_test_control(testctrl, &rc2); break; case SQLITE_TESTCTRL_BITVEC_TEST: { /* Examples: ** .testctrl bitvec_test 100 6,1 -- Show BITVEC constants ** .testctrl bitvec_test 1000 1,12,7,3 -- Simple test ** ---- -------- ** size of Bitvec -----^ ^--- aOp array. 0 added at end. ** ** See comments on sqlite3BitvecBuiltinTest() for more information ** about the aOp[] array. */ int iSize; const char *zTestArg; int nOp; int ii, jj, x; int *aOp; if( nArg!=4 ){ sqlite3_fprintf(stderr, "ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n" ); rc = 1; goto meta_command_exit; } isOk = 3; iSize = (int)integerValue(azArg[2]); zTestArg = azArg[3]; nOp = (int)strlen(zTestArg)+1; aOp = malloc( sizeof(int)*(nOp+1) ); shell_check_oom(aOp); memset(aOp, 0, sizeof(int)*(nOp+1) ); for(ii = jj = x = 0; zTestArg[ii]!=0; ii++){ if( IsDigit(zTestArg[ii]) ){ x = x*10 + zTestArg[ii] - '0'; }else{ aOp[jj++] = x; x = 0; } } aOp[jj] = x; x = sqlite3_test_control(testctrl, iSize, aOp); sqlite3_fprintf(p->out, "result: %d\n", x); free(aOp); break; } case SQLITE_TESTCTRL_FAULT_INSTALL: { int kk; int bShowHelp = nArg<=2; isOk = 3; for(kk=2; kk<nArg; kk++){ const char *z = azArg[kk]; if( z[0]=='-' && z[1]=='-' ) z++; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
164 165 166 167 168 169 170 | ** ** <blockquote><pre> ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); ** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** | | | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | ** ** <blockquote><pre> ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); ** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** ** ^The sqlite3_version[] string constant contains the text of the ** [SQLITE_VERSION] macro. ^The sqlite3_libversion() function returns a ** pointer to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to ** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built ** using an edited copy of [the amalgamation], then the last four characters |
︙ | ︙ | |||
366 367 368 369 370 371 372 | ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], ** that allows an application to run multiple statements of SQL ** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, | | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], ** that allows an application to run multiple statements of SQL ** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, ** semicolon-separated SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to ** sqlite3_exec() is not NULL, then it is invoked for each result row ** coming out of the evaluated SQL statements. ^The 4th argument to ** sqlite3_exec() is relayed through to the 1st argument of each ** callback invocation. ^If the callback pointer to sqlite3_exec() ** is NULL, then no callback is ever invoked and result rows are |
︙ | ︙ | |||
399 400 401 402 403 404 405 | ** ^The 2nd argument to the sqlite3_exec() callback function is the ** number of columns in the result. ^The 3rd argument to the sqlite3_exec() ** callback is an array of pointers to strings obtained as if from ** [sqlite3_column_text()], one for each column. ^If an element of a ** result row is NULL then the corresponding string pointer for the ** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the ** sqlite3_exec() callback is an array of pointers to strings where each | | | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | ** ^The 2nd argument to the sqlite3_exec() callback function is the ** number of columns in the result. ^The 3rd argument to the sqlite3_exec() ** callback is an array of pointers to strings obtained as if from ** [sqlite3_column_text()], one for each column. ^If an element of a ** result row is NULL then the corresponding string pointer for the ** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the ** sqlite3_exec() callback is an array of pointers to strings where each ** entry represents the name of a corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer ** to an empty string, or a pointer that contains only whitespace and/or ** SQL comments, then no SQL statements are evaluated and the database ** is not changed. ** |
︙ | ︙ | |||
585 586 587 588 589 590 591 | ** though future versions of SQLite might change so that an error is ** raised if any of the disallowed bits are passed into sqlite3_open_v2(). ** Applications should not depend on the historical behavior. ** ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into | | | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | ** though future versions of SQLite might change so that an error is ** raised if any of the disallowed bits are passed into sqlite3_open_v2(). ** Applications should not depend on the historical behavior. ** ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into ** [sqlite3_open_v2()] has historically been a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ |
︙ | ︙ | |||
679 680 681 682 683 684 685 | /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods ** of an [sqlite3_io_methods] object. These values are ordered from | | | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 | /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods ** of an [sqlite3_io_methods] object. These values are ordered from ** least restrictive to most restrictive. ** ** The argument to xLock() is always SHARED or higher. The argument to ** xUnlock is either SHARED or NONE. */ #define SQLITE_LOCK_NONE 0 /* xUnlock() only */ #define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */ #define SQLITE_LOCK_RESERVED 2 /* xLock() only */ |
︙ | ︙ | |||
995 996 997 998 999 1000 1001 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some ** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. ** ** <li>[[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of | | | | 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 | ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some ** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. ** ** <li>[[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of ** all [VFSes] in the VFS stack. The names of all VFS shims and the ** final bottom-level VFS are written into memory obtained from ** [sqlite3_malloc()] and the result is stored in the char* variable ** that the fourth parameter of [sqlite3_file_control()] points to. ** The caller is responsible for freeing the memory when done. As with ** all file-control actions, there is no guarantee that this will actually ** do anything. Callers should initialize the char* variable to a NULL ** pointer in case this file-control is not implemented. This file-control ** is intended for diagnostic use only. ** ** <li>[[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 opcode 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. ** ** <li>[[SQLITE_FCNTL_PRAGMA]] ** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] ** file control is sent to the open [sqlite3_file] object corresponding |
︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 | ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode | | | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode ** transaction open on the database or not. It is only available on unix. The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that ** currently has an SQL transaction open on the database. It is set to 0 if ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes. |
︙ | ︙ | |||
1624 1625 1626 1627 1628 1629 1630 | ** the library (perhaps it is unable to allocate a needed resource such ** as a mutex) it returns an [error code] other than [SQLITE_OK]. ** ** ^The sqlite3_initialize() routine is called internally by many other ** SQLite interfaces so that an application usually does not need to ** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] ** calls sqlite3_initialize() so the SQLite library will be automatically | | | 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 | ** the library (perhaps it is unable to allocate a needed resource such ** as a mutex) it returns an [error code] other than [SQLITE_OK]. ** ** ^The sqlite3_initialize() routine is called internally by many other ** SQLite interfaces so that an application usually does not need to ** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] ** calls sqlite3_initialize() so the SQLite library will be automatically ** initialized when [sqlite3_open()] is called if it has not been initialized ** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] ** compile-time option, then the automatic calls to sqlite3_initialize() ** are omitted and the application must call sqlite3_initialize() directly ** prior to using any other SQLite interface. For maximum portability, ** it is recommended that applications always invoke sqlite3_initialize() ** directly prior to using any other SQLite interface. Future releases ** of SQLite may require this. In other words, the behavior exhibited |
︙ | ︙ | |||
1881 1882 1883 1884 1885 1886 1887 | ** ** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt> ** <dd> ^(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.)^ ** This option can be used to overload the default memory allocation | | | | | | 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 | ** ** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt> ** <dd> ^(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.)^ ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulates memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> ** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes a single argument of ** type int, interpreted as a boolean, which if true provides a hint to ** SQLite that it should avoid large memory allocations if possible. ** SQLite will run faster if it is free to make large memory allocations, ** but some applications might prefer to run slower in exchange for ** guarantees about memory fragmentation that are possible if large ** allocations are avoided. This hint is normally off. ** </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes a 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: ** <ul> ** <li> [sqlite3_hard_heap_limit64()] ** <li> [sqlite3_memory_used()] ** <li> [sqlite3_memory_highwater()] |
︙ | ︙ | |||
1940 1941 1942 1943 1944 1945 1946 | ** ^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 | | | 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 | ** ^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. </dd> ** ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs |
︙ | ︙ | |||
1969 1970 1971 1972 1973 1974 1975 | ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.</dd> ** ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd> ^(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 | | | 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 | ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.</dd> ** ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd> ^(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 of 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 ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will ** return [SQLITE_ERROR].</dd> ** |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 | ** <dd> ^(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.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which | | | | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 | ** <dd> ^(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.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off ** the current page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger ** function whenever that function is invoked. ^The second parameter to ** the logger function is a copy of the first parameter to the corresponding ** [sqlite3_log()] call and is intended to be a [result code] or an ** [extended result code]. ^The third parameter passed to the logger is ** a log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
︙ | ︙ | |||
2219 2220 2221 2222 2223 2224 2225 | /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second parameter to the [sqlite3_db_config()] interface. ** | | | 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second parameter to the [sqlite3_db_config()] interface. ** ** The [sqlite3_db_config()] interface is a var-args function. It takes a ** variable number of parameters, though always at least two. The number of ** parameters passed into sqlite3_db_config() depends on which of these ** constants is given as the second parameter. This documentation page ** refers to parameters beyond the second as "arguments". Thus, when this ** page says "the N-th argument" it means "the N-th parameter past the ** configuration option" or "the (N+2)-th parameter to sqlite3_db_config()". ** |
︙ | ︙ | |||
2353 2354 2355 2356 2357 2358 2359 | ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. ** There must be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. | | | | 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 | ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. ** There must be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to the state of either ** the C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** ** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> |
︙ | ︙ | |||
2472 2473 2474 2475 2476 2477 2478 | ** integer into which is written 0 or 1 to indicate whether the writable_schema ** is enabled or disabled following this call. ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] ** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates | | | 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 | ** integer into which is written 0 or 1 to indicate whether the writable_schema ** is enabled or disabled following this call. ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] ** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates ** the legacy behavior of the [ALTER TABLE RENAME] command such that it ** behaves as it did prior to [version 3.24.0] (2018-06-04). See the ** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for ** additional information. This feature can also be turned on and off ** using the [PRAGMA legacy_alter_table] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DML]] |
︙ | ︙ | |||
2521 2522 2523 2524 2525 2526 2527 | ** can also be controlled using the [PRAGMA trusted_schema] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] ** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly | | | 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 | ** can also be controlled using the [PRAGMA trusted_schema] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] ** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly ** created database files to have a schema format version number (the 4-byte ** integer found at offset 44 into the database header) of 1. This in turn ** means that the resulting database file will be readable and writable by ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, ** newly created databases are generally not understandable by SQLite versions ** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there ** is now scarcely any need to generate database files that are compatible ** all the way back to version 3.0.0, and so this setting is of little |
︙ | ︙ | |||
2548 2549 2550 2551 2552 2553 2554 | ** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in ** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears ** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() ** statistics. For statistics to be collected, the flag must be set on ** the database handle both when the SQL statement is prepared and when it ** is stepped. The flag is set (collection of statistics is enabled) ** by default. <p>This option takes two arguments: an integer and a pointer to | | | 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 | ** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in ** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears ** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() ** statistics. For statistics to be collected, the flag must be set on ** the database handle both when the SQL statement is prepared and when it ** is stepped. The flag is set (collection of statistics is enabled) ** by default. <p>This option takes two arguments: an integer and a pointer to ** an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after ** processing the first argument is written into the integer that the second ** argument points to. ** </dd> ** ** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]] |
︙ | ︙ | |||
2591 2592 2593 2594 2595 2596 2597 | ** </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]] ** <dt>SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE</dt> ** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the ** ability of the [ATTACH DATABASE] SQL command to open a database for writing. ** This capability is enabled by default. Applications can disable or | | | | 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 | ** </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]] ** <dt>SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE</dt> ** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the ** ability of the [ATTACH DATABASE] SQL command to open a database for writing. ** This capability is enabled by default. Applications can disable or ** reenable this capability using the current DBCONFIG option. If ** this capability is disabled, the [ATTACH] command will still work, ** but the database will be opened read-only. If this option is disabled, ** then the ability to create a new database using [ATTACH] is also disabled, ** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] ** option.<p> ** This option takes two arguments which are an integer and a pointer ** to an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the ability to ATTACH another database for writing, |
︙ | ︙ | |||
2626 2627 2628 2629 2630 2631 2632 | ** ** </dl> ** ** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3> ** ** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the ** overall call to [sqlite3_db_config()] has a total of four parameters. | | | 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 | ** ** </dl> ** ** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3> ** ** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the ** overall call to [sqlite3_db_config()] has a total of four parameters. ** The first argument (the third parameter to sqlite3_db_config()) is an integer. ** The second argument is a pointer to an integer. If the first argument is 1, ** then the option becomes enabled. If the first integer argument is 0, then the ** option is disabled. If the first argument is -1, then the option setting ** is unchanged. The second argument, the pointer to an integer, may be NULL. ** If the second argument is not NULL, then a value of 0 or 1 is written into ** the integer to which the second argument points, depending on whether the ** setting is disabled or enabled after applying any changes specified by |
︙ | ︙ | |||
2916 2917 2918 2919 2920 2921 2922 | ** independent tokens (they are part of the token in which they are ** embedded) and thus do not count as a statement terminator. ^Whitespace ** and comments that follow the final semicolon are ignored. ** ** ^These routines return 0 if the statement is incomplete. ^If a ** memory allocation fails, then SQLITE_NOMEM is returned. ** | | | 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 | ** independent tokens (they are part of the token in which they are ** embedded) and thus do not count as a statement terminator. ^Whitespace ** and comments that follow the final semicolon are ignored. ** ** ^These routines return 0 if the statement is incomplete. ^If a ** memory allocation fails, then SQLITE_NOMEM is returned. ** ** ^These routines do not parse the SQL statements and thus ** will not detect syntactically incorrect SQL. ** ** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior ** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked ** automatically by sqlite3_complete16(). If that initialization fails, ** then the return value from sqlite3_complete16() will be non-zero ** regardless of whether or not the input SQL is complete.)^ |
︙ | ︙ | |||
3033 3034 3035 3036 3037 3038 3039 | ** not support blocking locks, this function is a no-op. ** ** Passing 0 to this function disables blocking locks altogether. Passing ** -1 to this function requests that the VFS blocks for a long time - ** indefinitely if possible. The results of passing any other negative value ** are undefined. ** | | | 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 | ** not support blocking locks, this function is a no-op. ** ** Passing 0 to this function disables blocking locks altogether. Passing ** -1 to this function requests that the VFS blocks for a long time - ** indefinitely if possible. The results of passing any other negative value ** are undefined. ** ** Internally, each SQLite database handle stores two timeout values - the ** busy-timeout (used for rollback mode databases, or if the VFS does not ** support blocking locks) and the setlk-timeout (used for blocking locks ** on wal-mode databases). The sqlite3_busy_timeout() method sets both ** values, this function sets only the setlk-timeout value. Therefore, ** to configure separate busy-timeout and setlk-timeout values for a single ** database handle, call sqlite3_busy_timeout() followed by this function. ** |
︙ | ︙ | |||
3063 3064 3065 3066 3067 3068 3069 | /* ** 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. ** | | | 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 | /* ** 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. ** ** Definition: A <b>result table</b> is a memory data structure created by the ** [sqlite3_get_table()] interface. A result table records the ** complete query results from one or more queries. ** ** The table conceptually has a number of rows and columns. But ** these numbers are not part of the result table itself. These ** numbers are obtained separately. Let N be the number of rows ** and M be the number of columns. |
︙ | ︙ | |||
3206 3207 3208 3209 3210 3211 3212 | ** ^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 | | | | | | 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 | ** ^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 ** a no-op if it is called with a NULL pointer. Passing a NULL pointer ** to sqlite3_free() is harmless. After being freed, memory ** should neither be read nor written. Even reading previously freed ** memory might result in a segmentation fault or other severe error. ** Memory corruption, a segmentation fault, or other severe error ** 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) ** 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 ** 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. ** ^If M is the size of the prior allocation, then min(N,M) bytes of the ** prior allocation are copied into the beginning of the 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. ** ** ^The sqlite3_realloc64(X,N) interface 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 |
︙ | ︙ | |||
3280 3281 3282 3283 3284 3285 3286 | ** ^The [sqlite3_memory_used()] routine returns the number of bytes ** of memory currently outstanding (malloced but not freed). ** ^The [sqlite3_memory_highwater()] routine returns the maximum ** value of [sqlite3_memory_used()] since the high-water mark ** was last reset. ^The values returned by [sqlite3_memory_used()] and ** [sqlite3_memory_highwater()] include any overhead ** added by SQLite in its implementation of [sqlite3_malloc()], | | | 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 | ** ^The [sqlite3_memory_used()] routine returns the number of bytes ** of memory currently outstanding (malloced but not freed). ** ^The [sqlite3_memory_highwater()] routine returns the maximum ** value of [sqlite3_memory_used()] since the high-water mark ** was last reset. ^The values returned by [sqlite3_memory_used()] and ** [sqlite3_memory_highwater()] include any overhead ** added by SQLite in its implementation of [sqlite3_malloc()], ** but not overhead added by any underlying system library ** routines that [sqlite3_malloc()] may call. ** ** ^The memory high-water mark is reset to the current value of ** [sqlite3_memory_used()] if and only if the parameter to ** [sqlite3_memory_highwater()] is true. ^The value returned ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. |
︙ | ︙ | |||
3732 3733 3734 3735 3736 3737 3738 | ** <dd>The new database connection will use the "serialized" ** [threading mode].)^ This means the multiple threads can safely ** attempt to use the same database connection at the same time. ** (Mutexes will block any actual concurrency, but in this mode ** there is no harm in trying.) ** ** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt> | | | | 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 | ** <dd>The new database connection will use the "serialized" ** [threading mode].)^ This means the multiple threads can safely ** attempt to use the same database connection at the same time. ** (Mutexes will block any actual concurrency, but in this mode ** there is no harm in trying.) ** ** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt> ** <dd>The database is opened with [shared cache] enabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** The [use of shared cache mode is discouraged] and hence shared cache ** capabilities may be omitted from many builds of SQLite. In such cases, ** this option is a no-op. ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened with [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt> ** <dd>The database connection comes up in "extended result code mode". ** In other words, the database behaves as if ** [sqlite3_extended_result_codes(db,1)] were called on the database |
︙ | ︙ | |||
4075 4076 4077 4078 4079 4080 4081 | ** CAPI3REF: Create and Destroy VFS Filenames ** ** These interfaces are provided for use by [VFS shim] implementations and ** are not useful outside of that context. ** ** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of ** database filename D with corresponding journal file J and WAL file W and | | | 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 | ** CAPI3REF: Create and Destroy VFS Filenames ** ** These interfaces are provided for use by [VFS shim] implementations and ** are not useful outside of that context. ** ** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of ** database filename D with corresponding journal file J and WAL file W and ** an array P of N URI Key/Value pairs. The result from ** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that ** is safe to pass to routines like: ** <ul> ** <li> [sqlite3_uri_parameter()], ** <li> [sqlite3_uri_boolean()], ** <li> [sqlite3_uri_int64()], ** <li> [sqlite3_uri_key()], |
︙ | ︙ | |||
4158 4159 4160 4161 4162 4163 4164 | ** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text | | | | 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 | ** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text ** that describes the [result code] E, as UTF-8, or NULL if E is not a ** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** ** ^If the most recent error references a specific token in the input ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by ** sqlite3_error_offset() assumes that the input SQL is UTF-8. ** ^If the most recent error does not reference a specific token in the input ** SQL, then the sqlite3_error_offset() function returns -1. ** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. ** When that happens, the second error will be reported since these |
︙ | ︙ | |||
4265 4266 4267 4268 4269 4270 4271 | /* ** CAPI3REF: Run-Time Limit Categories ** KEYWORDS: {limit category} {*limit categories} ** ** These constants define various performance limits ** that can be lowered at run-time using [sqlite3_limit()]. | | | | 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 | /* ** CAPI3REF: Run-Time Limit Categories ** KEYWORDS: {limit category} {*limit categories} ** ** These constants define various performance limits ** that can be lowered at run-time using [sqlite3_limit()]. ** A concise description of these limits follows, and additional information ** is available at [limits | Limits in SQLite]. ** ** <dl> ** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt> ** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^ ** ** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt> ** <dd>The maximum length of an SQL statement, in bytes.</dd>)^ |
︙ | ︙ | |||
4331 4332 4333 4334 4335 4336 4337 | #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 /* ** CAPI3REF: Prepare Flags ** | | | 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 | #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 /* ** CAPI3REF: Prepare Flags ** ** These constants define various flags that can be passed into the ** "prepFlags" parameter of the [sqlite3_prepare_v3()] and ** [sqlite3_prepare16_v3()] interfaces. ** ** New flags may be added in future releases of SQLite. ** ** <dl> ** [[SQLITE_PREPARE_PERSISTENT]] ^(<dt>SQLITE_PREPARE_PERSISTENT</dt> |
︙ | ︙ | |||
4418 4419 4420 4421 4422 4423 4424 | ** up to the first zero terminator or until the nByte bytes have been read, ** whichever comes first. ^If nByte is zero, then no prepared ** statement is generated. ** If the caller knows that the supplied string is nul-terminated, then ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string <i>including</i> ** the nul-terminator. | | | 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 | ** up to the first zero terminator or until the nByte bytes have been read, ** whichever comes first. ^If nByte is zero, then no prepared ** statement is generated. ** If the caller knows that the supplied string is nul-terminated, then ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string <i>including</i> ** the nul-terminator. ** Note that nByte measures the length of the input in bytes, not ** characters, even for the UTF-16 interfaces. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only ** compile the first statement in zSql, so *pzTail is left pointing to ** what remains uncompiled. ** |
︙ | ︙ | |||
4552 4553 4554 4555 4556 4557 4558 | ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** and parameter :xyz is unbound, then sqlite3_sql() will return ** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() ** will return "SELECT 2345,NULL".)^ ** ** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory ** is available to hold the result, or if the result would exceed the | | | 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 | ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** and parameter :xyz is unbound, then sqlite3_sql() will return ** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() ** will return "SELECT 2345,NULL".)^ ** ** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory ** is available to hold the result, or if the result would exceed the ** maximum string length determined by the [SQLITE_LIMIT_LENGTH]. ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ** are managed by SQLite and are automatically freed when the prepared |
︙ | ︙ | |||
4740 4741 4742 4743 4744 4745 4746 | typedef struct sqlite3_value sqlite3_value; /* ** CAPI3REF: SQL Function Context Object ** ** The context in which an SQL function executes is stored in an ** sqlite3_context object. ^A pointer to an sqlite3_context object | | | | 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 | typedef struct sqlite3_value sqlite3_value; /* ** CAPI3REF: SQL Function Context Object ** ** The context in which an SQL function executes is stored in an ** sqlite3_context object. ^A pointer to an sqlite3_context object ** is always the first parameter to [application-defined SQL functions]. ** The application-defined SQL function implementation will pass this ** pointer through into calls to [sqlite3_result_int | sqlite3_result()], ** [sqlite3_aggregate_context()], [sqlite3_user_data()], ** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], ** and/or [sqlite3_set_auxdata()]. */ 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 the following ** templates: ** ** <ul> ** <li> ? ** <li> ?NNN ** <li> :VVV ** <li> @VVV |
︙ | ︙ | |||
4801 4802 4803 4804 4805 4806 4807 | ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is ** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 ** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) | | | | 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 | ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is ** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 ** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) ** found in the first character, which is removed, or in the absence of a BOM ** the byte order is the native byte order of the host ** machine for sqlite3_bind_text16() or the byte order specified in ** the 6th parameter for sqlite3_bind_text64().)^ ** ^If UTF16 input text contains invalid unicode ** characters, then SQLite might change those invalid characters ** into the unicode replacement character: U+FFFD. ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of <u>bytes</u> in the value, not the number of characters.)^ ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() ** is negative, then the length of the string is ** the number of bytes up to the first zero terminator. ** 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 ** 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 controls ** or indicates the lifetime of the object referenced by the third parameter. ** These three options exist: |
︙ | ︙ | |||
5033 5034 5035 5036 5037 5038 5039 | 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 | | | 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 | 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 a ** [SELECT] statement. ** ^The name of the database or table or column can be returned as ** either a UTF-8 or UTF-16 string. ^The _database_ routines return ** the database name, the _table_ routines return the table name, and ** the origin_ routines return the column name. ** ^The returned string is valid until the [prepared statement] is destroyed ** using [sqlite3_finalize()] or until the statement is automatically |
︙ | ︙ | |||
5477 5478 5479 5480 5481 5482 5483 | /* ** 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 | | | 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 | /* ** 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 ** or if the statement has never been evaluated, then sqlite3_finalize() returns ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then ** sqlite3_finalize(S) returns the appropriate [error code] or ** [extended error code]. ** ** ^The sqlite3_finalize(S) routine can be called at any point during ** the life cycle of [prepared statement] S: ** before statement S is ever evaluated, after |
︙ | ︙ | |||
5602 5603 5604 5605 5606 5607 5608 | ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** all application-defined SQL functions that do not need to be | | | | 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 | ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** all application-defined SQL functions that do not need to be ** used inside of triggers, views, CHECK constraints, or other elements of ** the database schema. This flag is especially recommended for SQL ** functions that have side effects or reveal internal application state. ** Without this flag, an attacker might be able to modify the schema of ** a database file to include invocations of the function with parameters ** chosen by the attacker, which the application will then execute when ** the database file is opened and read. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the |
︙ | ︙ | |||
5634 5635 5636 5637 5638 5639 5640 | ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate ** or aggregate window function. More details regarding the implementation ** of aggregate window functions are ** [user-defined window functions|available here]. ** ** ^(If the final parameter to sqlite3_create_function_v2() or | | | 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 | ** which case a regular aggregate function is created, or must both be ** non-NULL, in which case the new function may be used as either an aggregate ** or aggregate window function. More details regarding the implementation ** of aggregate window functions are ** [user-defined window functions|available here]. ** ** ^(If the final parameter to sqlite3_create_function_v2() or ** sqlite3_create_window_function() is not NULL, then it is the destructor for ** the application data pointer. The destructor is invoked when the function ** is deleted, either by being overloaded or when the database connection ** closes.)^ ^The destructor is also invoked if the call to ** sqlite3_create_function_v2() fails. ^When the destructor callback is ** invoked, it is passed a single argument which is a copy of the application ** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ** |
︙ | ︙ | |||
5709 5710 5711 5712 5713 5714 5715 | void (*xInverse)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** | | | 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 | void (*xInverse)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** ** These constants 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_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ |
︙ | ︙ | |||
5801 5802 5803 5804 5805 5806 5807 | ** ** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd> ** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_result_subtype()] to cause a sub-type to be associated with its ** result. ** Every function that invokes [sqlite3_result_subtype()] should have this ** property. If it does not, then the call to [sqlite3_result_subtype()] | | | 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 | ** ** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd> ** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call ** [sqlite3_result_subtype()] to cause a sub-type to be associated with its ** result. ** Every function that invokes [sqlite3_result_subtype()] should have this ** property. If it does not, then the call to [sqlite3_result_subtype()] ** might become a no-op if the function is used as a term in an ** [expression index]. On the other hand, SQL functions that never invoke ** [sqlite3_result_subtype()] should avoid setting this property, as the ** purpose of this property is to disable certain optimizations that are ** incompatible with subtypes. ** ** [[SQLITE_SELFORDER1]] <dt>SQLITE_SELFORDER1</dt><dd> ** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate |
︙ | ︙ | |||
5928 5929 5930 5931 5932 5933 5934 | ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** ** ^Within the [xUpdate] method of a [virtual table], the ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation ** that the xUpdate method call was invoked to implement and if | | | 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 | ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** ** ^Within the [xUpdate] method of a [virtual table], the ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation ** that the xUpdate method call was invoked to implement and if ** the prior [xColumn] method call that was invoked to extract ** the value for that column returned without setting a result (probably ** because it queried [sqlite3_vtab_nochange()] and found that the column ** was unchanging). ^Within an [xUpdate] method, any value for which ** sqlite3_value_nochange(X) is true will in all other respects appear ** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. |
︙ | ︙ | |||
6034 6035 6036 6037 6038 6039 6040 | unsigned int 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] | | | 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 | unsigned int 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 V and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a ** memory allocation fails. ^If V is a [pointer value], then the result ** of sqlite3_value_dup(V) is a NULL value. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer |
︙ | ︙ | |||
6072 6073 6074 6075 6076 6077 6078 | ** first time from within xFinal().)^ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory ** allocation error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is | | | 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 | ** first time from within xFinal().)^ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory ** allocation error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on the first successful call. Changing the ** value of N in any subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ Within the xFinal callback, it is customary to set ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no ** pointless memory allocations occur. ** ** ^SQLite automatically frees the memory allocated by |
︙ | ︙ | |||
6234 6235 6236 6237 6238 6239 6240 | ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought ** of as a secret key such that only code that knows the secret key is able ** to access the associated data. ** ** Security Warning: These interfaces should not be exposed in scripting ** languages or in other circumstances where it might be possible for an | | | 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 | ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought ** of as a secret key such that only code that knows the secret key is able ** to access the associated data. ** ** Security Warning: These interfaces should not be exposed in scripting ** languages or in other circumstances where it might be possible for an ** attacker to invoke them. Any agent that can invoke these interfaces ** can probably also take control of the process. ** ** Database connection client data is only available for SQLite ** version 3.44.0 ([dateof:3.44.0]) and later. ** ** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()]. */ |
︙ | ︙ | |||
6348 6349 6350 6351 6352 6353 6354 | ** the string length itself by searching the 2nd parameter for the first ** zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined ** function result. If the 3rd parameter is non-negative, then it ** must be the byte offset into the string where the NUL terminator would | | | 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 | ** the string length itself by searching the 2nd parameter for the first ** zero character. ** ^If the 3rd parameter to the sqlite3_result_text* interfaces ** is non-negative, then as many bytes (not characters) of the text ** pointed to by the 2nd parameter are taken as the application-defined ** function result. If the 3rd parameter is non-negative, then it ** must be the byte offset into the string where the NUL terminator would ** appear if the string were NUL terminated. If any NUL characters occur ** in the string at a byte offset that is less than the value of the 3rd ** parameter, then the resulting string will contain embedded NULs and the ** result of expressions operating on strings with embedded NULs is undefined. ** ^If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that ** function as the destructor on the text or BLOB result when it has ** finished using that result. |
︙ | ︙ | |||
6406 6407 6408 6409 6410 6411 6412 | ** [application-defined SQL function] using [sqlite3_value_pointer()]. ** ^If the D parameter is not NULL, then it is a pointer to a destructor ** for the P parameter. ^SQLite invokes D with P as its only argument ** when SQLite is finished with P. The T parameter should be a static ** string and preferably a string literal. The sqlite3_result_pointer() ** routine is part of the [pointer passing interface] added for SQLite 3.20.0. ** | | | 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 | ** [application-defined SQL function] using [sqlite3_value_pointer()]. ** ^If the D parameter is not NULL, then it is a pointer to a destructor ** for the P parameter. ^SQLite invokes D with P as its only argument ** when SQLite is finished with P. The T parameter should be a static ** string and preferably a string literal. The sqlite3_result_pointer() ** routine is part of the [pointer passing interface] added for SQLite 3.20.0. ** ** If these routines are called from within a different thread ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_blob64(sqlite3_context*,const void*, sqlite3_uint64,void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); |
︙ | ︙ | |||
6812 6813 6814 6815 6816 6817 6818 | sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Schema Name For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name | | | 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 | sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Schema Name For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name ** for the N-th database on database connection D, or a NULL pointer if N is ** out of range. An N value of 0 means the main database file. An N of 1 is ** the "temp" schema. Larger values of N correspond to various ATTACH-ed ** databases. ** ** Space to hold the string that is returned by sqlite3_db_name() is managed ** by SQLite itself. The string might be deallocated by any operation that ** changes the schema, including [ATTACH] or [DETACH] or calls to |
︙ | ︙ | |||
6907 6908 6909 6910 6911 6912 6913 | ** <dd>The SQLITE_TXN_NONE state means that no transaction is currently ** pending.</dd> ** ** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt> ** <dd>The SQLITE_TXN_READ state means that the database is currently ** in a read transaction. Content has been read from the database file ** but nothing in the database file has changed. The transaction state | | | | 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 | ** <dd>The SQLITE_TXN_NONE state means that no transaction is currently ** pending.</dd> ** ** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt> ** <dd>The SQLITE_TXN_READ state means that the database is currently ** in a read transaction. Content has been read from the database file ** but nothing in the database file has changed. The transaction state ** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are ** no other conflicting concurrent write transactions. The transaction ** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or ** [COMMIT].</dd> ** ** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt> ** <dd>The SQLITE_TXN_WRITE state means that the database is currently ** in a write transaction. Content has been written to the database file ** but has not yet committed. The transaction state will change to ** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd> */ #define SQLITE_TXN_NONE 0 #define SQLITE_TXN_READ 1 #define SQLITE_TXN_WRITE 2 /* ** CAPI3REF: Find the next prepared statement |
︙ | ︙ | |||
7197 7198 7199 7200 7201 7202 7203 | */ int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** These interfaces impose limits on the amount of heap memory that will be | | | 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 | */ int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** These interfaces impose limits on the amount of heap memory that will be ** used by all database connections within a single process. ** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay |
︙ | ︙ | |||
7255 7256 7257 7258 7259 7260 7261 | ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). ** <li> The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. ** </ul>)^ ** ** The circumstances under which SQLite will enforce the heap limits may | | | 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 | ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). ** <li> The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. ** </ul>)^ ** ** The circumstances under which SQLite will enforce the heap limits may ** change in future releases of SQLite. */ sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED |
︙ | ︙ | |||
7370 7371 7372 7373 7374 7375 7376 | ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. ** ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". | | | | 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 | ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. ** ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". ** If that does not work, it constructs a name "sqlite3_X_init" where ** X consists of the lower-case equivalent of all ASCII alphabetic ** characters in the filename from the last "/" to the first following ** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory |
︙ | ︙ | |||
7442 7443 7444 7445 7446 7447 7448 | ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked [SQLite extension] ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects an integer result as if the signature of the | | | 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 | ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked [SQLite extension] ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects an integer result as if the signature of the ** entry point were as follows: ** ** <blockquote><pre> ** int xEntryPoint( ** sqlite3 *db, ** const char **pzErrMsg, ** const struct sqlite3_api_routines *pThunk ** ); |
︙ | ︙ | |||
7606 7607 7608 7609 7610 7611 7612 | ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and might not be checked again by the byte code.)^ ^(The ** aConstraintUsage[].omit flag is an optimization hint. When the omit flag ** is left in its default setting of false, the constraint will always be | | | 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 | ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and might not be checked again by the byte code.)^ ^(The ** aConstraintUsage[].omit flag is an optimization hint. When the omit flag ** is left in its default setting of false, the constraint will always be ** checked separately in byte code. If the omit flag is changed to true, then ** the constraint may or may not be checked in byte code. In other words, ** when the omit flag is true there is no guarantee that the constraint will ** not be checked again using byte code.)^ ** ** ^The idxNum and idxStr values are recorded and passed into the ** [xFilter] method. ** ^[sqlite3_free()] is used to free idxStr if and only if |
︙ | ︙ | |||
7632 7633 7634 7635 7636 7637 7638 | ** ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** ** The xBestIndex method may optionally populate the idxFlags field with a ** mask of SQLITE_INDEX_SCAN_* flags. One such flag is ** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN] | | | 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 | ** ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** ** The xBestIndex method may optionally populate the idxFlags field with a ** mask of SQLITE_INDEX_SCAN_* flags. One such flag is ** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN] ** output to show the idxNum as hex instead of as decimal. Another flag is ** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will ** return at most one row. ** ** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then ** SQLite also assumes that if a call to the xUpdate() method is made as ** 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 |
︙ | ︙ | |||
7773 7774 7775 7776 7777 7778 7779 | ** ** ^The module name is registered on the [database connection] specified ** by the first parameter. ^The name of the module is given by the ** second parameter. ^The third parameter is a pointer to ** the implementation of the [virtual table module]. ^The fourth ** parameter is an arbitrary client data pointer that is passed through ** into the [xCreate] and [xConnect] methods of the virtual table module | | | 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 | ** ** ^The module name is registered on the [database connection] specified ** by the first parameter. ^The name of the module is given by the ** second parameter. ^The third parameter is a pointer to ** the implementation of the [virtual table module]. ^The fourth ** parameter is an arbitrary client data pointer that is passed through ** into the [xCreate] and [xConnect] methods of the virtual table module ** when a new virtual table is being created or reinitialized. ** ** ^The sqlite3_create_module_v2() interface has a fifth parameter which ** is a pointer to a destructor for the pClientData. ^SQLite will ** invoke the destructor function (if it is not NULL) when SQLite ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() |
︙ | ︙ | |||
7938 7939 7940 7941 7942 7943 7944 | ** and write access. ^If the flags parameter is zero, the BLOB is opened for ** read-only access. ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored ** in *ppBlob. Otherwise an [error code] is returned and, unless the error ** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided ** the API is not misused, it is always safe to call [sqlite3_blob_close()] | | | 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 | ** and write access. ^If the flags parameter is zero, the BLOB is opened for ** read-only access. ** ** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored ** in *ppBlob. Otherwise an [error code] is returned and, unless the error ** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided ** the API is not misused, it is always safe to call [sqlite3_blob_close()] ** on *ppBlob after this function returns. ** ** This function fails with SQLITE_ERROR if any of the following are true: ** <ul> ** <li> ^(Database zDb does not exist)^, ** <li> ^(Table zTable does not exist within database zDb)^, ** <li> ^(Table zTable is a WITHOUT ROWID table)^, ** <li> ^(Column zColumn does not exist)^, |
︙ | ︙ | |||
8058 8059 8060 8061 8062 8063 8064 | /* ** 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 | | | 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 | /* ** 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 ** incremental blob I/O routines can only read or overwrite existing ** blob content; they cannot change the size of a blob. ** ** 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 ** to this routine results in undefined and probably undesirable behavior. */ |
︙ | ︙ | |||
8208 8209 8210 8211 8212 8213 8214 | ** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function ** before calling sqlite3_initialize() or any other public sqlite3_ ** 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 | | | 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 | ** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function ** before calling sqlite3_initialize() or any other public sqlite3_ ** 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 be one of these ** integer constants: ** ** <ul> ** <li> SQLITE_MUTEX_FAST ** <li> SQLITE_MUTEX_RECURSIVE ** <li> SQLITE_MUTEX_STATIC_MAIN ** <li> SQLITE_MUTEX_STATIC_MEM |
︙ | ︙ | |||
8441 8442 8443 8444 8445 8446 8447 | #define SQLITE_MUTEX_STATIC_MASTER 2 /* ** CAPI3REF: Retrieve the mutex for a database connection ** METHOD: sqlite3 ** | | | 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 | #define SQLITE_MUTEX_STATIC_MASTER 2 /* ** CAPI3REF: Retrieve the mutex for a database connection ** METHOD: sqlite3 ** ** ^This interface returns a pointer to the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); |
︙ | ︙ | |||
8564 8565 8566 8567 8568 8569 8570 | #define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ #define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords | | | 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 | #define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */ #define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can use these routines to determine ** whether or not a specific identifier needs to be escaped (for example, ** by enclosing in double-quotes) so as not to confuse the parser. ** ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** ** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and |
︙ | ︙ | |||
8732 8733 8734 8735 8736 8737 8738 | ** ^The length returned by [sqlite3_str_length(X)] does not include the ** zero-termination byte. ** ** ^The [sqlite3_str_value(X)] method returns a pointer to the current ** content of the dynamic string under construction in X. The value ** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ** and might be freed or altered by any subsequent method on the same | | | 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 | ** ^The length returned by [sqlite3_str_length(X)] does not include the ** zero-termination byte. ** ** ^The [sqlite3_str_value(X)] method returns a pointer to the current ** content of the dynamic string under construction in X. The value ** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ** and might be freed or altered by any subsequent method on the same ** [sqlite3_str] object. Applications must not use the pointer returned by ** [sqlite3_str_value(X)] after any subsequent method call on the same ** object. ^Applications may change the content of the string returned ** by [sqlite3_str_value(X)] as long as they do not write into any bytes ** outside the range of 0 to [sqlite3_str_length(X)] and do not read or ** write any byte after any subsequent sqlite3_str method call. */ int sqlite3_str_errcode(sqlite3_str*); |
︙ | ︙ | |||
8818 8819 8820 8821 8822 8823 8824 | ** ** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt> ** <dd>This parameter returns the number of bytes of page cache ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] ** buffer and where forced to overflow to [sqlite3_malloc()]. The ** returned value includes allocations that overflowed because they | | | 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 | ** ** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] ** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt> ** <dd>This parameter returns the number of bytes of page cache ** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] ** buffer and where forced to overflow to [sqlite3_malloc()]. The ** returned value includes allocations that overflowed because they ** were too large (they were larger than the "sz" parameter to ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.</dd>)^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt> ** <dd>This parameter records the largest memory allocation request ** handed to the [pagecache memory allocator]. Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. |
︙ | ︙ | |||
8902 8903 8904 8905 8906 8907 8908 | ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt> ** <dd>This parameter returns the number of lookaside memory slots currently ** checked out.</dd>)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt> ** <dd>This parameter returns the number of malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; | | | | | | > | | > | 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 | ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt> ** <dd>This parameter returns the number of lookaside memory slots currently ** checked out.</dd>)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt> ** <dd>This parameter returns the number of malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.</dd>)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt> ** <dd>This parameter returns the number of malloc attempts that might have ** been satisfied using lookaside memory but failed due to the amount of ** memory requested being larger than the lookaside slot size. ** Only the high-water value is meaningful; ** the current value is always zero.</dd>)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] ** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt> ** <dd>This parameter returns the number of malloc attempts that might have ** been satisfied using lookaside memory but failed due to all lookaside ** memory already being in use. ** Only the high-water value is meaningful; ** the current value is always zero.</dd>)^ ** ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] ** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt> ** <dd>This parameter is similar to DBSTATUS_CACHE_USED, except that if a ** pager cache is shared between two or more connections the bytes of heap ** memory used by that pager cache is divided evenly between the attached ** connections.)^ In other words, if none of the pager caches associated ** with the database connection are shared, this request returns the same ** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are ** shared, the value returned by this call will be smaller than that returned ** by DBSTATUS_CACHE_USED. ^The highwater mark associated with ** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.</dd> ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated ** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. ** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt> ** <dd>This parameter returns the approximate number 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. ** </dd> |
︙ | ︙ | |||
8981 8982 8983 8984 8985 8986 8987 | ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> ** <dd>This parameter returns the number of dirty cache entries that have ** been written to disk in the middle of a transaction due to the page ** cache overflowing. Transactions are more efficient if they are written ** to disk all at once. When pages spill mid-transaction, that introduces | | | 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 | ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> ** <dd>This parameter returns the number of dirty cache entries that have ** been written to disk in the middle of a transaction due to the page ** cache overflowing. Transactions are more efficient if they are written ** to disk all at once. When pages spill mid-transaction, that introduces ** additional overhead. This parameter can be used to help identify ** inefficiencies that can be resolved by increasing the cache size. ** </dd> ** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> ** <dd>This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. |
︙ | ︙ | |||
9461 9462 9463 9464 9465 9466 9467 | ** lasts for the duration of the sqlite3_backup_step() call. ** ^Because the source database is not locked between calls to ** sqlite3_backup_step(), the source database may be modified mid-way ** through the backup process. ^If the source database is modified by an ** external process or via a database connection other than the one being ** used by the backup operation, then the backup will be automatically ** restarted by the next call to sqlite3_backup_step(). ^If the source | | | | 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 | ** lasts for the duration of the sqlite3_backup_step() call. ** ^Because the source database is not locked between calls to ** sqlite3_backup_step(), the source database may be modified mid-way ** through the backup process. ^If the source database is modified by an ** external process or via a database connection other than the one being ** used by the backup operation, then the backup will be automatically ** restarted by the next call to sqlite3_backup_step(). ^If the source ** database is modified by using the same database connection as is used ** by the backup operation, then the backup database is automatically ** updated at the same time. ** ** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b> ** ** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the ** application wishes to abandon the backup operation, the application ** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). ** ^The sqlite3_backup_finish() interfaces releases all ** resources associated with the [sqlite3_backup] object. ** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any ** active write-transaction on the destination database is rolled back. ** The [sqlite3_backup] object is invalid ** and may not be used following a call to sqlite3_backup_finish(). ** ** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no ** sqlite3_backup_step() errors occurred, regardless of whether or not ** sqlite3_backup_step() completed. ** ^If an out-of-memory condition or IO error occurred during any prior ** sqlite3_backup_step() call on the same [sqlite3_backup] object, then ** sqlite3_backup_finish() returns the corresponding [error code]. ** ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() ** is not a permanent error and does not affect the return value of |
︙ | ︙ | |||
10517 10518 10519 10520 10521 10522 10523 | ** See also: [sqlite3_stmt_scanstatus_reset()] */ int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ | | | | 10519 10520 10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 | ** See also: [sqlite3_stmt_scanstatus_reset()] */ int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ ); int sqlite3_stmt_scanstatus_v2( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ int flags, /* Mask of flags defined below */ void *pOut /* Result written here */ ); /* ** CAPI3REF: Prepared Statement Scan Status ** KEYWORDS: {scan status flags} */ #define SQLITE_SCANSTAT_COMPLEX 0x0001 |
︙ | ︙ | |||
10548 10549 10550 10551 10552 10553 10554 | void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction ** METHOD: sqlite3 ** ** ^If a write-transaction is open on [database connection] D when the | | | 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 10564 | void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction ** METHOD: sqlite3 ** ** ^If a write-transaction is open on [database connection] D when the ** [sqlite3_db_cacheflush(D)] interface is 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. ** |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
761 762 763 764 765 766 767 | #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof | | | 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof # define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) #endif /* ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as ** to avoid complaints from -fsanitize=strict-bounds. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) |
︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 | #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Macro SMXV(n) return the maximum value that can be held in variable n, ** assuming n is a signed integer type. UMXV(n) is similar for unsigned ** integer types. */ | | | | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) /* ** Macro SMXV(n) return the maximum value that can be held in variable n, ** assuming n is a signed integer type. UMXV(n) is similar for unsigned ** integer types. */ #define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1) #define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1) /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. ** ** ROUND8() always does the rounding, for any argument. ** |
︙ | ︙ | |||
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | ** 0x00002000 Constant propagation ** 0x00004000 Push-down optimization ** 0x00008000 After all FROM-clause analysis ** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated ** 0x00080000 NOT NULL strength reduction */ /* ** Macros for "wheretrace" */ extern u32 sqlite3WhereTrace; #if defined(SQLITE_DEBUG) \ | > | 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 | ** 0x00002000 Constant propagation ** 0x00004000 Push-down optimization ** 0x00008000 After all FROM-clause analysis ** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated ** 0x00080000 NOT NULL strength reduction ** 0x00100000 Pointers are all shown as zero */ /* ** Macros for "wheretrace" */ extern u32 sqlite3WhereTrace; #if defined(SQLITE_DEBUG) \ |
︙ | ︙ | |||
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 | ** 0x00004000 Show all WHERE terms at key points ** 0x00008000 Show the full SELECT statement at key places ** ** 0x00010000 Show more detail when printing WHERE terms ** 0x00020000 Show WHERE terms returned from whereScanNext() ** 0x00040000 Solver overview messages ** 0x00080000 Star-query heuristic */ /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** | > | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 | ** 0x00004000 Show all WHERE terms at key points ** 0x00008000 Show the full SELECT statement at key places ** ** 0x00010000 Show more detail when printing WHERE terms ** 0x00020000 Show WHERE terms returned from whereScanNext() ** 0x00040000 Solver overview messages ** 0x00080000 Star-query heuristic ** 0x00100000 Pointers are all shown as zero */ /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** |
︙ | ︙ | |||
1265 1266 1267 1268 1269 1270 1271 | ** The following value as a destructor means to use sqlite3DbFree(). ** The sqlite3DbFree() routine requires two parameters instead of the ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ | | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 | ** The following value as a destructor means to use sqlite3DbFree(). ** The sqlite3DbFree() routine requires two parameters instead of the ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ #define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does ** not support Writable Static Data (WSD) such as global and static variables. ** All variables must either be on the stack or dynamically allocated from ** the heap. When WSD is unsupported, the variable declarations scattered ** throughout the SQLite code must become constants instead. The SQLITE_WSD |
︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 | #define SQLITE_AFF_NONE 0x40 /* '@' */ #define SQLITE_AFF_BLOB 0x41 /* 'A' */ #define SQLITE_AFF_TEXT 0x42 /* 'B' */ #define SQLITE_AFF_NUMERIC 0x43 /* 'C' */ #define SQLITE_AFF_INTEGER 0x44 /* 'D' */ #define SQLITE_AFF_REAL 0x45 /* 'E' */ #define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */ #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** The SQLITE_AFF_MASK values masks off the significant bits of an ** affinity value. */ | > | 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 | #define SQLITE_AFF_NONE 0x40 /* '@' */ #define SQLITE_AFF_BLOB 0x41 /* 'A' */ #define SQLITE_AFF_TEXT 0x42 /* 'B' */ #define SQLITE_AFF_NUMERIC 0x43 /* 'C' */ #define SQLITE_AFF_INTEGER 0x44 /* 'D' */ #define SQLITE_AFF_REAL 0x45 /* 'E' */ #define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */ #define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */ #define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** The SQLITE_AFF_MASK values masks off the significant bits of an ** affinity value. */ |
︙ | ︙ | |||
2661 2662 2663 2664 2665 2666 2667 | /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** | | | | > > > > > > | > > > > > > > > > | | < | | | | 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 | /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** ** The aSortOrder[] and aColl[] arrays have nAllField slots each. There ** are nKeyField slots for the columns of an index then extra slots ** for the rowid or key at the end. The aSortOrder array is located after ** the aColl[] array. ** ** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL ** to indicate that this object is for use by a preupdate hook. When aSortFlags ** is NULL, then nAllField is uninitialized and no space is allocated for ** aColl[], so those fields may not be used. */ struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ u16 nKeyField; /* Number of key columns in the index */ u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ u8 *aSortFlags; /* Sort order for each column. */ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */ }; /* The size (in bytes) of a KeyInfo object with up to N fields. This includes ** the main body of the KeyInfo object and the aColl[] array of N elements, ** but does not count the memory used to hold aSortFlags[]. */ #define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*)) /* The size of a bare KeyInfo with no aColl[] entries */ #if FLEXARRAY+1 > 1 # define SZ_KEYINFO_0 offsetof(KeyInfo,aColl) #else # define SZ_KEYINFO_0 sizeof(KeyInfo) #endif /* ** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. */ #define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */ #define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */ /* ** This object holds a record which has been parsed out into individual ** fields, for the purposes of doing a comparison. ** ** A record is an object that contains one or more fields of data. ** Records are used to store the content of a table row and to store ** the key of an index. A blob encoding of a record is created by ** 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 closest to the key described by this object. This object might hold ** just a prefix of the key. The number of fields is given by nField. ** ** 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 nField elements) 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. */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */ Mem *aMem; /* Values for columns of the index */ union { char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */ i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */ } u; int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ |
︙ | ︙ | |||
2896 2897 2898 2899 2900 2901 2902 | ** fields do not need to be freed when deallocating the AggInfo structure. */ struct AggInfo { u8 directMode; /* Direct rendering mode means take data directly ** from source tables rather than from accumulators */ u8 useSortingIdx; /* In direct mode, reference the sorting index rather ** than the source table */ | | | | | 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 | ** fields do not need to be freed when deallocating the AggInfo structure. */ struct AggInfo { u8 directMode; /* Direct rendering mode means take data directly ** from source tables rather than from accumulators */ u8 useSortingIdx; /* In direct mode, reference the sorting index rather ** than the source table */ u32 nSortingColumn; /* Number of columns in the sorting index */ int sortingIdx; /* Cursor number of the sorting index */ int sortingIdxPTab; /* Cursor number of pseudo-table */ int iFirstReg; /* First register in range for aCol[] and aFunc[] */ ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ Expr *pCExpr; /* The original expression */ int iTable; /* Cursor number of the source table */ int iColumn; /* Column number within the source table */ int iSorterColumn; /* Column number in the sorting index */ } *aCol; int nColumn; /* Number of used entries in aCol[] */ int nAccumulator; /* Number of columns that show through to the output. ** Additional columns are used only as parameters to ** aggregate functions */ struct AggInfo_func { /* For each aggregate function */ Expr *pFExpr; /* Expression encoding the function */ |
︙ | ︙ | |||
4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 | void sqlite3ShowTrigger(const Trigger*); void sqlite3ShowTriggerList(const Trigger*); #endif #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3ShowWindow(const Window*); void sqlite3ShowWinFunc(const Window*); #endif #endif void sqlite3SetString(char **, sqlite3*, const char*); void sqlite3ProgressCheck(Parse*); void sqlite3ErrorMsg(Parse*, const char*, ...); int sqlite3ErrorToParser(sqlite3*,int); void sqlite3Dequote(char*); | > | 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 | void sqlite3ShowTrigger(const Trigger*); void sqlite3ShowTriggerList(const Trigger*); #endif #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3ShowWindow(const Window*); void sqlite3ShowWinFunc(const Window*); #endif void sqlite3ShowBitvec(Bitvec*); #endif void sqlite3SetString(char **, sqlite3*, const char*); void sqlite3ProgressCheck(Parse*); void sqlite3ErrorMsg(Parse*, const char*, ...); int sqlite3ErrorToParser(sqlite3*,int); void sqlite3Dequote(char*); |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # endif #endif /* Compatability between Tcl8.6 and Tcl9.0 */ #if TCL_MAJOR_VERSION==9 # define CONST const #elif !defined(Tcl_Size) typedef int Tcl_Size; #endif /**** End copy of tclsqlite.h ****/ #include <errno.h> /* ** Some additional include files are needed if this file is not | > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # endif #endif /* Compatability between Tcl8.6 and Tcl9.0 */ #if TCL_MAJOR_VERSION==9 # define CONST const #elif !defined(Tcl_Size) typedef int Tcl_Size; # ifndef Tcl_BounceRefCount # define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X) /* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */ # endif #endif /**** End copy of tclsqlite.h ****/ #include <errno.h> /* ** Some additional include files are needed if this file is not |
︙ | ︙ | |||
1080 1081 1082 1083 1084 1085 1086 | ** happening, make sure pCmd has a valid string representation */ Tcl_GetString(pCmd); } rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); Tcl_DecrRefCount(pCmd); } | > > | | | 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | ** happening, make sure pCmd has a valid string representation */ Tcl_GetString(pCmd); } rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); Tcl_DecrRefCount(pCmd); } if( TCL_BREAK==rc ){ sqlite3_result_null(context); }else if( rc && rc!=TCL_RETURN ){ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); }else{ Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); Tcl_Size n; u8 *data; const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); char c = zType[0]; int eType = p->eType; if( eType==SQLITE_NULL ){ if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ /* Only return a BLOB type if the Tcl variable is a bytearray and ** has no string representation. */ eType = SQLITE_BLOB; }else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 ) || (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 ) || (c=='w' && strcmp(zType,"wideInt")==0) || (c=='i' && strcmp(zType,"int")==0) ){ eType = SQLITE_INTEGER; }else if( c=='d' && strcmp(zType,"double")==0 ){ eType = SQLITE_FLOAT; }else{ eType = SQLITE_TEXT; } |
︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 | struct DbEvalContext { SqliteDb *pDb; /* Database handle */ Tcl_Obj *pSql; /* Object holding string zSql */ const char *zSql; /* Remaining SQL to execute */ SqlPreparedStmt *pPreStmt; /* Current statement */ int nCol; /* Number of columns returned by pStmt */ int evalFlags; /* Flags used */ | | > | | | | | | | 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 | struct DbEvalContext { SqliteDb *pDb; /* Database handle */ Tcl_Obj *pSql; /* Object holding string zSql */ const char *zSql; /* Remaining SQL to execute */ SqlPreparedStmt *pPreStmt; /* Current statement */ int nCol; /* Number of columns returned by pStmt */ int evalFlags; /* Flags used */ Tcl_Obj *pVarName; /* Name of target array/dict variable */ Tcl_Obj **apColName; /* Array of column names */ }; #define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */ #define SQLITE_EVAL_ASDICT 0x00002 /* Use dict instead of array */ /* ** Release any cache of column names currently held as part of ** the DbEvalContext structure passed as the first argument. */ static void dbReleaseColumnNames(DbEvalContext *p){ if( p->apColName ){ int i; for(i=0; i<p->nCol; i++){ Tcl_DecrRefCount(p->apColName[i]); } Tcl_Free((char *)p->apColName); p->apColName = 0; } p->nCol = 0; } /* ** Initialize a DbEvalContext structure. ** ** If pVarName is not NULL, then it contains the name of a Tcl array ** variable. The "*" member of this array is set to a list containing ** the names of the columns returned by the statement as part of each ** call to dbEvalStep(), in order from left to right. e.g. if the names ** of the returned columns are a, b and c, it does the equivalent of the ** tcl command: ** ** set ${pVarName}(*) {a b c} */ static void dbEvalInit( DbEvalContext *p, /* Pointer to structure to initialize */ SqliteDb *pDb, /* Database handle */ Tcl_Obj *pSql, /* Object containing SQL script */ Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */ int evalFlags /* Flags controlling evaluation */ ){ memset(p, 0, sizeof(DbEvalContext)); p->pDb = pDb; p->zSql = Tcl_GetString(pSql); p->pSql = pSql; Tcl_IncrRefCount(pSql); if( pVarName ){ p->pVarName = pVarName; Tcl_IncrRefCount(pVarName); } p->evalFlags = evalFlags; addDatabaseRef(p->pDb); } /* ** Obtain information about the row that the DbEvalContext passed as the |
︙ | ︙ | |||
1683 1684 1685 1686 1687 1688 1689 | if( 0==p->apColName ){ sqlite3_stmt *pStmt = p->pPreStmt->pStmt; int i; /* Iterator variable */ int nCol; /* Number of columns returned by pStmt */ Tcl_Obj **apColName = 0; /* Array of column names */ p->nCol = nCol = sqlite3_column_count(pStmt); | | | | | > > > > > > > > | > > > | > > > > | 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 | if( 0==p->apColName ){ sqlite3_stmt *pStmt = p->pPreStmt->pStmt; int i; /* Iterator variable */ int nCol; /* Number of columns returned by pStmt */ Tcl_Obj **apColName = 0; /* Array of column names */ p->nCol = nCol = sqlite3_column_count(pStmt); if( nCol>0 && (papColName || p->pVarName) ){ apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); for(i=0; i<nCol; i++){ apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1); Tcl_IncrRefCount(apColName[i]); } p->apColName = apColName; } /* If results are being stored in a variable then create the ** array(*) or dict(*) entry for that variable. */ if( p->pVarName ){ Tcl_Interp *interp = p->pDb->interp; Tcl_Obj *pColList = Tcl_NewObj(); Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); Tcl_IncrRefCount(pColList); Tcl_IncrRefCount(pStar); for(i=0; i<nCol; i++){ Tcl_ListObjAppendElement(interp, pColList, apColName[i]); } if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){ Tcl_ObjSetVar2(interp, p->pVarName, pStar, pColList, 0); }else{ Tcl_Obj * pDict = Tcl_ObjGetVar2(interp, p->pVarName, NULL, 0); if( !pDict ){ pDict = Tcl_NewDictObj(); }else if( Tcl_IsShared(pDict) ){ pDict = Tcl_DuplicateObj(pDict); } if( Tcl_DictObjPut(interp, pDict, pStar, pColList)==TCL_OK ){ Tcl_ObjSetVar2(interp, p->pVarName, NULL, pDict, 0); } Tcl_BounceRefCount(pDict); } Tcl_DecrRefCount(pStar); Tcl_DecrRefCount(pColList); } } if( papColName ){ *papColName = p->apColName; } if( pnCol ){ |
︙ | ︙ | |||
1747 1748 1749 1750 1751 1752 1753 | SqlPreparedStmt *pPreStmt = p->pPreStmt; sqlite3_stmt *pStmt = pPreStmt->pStmt; rcs = sqlite3_step(pStmt); if( rcs==SQLITE_ROW ){ return TCL_OK; } | | | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 | SqlPreparedStmt *pPreStmt = p->pPreStmt; sqlite3_stmt *pStmt = pPreStmt->pStmt; rcs = sqlite3_step(pStmt); if( rcs==SQLITE_ROW ){ return TCL_OK; } if( p->pVarName ){ dbEvalRowInfo(p, 0, 0); } rcs = sqlite3_reset(pStmt); pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1); pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1); pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1); |
︙ | ︙ | |||
1798 1799 1800 1801 1802 1803 1804 | */ static void dbEvalFinalize(DbEvalContext *p){ if( p->pPreStmt ){ sqlite3_reset(p->pPreStmt->pStmt); dbReleaseStmt(p->pDb, p->pPreStmt, 0); p->pPreStmt = 0; } | | | | | 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 | */ static void dbEvalFinalize(DbEvalContext *p){ if( p->pPreStmt ){ sqlite3_reset(p->pPreStmt->pStmt); dbReleaseStmt(p->pDb, p->pPreStmt, 0); p->pPreStmt = 0; } if( p->pVarName ){ Tcl_DecrRefCount(p->pVarName); p->pVarName = 0; } Tcl_DecrRefCount(p->pSql); dbReleaseColumnNames(p); delDatabaseRef(p->pDb); } /* |
︙ | ︙ | |||
1875 1876 1877 1878 1879 1880 1881 | # define Tcl_NREvalObj(a,b,c) 0 # define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0 #endif /* ** This function is part of the implementation of the command: ** | | | | | | > > > | | | > > > > > > > > > > > > > > | > > > > > > > > > > > > > > | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 | # define Tcl_NREvalObj(a,b,c) 0 # define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0 #endif /* ** This function is part of the implementation of the command: ** ** $db eval SQL ?TGT-NAME? SCRIPT */ static int SQLITE_TCLAPI DbEvalNextCmd( ClientData data[], /* data[0] is the (DbEvalContext*) */ Tcl_Interp *interp, /* Tcl interpreter */ int result /* Result so far */ ){ int rc = result; /* Return code */ /* The first element of the data[] array is a pointer to a DbEvalContext ** structure allocated using Tcl_Alloc(). The second element of data[] ** is a pointer to a Tcl_Obj containing the script to run for each row ** returned by the queries encapsulated in data[0]. */ DbEvalContext *p = (DbEvalContext *)data[0]; Tcl_Obj * const pScript = (Tcl_Obj *)data[1]; Tcl_Obj * const pVarName = p->pVarName; while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){ int i; int nCol; Tcl_Obj **apColName; dbEvalRowInfo(p, &nCol, &apColName); for(i=0; i<nCol; i++){ if( pVarName==0 ){ Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0); }else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0 && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL ){ /* Remove NULL-containing column from the target container... */ if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){ /* Target is an array */ Tcl_UnsetVar2(interp, Tcl_GetString(pVarName), Tcl_GetString(apColName[i]), 0); }else{ /* Target is a dict */ Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0); if( pDict ){ if( Tcl_IsShared(pDict) ){ pDict = Tcl_DuplicateObj(pDict); } if( Tcl_DictObjRemove(interp, pDict, apColName[i])==TCL_OK ){ Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0); } Tcl_BounceRefCount(pDict); } } }else if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){ /* Target is an array: set target(colName) = colValue */ Tcl_ObjSetVar2(interp, pVarName, apColName[i], dbEvalColumnValue(p,i), 0); }else{ /* Target is a dict: set target(colName) = colValue */ Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0); if( !pDict ){ pDict = Tcl_NewDictObj(); }else if( Tcl_IsShared(pDict) ){ pDict = Tcl_DuplicateObj(pDict); } if( Tcl_DictObjPut(interp, pDict, apColName[i], dbEvalColumnValue(p,i))==TCL_OK ){ Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0); } Tcl_BounceRefCount(pDict); } } /* The required interpreter variables are now populated with the data ** from the current row. If using NRE, schedule callbacks to evaluate ** script pScript, then to invoke this function again to fetch the next ** row (or clean up if there is no next row or the script throws an |
︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 | "interrupt", "last_insert_rowid", "nullvalue", "onecolumn", "preupdate", "profile", "progress", "rekey", "restore", "rollback_hook", "serialize", "status", "timeout", "total_changes", "trace", "trace_v2", "transaction", "unlock_notify", "update_hook", "version", "wal_hook", | | | 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 | "interrupt", "last_insert_rowid", "nullvalue", "onecolumn", "preupdate", "profile", "progress", "rekey", "restore", "rollback_hook", "serialize", "status", "timeout", "total_changes", "trace", "trace_v2", "transaction", "unlock_notify", "update_hook", "version", "wal_hook", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG, DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION, |
︙ | ︙ | |||
2849 2850 2851 2852 2853 2854 2855 | if( rc==TCL_BREAK ){ rc = TCL_OK; } break; } /* | | | | > | | | > | > | | | | 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 | if( rc==TCL_BREAK ){ rc = TCL_OK; } break; } /* ** $db eval ?options? $sql ?varName? ?{ ...code... }? ** ** The SQL statement in $sql is evaluated. For each row, the values ** are placed in elements of the array or dict named $varName and ** ...code... is executed. If $varName and $code are omitted, then ** no callback is ever invoked. If $varName is an empty string, ** then the values are placed in variables that have the same name ** as the fields extracted by the query, and those variables are ** accessible during the eval of $code. */ case DB_EVAL: { int evalFlags = 0; const char *zOpt; while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){ if( strcmp(zOpt, "-withoutnulls")==0 ){ evalFlags |= SQLITE_EVAL_WITHOUTNULLS; }else if( strcmp(zOpt, "-asdict")==0 ){ evalFlags |= SQLITE_EVAL_ASDICT; }else{ Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0); return TCL_ERROR; } objc--; objv++; } if( objc<3 || objc>5 ){ Tcl_WrongNumArgs(interp, 2, objv, "?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?"); return TCL_ERROR; } if( objc==3 ){ DbEvalContext sEval; Tcl_Obj *pRet = Tcl_NewObj(); Tcl_IncrRefCount(pRet); |
︙ | ︙ | |||
2899 2900 2901 2902 2903 2904 2905 | Tcl_SetObjResult(interp, pRet); rc = TCL_OK; } Tcl_DecrRefCount(pRet); }else{ ClientData cd2[2]; DbEvalContext *p; | | | | | 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 | Tcl_SetObjResult(interp, pRet); rc = TCL_OK; } Tcl_DecrRefCount(pRet); }else{ ClientData cd2[2]; DbEvalContext *p; Tcl_Obj *pVarName = 0; Tcl_Obj *pScript; if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){ pVarName = objv[3]; } pScript = objv[objc-1]; Tcl_IncrRefCount(pScript); p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext)); dbEvalInit(p, pDb, objv[2], pVarName, evalFlags); cd2[0] = (void *)p; cd2[1] = (void *)pScript; rc = DbEvalNextCmd(cd2, interp, TCL_OK); } break; } |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 | { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "DQS_DML", SQLITE_DBCONFIG_DQS_DML }, { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL }, { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "STMT_SCANSTATUS", SQLITE_DBCONFIG_STMT_SCANSTATUS }, }; int i; int v = 0; const char *zSetting; sqlite3 *db; if( objc!=4 && objc!=3 ){ | > > > > > | 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 | { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "DQS_DML", SQLITE_DBCONFIG_DQS_DML }, { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL }, { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "TRUSTED_SCHEMA", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, { "STMT_SCANSTATUS", SQLITE_DBCONFIG_STMT_SCANSTATUS }, { "REVERSE_SCANORDER", SQLITE_DBCONFIG_REVERSE_SCANORDER }, { "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE }, { "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE }, { "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS }, }; int i; int v = 0; const char *zSetting; sqlite3 *db; if( objc!=4 && objc!=3 ){ |
︙ | ︙ |
Changes to src/test_fs.c.
︙ | ︙ | |||
68 69 70 71 72 73 74 | #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_WIN32) || defined(__MSVCRT__) # include <unistd.h> # include <dirent.h> | < < < | < | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_WIN32) || defined(__MSVCRT__) # include <unistd.h> # include <dirent.h> #else # include "windirent.h" # ifndef S_ISREG # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) # endif #endif #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
117 118 119 120 121 122 123 | }; struct FsdirCsr { sqlite3_vtab_cursor base; char *zDir; /* Buffer containing directory scanned */ DIR *pDir; /* Open directory */ sqlite3_int64 iRowid; | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | }; struct FsdirCsr { sqlite3_vtab_cursor base; char *zDir; /* Buffer containing directory scanned */ DIR *pDir; /* Open directory */ sqlite3_int64 iRowid; struct dirent *pEntry; }; /* ** This function is the implementation of both the xConnect and xCreate ** methods of the fsdir virtual table. ** ** The argv[] array contains the following: |
︙ | ︙ | |||
479 480 481 482 483 484 485 | char *zPrefix; int nPrefix; const char *zDir; int nDir; char aWild[2] = { '\0', '\0' }; #ifdef _WIN32 | | | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | char *zPrefix; int nPrefix; const char *zDir; int nDir; char aWild[2] = { '\0', '\0' }; #ifdef _WIN32 const char *zDrive = getenv("fstreeDrive"); if( zDrive==0 ){ zDrive = getenv("SystemDrive"); } zRoot = sqlite3_mprintf("%s%c", zDrive, '/'); nRoot = sqlite3Strlen30(zRoot); zPrefix = sqlite3_mprintf("%s", zDrive); nPrefix = sqlite3Strlen30(zPrefix); #else zRoot = "/"; |
︙ | ︙ |
Deleted src/test_windirent.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted src/test_windirent.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/vacuum.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 | ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; | | > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments | SQLITE_AttachCreate | SQLITE_AttachWrite; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName; pMain = db->aDb[iDb].pBt; |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
788 789 790 791 792 793 794 795 796 797 798 799 800 801 | pDest->flags |= MEM_Term; } } pDest->flags &= ~MEM_Ephem; return rc; } /* ** Return the symbolic name for the data type of a pMem */ static const char *vdbeMemTypeName(Mem *pMem){ static const char *azTypes[] = { /* SQLITE_INTEGER */ "INT", | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 | pDest->flags |= MEM_Term; } } pDest->flags &= ~MEM_Ephem; return rc; } /* ** Send a "statement aborts" message to the error log. */ static SQLITE_NOINLINE void sqlite3VdbeLogAbort( Vdbe *p, /* The statement that is running at the time of failure */ int rc, /* Error code */ Op *pOp, /* Opcode that filed */ Op *aOp /* All opcodes */ ){ const char *zSql = p->zSql; /* Original SQL text */ const char *zPrefix = ""; /* Prefix added to SQL text */ int pc; /* Opcode address */ char zXtra[100]; /* Buffer space to store zPrefix */ if( p->pFrame ){ assert( aOp[0].opcode==OP_Init ); if( aOp[0].p4.z!=0 ){ assert( aOp[0].p4.z[0]=='-' && aOp[0].p4.z[1]=='-' && aOp[0].p4.z[2]==' ' ); sqlite3_snprintf(sizeof(zXtra), zXtra,"/* %s */ ",aOp[0].p4.z+3); zPrefix = zXtra; }else{ zPrefix = "/* unknown trigger */ "; } } pc = (int)(pOp - aOp); sqlite3_log(rc, "statement aborts at %d: %s; [%s%s]", pc, p->zErrMsg, zPrefix, zSql); } /* ** Return the symbolic name for the data type of a pMem */ static const char *vdbeMemTypeName(Mem *pMem){ static const char *azTypes[] = { /* SQLITE_INTEGER */ "INT", |
︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 | sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]); if( pOp->p4.z ){ p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z); } }else{ sqlite3VdbeError(p, "%s", pOp->p4.z); } | | < | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | sqlite3VdbeError(p, "%s constraint failed", azType[pOp->p5-1]); if( pOp->p4.z ){ p->zErrMsg = sqlite3MPrintf(db, "%z: %s", p->zErrMsg, pOp->p4.z); } }else{ sqlite3VdbeError(p, "%s", pOp->p4.z); } sqlite3VdbeLogAbort(p, pOp->p1, pOp, aOp); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ p->rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); |
︙ | ︙ | |||
2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 | aPermute = pOp[-1].p4.ai + 1; assert( aPermute!=0 ); } n = pOp->p3; pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); p1 = pOp->p1; p2 = pOp->p2; #ifdef SQLITE_DEBUG if( aPermute ){ int k, mx = 0; for(k=0; k<n; k++) if( aPermute[k]>(u32)mx ) mx = aPermute[k]; assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); | > | 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 | aPermute = pOp[-1].p4.ai + 1; assert( aPermute!=0 ); } n = pOp->p3; pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); assert( pKeyInfo->aSortFlags!=0 ); p1 = pOp->p1; p2 = pOp->p2; #ifdef SQLITE_DEBUG if( aPermute ){ int k, mx = 0; for(k=0; k<n; k++) if( aPermute[k]>(u32)mx ) mx = aPermute[k]; assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); |
︙ | ︙ | |||
3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 | /* Opcode: TypeCheck P1 P2 P3 P4 * ** Synopsis: typecheck(r[P1@P2]) ** ** Apply affinities to the range of P2 registers beginning with P1. ** Take the affinities from the Table object in P4. If any value ** cannot be coerced into the correct type, then raise an error. ** ** This opcode is similar to OP_Affinity except that this opcode ** forces the register type to the Table column type. This is used ** to implement "strict affinity". ** ** GENERATED ALWAYS AS ... STATIC columns are only checked if P3 ** is zero. When P3 is non-zero, no type checking occurs for ** static generated columns. Virtual columns are computed at query time ** and so they are never checked. ** ** Preconditions: ** ** <ul> ** <li> P2 should be the number of non-virtual columns in the | > > > > > > > > > | | > | > > > > > > > | > > > > | | | 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 | /* Opcode: TypeCheck P1 P2 P3 P4 * ** Synopsis: typecheck(r[P1@P2]) ** ** Apply affinities to the range of P2 registers beginning with P1. ** Take the affinities from the Table object in P4. If any value ** cannot be coerced into the correct type, then raise an error. ** ** If P3==0, then omit checking of VIRTUAL columns. ** ** If P3==1, then omit checking of all generated column, both VIRTUAL ** and STORED. ** ** If P3>=2, then only check column number P3-2 in the table (which will ** be a VIRTUAL column) against the value in reg[P1]. In this case, ** P2 will be 1. ** ** This opcode is similar to OP_Affinity except that this opcode ** forces the register type to the Table column type. This is used ** to implement "strict affinity". ** ** GENERATED ALWAYS AS ... STATIC columns are only checked if P3 ** is zero. When P3 is non-zero, no type checking occurs for ** static generated columns. Virtual columns are computed at query time ** and so they are never checked. ** ** Preconditions: ** ** <ul> ** <li> P2 should be the number of non-virtual columns in the ** table of P4 unless P3>1, in which case P2 will be 1. ** <li> Table P4 is a STRICT table. ** </ul> ** ** If any precondition is false, an assertion fault occurs. */ case OP_TypeCheck: { Table *pTab; Column *aCol; int i; int nCol; assert( pOp->p4type==P4_TABLE ); pTab = pOp->p4.pTab; assert( pTab->tabFlags & TF_Strict ); assert( pOp->p3>=0 && pOp->p3<pTab->nCol+2 ); aCol = pTab->aCol; pIn1 = &aMem[pOp->p1]; if( pOp->p3<2 ){ assert( pTab->nNVCol==pOp->p2 ); i = 0; nCol = pTab->nCol; }else{ i = pOp->p3-2; nCol = i+1; assert( i<pTab->nCol ); assert( aCol[i].colFlags & COLFLAG_VIRTUAL ); assert( pOp->p2==1 ); } for(; i<nCol; i++){ if( (aCol[i].colFlags & COLFLAG_GENERATED)!=0 && pOp->p3<2 ){ if( (aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ) continue; if( pOp->p3 ){ pIn1++; continue; } } assert( pIn1 < &aMem[pOp->p1+pOp->p2] ); applyAffinity(pIn1, aCol[i].affinity, encoding); if( (pIn1->flags & MEM_Null)==0 ){ switch( aCol[i].eCType ){ case COLTYPE_BLOB: { |
︙ | ︙ | |||
5381 5382 5383 5384 5385 5386 5387 | assert( r.aMem->flags & MEM_Blob ); assert( pOp->opcode!=OP_NoConflict ); rc = ExpandBlob(r.aMem); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc ) goto no_mem; pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; | | | 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 | assert( r.aMem->flags & MEM_Blob ); assert( pOp->opcode!=OP_NoConflict ); rc = ExpandBlob(r.aMem); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc ) goto no_mem; pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey); pIdxKey->default_rc = 0; rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult); sqlite3DbFreeNN(db, pIdxKey); } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } |
︙ | ︙ | |||
9197 9198 9199 9200 9201 9202 9203 | #endif if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){ sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); } p->rc = rc; sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); | | < | 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 | #endif if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){ sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); } p->rc = rc; sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3VdbeLogAbort(p, rc, pOp, aOp); if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ db->flags |= SQLITE_CorruptRdOnly; } rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
297 298 299 300 301 302 303 | void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3BlobCompare(const Mem*, const Mem*); | | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3BlobCompare(const Mem*, const Mem*); void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
553 554 555 556 557 558 559 | i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem oldipk; /* Memory cell holding "old" IPK value */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ sqlite3_value **apDflt; /* Array of default values, if required */ | | | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem oldipk; /* Memory cell holding "old" IPK value */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ sqlite3_value **apDflt; /* Array of default values, if required */ u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */ }; /* ** An instance of this object is used to pass an vector of values into ** OP_VFilter, the xFilter method of a virtual table. The vector is the ** set of values on the right-hand side of an IN constraint. ** |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
2159 2160 2161 2162 2163 2164 2165 | const void *pKey ){ UnpackedRecord *pRet; /* Return value */ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); | | | 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 | const void *pKey ){ UnpackedRecord *pRet; /* Return value */ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); sqlite3VdbeRecordUnpack(nKey, pKey, pRet); } return pRet; } /* ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or deleted. |
︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; } if( p->pPk ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_old_out; } | > > > | 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 | ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; } if( p->pPk ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); }else if( iIdx >= p->pTab->nCol ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_old_out; } |
︙ | ︙ | |||
2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 | p = db->pPreUpdate; if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_new_out; } if( p->pPk && p->op!=SQLITE_UPDATE ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_new_out; | > > | 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 | p = db->pPreUpdate; if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_new_out; } if( p->pPk && p->op!=SQLITE_UPDATE ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); }else if( iIdx >= p->pTab->nCol ){ return SQLITE_MISUSE_BKPT; }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } if( iStore>=p->pCsr->nField || iStore<0 ){ rc = SQLITE_RANGE; goto preupdate_new_out; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
4218 4219 4220 4221 4222 4223 4224 | pMem->flags = aFlag[serial_type&1]; return; } } return; } /* | | < | | < < < < < < | | < < > | 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 | pMem->flags = aFlag[serial_type&1]; return; } } return; } /* ** Allocate sufficient space for an UnpackedRecord structure large enough ** to hold a decoded index record for pKeyInfo. ** ** The space is allocated using sqlite3DbMallocRaw(). If an OOM error ** occurs, NULL is returned. */ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( KeyInfo *pKeyInfo /* Description of the record */ ){ UnpackedRecord *p; /* Unpacked record to return */ u64 nByte; /* Number of bytes required for *p */ assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff ); nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))]; p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nKeyField + 1; return p; } /* ** Given the nKey-byte encoding of a record in pKey[], populate the ** UnpackedRecord structure indicated by the fourth argument with the ** contents of the decoded record. */ void sqlite3VdbeRecordUnpack( int nKey, /* Size of the binary record */ const void *pKey, /* The binary record */ UnpackedRecord *p /* Populate this structure before returning. */ ){ const unsigned char *aKey = (const unsigned char *)pKey; u32 d; u32 idx; /* Offset in aKey[] to read from */ u16 u; /* Unsigned loop counter */ u32 szHdr; Mem *pMem = p->aMem; KeyInfo *pKeyInfo = p->pKeyInfo; p->default_rc = 0; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; u = 0; while( idx<szHdr && d<=(u32)nKey ){ |
︙ | ︙ | |||
4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 | if( d>(u32)nKey && u ){ assert( CORRUPT_DB ); /* In a corrupt record entry, the last pMem might have been set up using ** uninitialized memory. Overwrite its value with NULL, to prevent ** warnings from MSAN. */ sqlite3VdbeMemSetNull(pMem-1); } assert( u<=pKeyInfo->nKeyField + 1 ); p->nField = u; } #ifdef SQLITE_DEBUG /* ** This function compares two index or table record keys in the same way | > > | 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 | if( d>(u32)nKey && u ){ assert( CORRUPT_DB ); /* In a corrupt record entry, the last pMem might have been set up using ** uninitialized memory. Overwrite its value with NULL, to prevent ** warnings from MSAN. */ sqlite3VdbeMemSetNull(pMem-1); } testcase( u == pKeyInfo->nKeyField + 1 ); testcase( u < pKeyInfo->nKeyField + 1 ); assert( u<=pKeyInfo->nKeyField + 1 ); p->nField = u; } #ifdef SQLITE_DEBUG /* ** This function compares two index or table record keys in the same way |
︙ | ︙ | |||
5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 | ** buffer passed to varintRecordCompareInt() this makes it convenient to ** limit the size of the header to 64 bytes in cases where the first field ** is an integer. ** ** The easiest way to enforce this limit is to consider only records with ** 13 fields or less. If the first field is an integer, the maximum legal ** header size is (12*5 + 1 + 1) bytes. */ if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortFlags[0] ){ if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ return sqlite3VdbeRecordCompare; } p->r1 = 1; | > | 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 | ** buffer passed to varintRecordCompareInt() this makes it convenient to ** limit the size of the header to 64 bytes in cases where the first field ** is an integer. ** ** The easiest way to enforce this limit is to consider only records with ** 13 fields or less. If the first field is an integer, the maximum legal ** header size is (12*5 + 1 + 1) bytes. */ assert( p->pKeyInfo->aSortFlags!=0 ); if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortFlags[0] ){ if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ return sqlite3VdbeRecordCompare; } p->r1 = 1; |
︙ | ︙ | |||
5508 5509 5510 5511 5512 5513 5514 | int iReg, /* Register for new.* record */ int iBlobWrite ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; | < | 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 | int iReg, /* Register for new.* record */ int iBlobWrite ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; #ifdef SQLITE_DEBUG int nRealCol; if( pTab->tabFlags & TF_WithoutRowid ){ nRealCol = sqlite3PrimaryKeyIndex(pTab)->nColumn; }else if( pTab->tabFlags & TF_HasVirtual ){ nRealCol = pTab->nNVCol; }else{ |
︙ | ︙ | |||
5547 5548 5549 5550 5551 5552 5553 | preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; preupdate.pKeyinfo->db = db; preupdate.pKeyinfo->enc = ENC(db); preupdate.pKeyinfo->nKeyField = pTab->nCol; | | | 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 | preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; preupdate.pKeyinfo->db = db; preupdate.pKeyinfo->enc = ENC(db); preupdate.pKeyinfo->nKeyField = pTab->nCol; preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */ preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; preupdate.iBlobWrite = iBlobWrite; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
762 763 764 765 766 767 768 | 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 ){ | | | 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 | 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(nKey2, pKey2, r2); *pbKey2Cached = 1; } return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); } /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, |
︙ | ︙ | |||
789 790 791 792 793 794 795 | 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 ){ | | | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | 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 ){ sqlite3VdbeRecordUnpack(nKey2, pKey2, r2); *pbKey2Cached = 1; } return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); } /* ** A specially optimized version of vdbeSorterCompare() that assumes that |
︙ | ︙ | |||
829 830 831 832 833 834 835 836 837 838 839 840 841 842 | if( res==0 ){ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } }else{ assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ res = res * -1; } } return res; | > | 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 | if( res==0 ){ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } }else{ assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 ); assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ res = res * -1; } } return res; |
︙ | ︙ | |||
892 893 894 895 896 897 898 899 900 901 902 903 904 905 | if( res>0 ){ if( *v1 & 0x80 ) res = -1; }else{ if( *v2 & 0x80 ) res = +1; } } if( res==0 ){ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ | > | 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 | if( res>0 ){ if( *v1 & 0x80 ) res = -1; }else{ if( *v2 & 0x80 ) res = +1; } } assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 ); if( res==0 ){ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ |
︙ | ︙ | |||
965 966 967 968 969 970 971 | #endif assert( pCsr->pKeyInfo ); assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) < 0x7fffffff ); | > | > > > > > | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | #endif assert( pCsr->pKeyInfo ); assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) < 0x7fffffff ); assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField ); szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField); sz = SZ_VDBESORTER(nWorker+1); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); pCsr->uc.pSorter = pSorter; if( pSorter==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ Btree *pBt = db->aDb[0].pBt; pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; if( nField && nWorker==0 ){ pKeyInfo->nKeyField = nField; assert( nField<=pCsr->pKeyInfo->nAllField ); } /* It is OK that pKeyInfo reuses the aSortFlags field from pCsr->pKeyInfo, ** since the pCsr->pKeyInfo->aSortFlags[] array is invariant and lives ** longer that pSorter. */ assert( pKeyInfo->aSortFlags==pCsr->pKeyInfo->aSortFlags ); sqlite3BtreeEnter(pBt); pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt); sqlite3BtreeLeave(pBt); pSorter->nTask = nWorker + 1; pSorter->iPrev = (u8)(nWorker - 1); pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; |
︙ | ︙ | |||
2759 2760 2761 2762 2763 2764 2765 | r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( r2==0 ) return SQLITE_NOMEM_BKPT; r2->nField = nKeyCol; } assert( r2->nField==nKeyCol ); pKey = vdbeSorterRowkey(pSorter, &nKey); | | | 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 | r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( r2==0 ) return SQLITE_NOMEM_BKPT; r2->nField = nKeyCol; } assert( r2->nField==nKeyCol ); pKey = vdbeSorterRowkey(pSorter, &nKey); sqlite3VdbeRecordUnpack(nKey, pKey, r2); for(i=0; i<nKeyCol; i++){ if( r2->aMem[i].flags & MEM_Null ){ *pRes = -1; return SQLITE_OK; } } *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2); return SQLITE_OK; } |
Changes to src/wal.c.
︙ | ︙ | |||
3071 3072 3073 3074 3075 3076 3077 | if( !useWal ){ assert( rc==SQLITE_OK ); if( pWal->bShmUnreliable==0 ){ rc = walIndexReadHdr(pWal, pChanged); } #ifdef SQLITE_ENABLE_SETLK_TIMEOUT | < > > | 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 | if( !useWal ){ assert( rc==SQLITE_OK ); if( pWal->bShmUnreliable==0 ){ rc = walIndexReadHdr(pWal, pChanged); } #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_BUSY_TIMEOUT ){ rc = SQLITE_BUSY; *pCnt |= WAL_RETRY_BLOCKED_MASK; } #endif if( rc==SQLITE_BUSY ){ /* If there is not a recovery running in another thread or process ** then convert BUSY errors to WAL_RETRY. If recovery is known to ** be running, convert BUSY to BUSY_RECOVERY. There is a race here ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY ** would be technically correct. But the race is benign since with ** WAL_RETRY this routine will be called again and will probably be ** right on the second iteration. */ (void)walEnableBlocking(pWal); if( pWal->apWiData[0]==0 ){ /* This branch is taken when the xShmMap() method returns SQLITE_BUSY. ** We assume this is a transient condition, so return WAL_RETRY. The ** xShmMap() implementation used by the default unix and win32 VFS ** modules may return SQLITE_BUSY due to a race condition in the ** code that determines whether or not the shared-memory region ** must be zeroed before the requested page is returned. */ rc = WAL_RETRY; }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ walUnlockShared(pWal, WAL_RECOVER_LOCK); rc = WAL_RETRY; }else if( rc==SQLITE_BUSY ){ rc = SQLITE_BUSY_RECOVERY; } } walDisableBlocking(pWal); if( rc!=SQLITE_OK ){ return rc; } else if( pWal->bShmUnreliable ){ return walBeginShmUnreliable(pWal, pChanged); } } |
︙ | ︙ | |||
4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 | */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } /* ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 ** values. This function populates the array with values required to | > | 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 | */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) pWal->iReCksum = 0; } return rc; } /* ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 ** values. This function populates the array with values required to |
︙ | ︙ | |||
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 | pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; SEH_TRY { walCleanupHash(pWal); } SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } /* ** This function is called just before writing a set of frames to the log | > > > | 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 | pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; SEH_TRY { walCleanupHash(pWal); } SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) if( pWal->iReCksum>pWal->hdr.mxFrame ){ pWal->iReCksum = 0; } } return rc; } /* ** This function is called just before writing a set of frames to the log |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
422 423 424 425 426 427 428 | ){ testcase( pTerm->eOperator & WO_IS ); continue; } pScan->pWC = pWC; pScan->k = k+1; #ifdef WHERETRACE_ENABLED | | | | | | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | ){ testcase( pTerm->eOperator & WO_IS ); continue; } pScan->pWC = pWC; pScan->k = k+1; #ifdef WHERETRACE_ENABLED if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){ int ii; sqlite3DebugPrintf("EQUIVALENT TO {%d:%d} (due to TERM-%d):", pScan->aiCur[0], pScan->aiColumn[0], pTerm->iTerm); for(ii=1; ii<pScan->nEquiv; ii++){ sqlite3DebugPrintf(" {%d:%d}", pScan->aiCur[ii], pScan->aiColumn[ii]); } sqlite3DebugPrintf("\n"); } #endif return pTerm; |
︙ | ︙ | |||
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 | pTerm->leftCursor, pTerm->u.x.leftColumn); }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx", pTerm->u.pOrInfo->indexable); }else{ sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); } sqlite3DebugPrintf( "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x", iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags); /* The 0x10000 .wheretrace flag causes extra information to be ** shown about each Term */ if( sqlite3WhereTrace & 0x10000 ){ sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx", | > | 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 | pTerm->leftCursor, pTerm->u.x.leftColumn); }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx", pTerm->u.pOrInfo->indexable); }else{ sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); } iTerm = pTerm->iTerm = MAX(iTerm,pTerm->iTerm); sqlite3DebugPrintf( "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x", iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags); /* The 0x10000 .wheretrace flag causes extra information to be ** shown about each Term */ if( sqlite3WhereTrace & 0x10000 ){ sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx", |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 | LogEst truthProb; /* Probability of truth for this expression */ u16 wtFlags; /* TERM_xxx bit flags. See below */ u16 eOperator; /* A WO_xx value describing <op> */ u8 nChild; /* Number of children that must disable us */ u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { struct { int leftColumn; /* Column number of X in "X <op> <expr>" */ int iField; /* Field in (?,?,?) IN (SELECT...) vector */ } x; /* Opcode other than OP_OR or OP_AND */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ | > > > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | LogEst truthProb; /* Probability of truth for this expression */ u16 wtFlags; /* TERM_xxx bit flags. See below */ u16 eOperator; /* A WO_xx value describing <op> */ u8 nChild; /* Number of children that must disable us */ u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ #ifdef SQLITE_DEBUG int iTerm; /* Which WhereTerm is this, for debug purposes */ #endif union { struct { int leftColumn; /* Column number of X in "X <op> <expr>" */ int iField; /* Field in (?,?,?) IN (SELECT...) vector */ } x; /* Opcode other than OP_OR or OP_AND */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
106 107 108 109 110 111 112 | if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3_str_append(pStr, ")", 1); } /* | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3_str_append(pStr, ")", 1); } /* ** This function sets the P4 value of an existing OP_Explain opcode to ** text describing the loop in pLevel. If the OP_Explain opcode already has ** a P4 value, it is freed before it is overwritten. */ void sqlite3WhereAddExplainText( Parse *pParse, /* Parse context */ int addr, /* Address of OP_Explain opcode */ SrcList *pTabList, /* Table list this loop refers to */ |
︙ | ︙ | |||
944 945 946 947 948 949 950 | VdbeCoverageIf(v, bRev!=0); sqlite3VdbeJumpHere(v, j); for(j=0; j<nSkip; j++){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); testcase( pIdx->aiColumn[j]==XN_EXPR ); VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); } | | | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 | VdbeCoverageIf(v, bRev!=0); sqlite3VdbeJumpHere(v, j); for(j=0; j<nSkip; j++){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j); testcase( pIdx->aiColumn[j]==XN_EXPR ); VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); } } /* Evaluate the equality constraints */ assert( zAff==0 || (int)strlen(zAff)>=nEq ); for(j=nSkip; j<nEq; j++){ int r1; pTerm = pLoop->aLTerm[j]; |
︙ | ︙ | |||
1285 1286 1287 1288 1289 1290 1291 | int iIdxCur /* Index cursor */ ){ Parse *pParse = pWInfo->pParse; /* Parse context */ Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); | | | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | int iIdxCur /* Index cursor */ ){ Parse *pParse = pWInfo->pParse; /* Parse context */ Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); pWInfo->bDeferredSeek = 1; sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ int i; Table *pTab = pIdx->pTable; |
︙ | ︙ | |||
1439 1440 1441 1442 1443 1444 1445 | } pLevel->regFilter = 0; pLevel->addrBrk = 0; } } /* | | | | | | | 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | } pLevel->regFilter = 0; pLevel->addrBrk = 0; } } /* ** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...) ** operator. Return true if level pLoop is guaranteed to visit only one ** row for each key generated for the index. */ static int whereLoopIsOneRow(WhereLoop *pLoop){ if( pLoop->u.btree.pIndex->onError && pLoop->nSkip==0 && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol ){ int ii; for(ii=0; ii<pLoop->u.btree.nEq; ii++){ if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){ return 0; } } |
︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 | VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Lt); VdbeCoverageIf(v, testOp==OP_Ge); VdbeCoverageIf(v, testOp==OP_Gt); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ | | | | | | | | | | | | | | | | | | | | | | | | | | | 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 | VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Lt); VdbeCoverageIf(v, testOp==OP_Ge); VdbeCoverageIf(v, testOp==OP_Gt); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ /* Case 4: Search using an index. ** ** The WHERE clause may contain zero or more equality ** terms ("==" or "IN" or "IS" operators) that refer to the N ** left-most columns of the index. It may also contain ** inequality constraints (>, <, >= or <=) on the indexed ** column that immediately follows the N equalities. Only ** the right-most column can be an inequality - the rest must ** use the "==", "IN", or "IS" operators. For example, if the ** index is on (x,y,z), then the following clauses are all ** optimized: ** ** x=5 ** x=5 AND y=10 ** x=5 AND y<10 ** x=5 AND y>5 AND y<10 ** x=5 AND y=5 AND z<=10 ** ** The z<10 term of the following cannot be used, only ** the x=5 term: ** ** x=5 AND z<10 ** ** N may be zero if there are inequality constraints. ** If there are no inequality constraints, then N is at ** least one. ** ** This case is also used when there are no WHERE clause ** constraints but an index is selected anyway, in order ** to force the output order to conform to an ORDER BY. */ static const u8 aStartOp[] = { 0, 0, OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ OP_Last, /* 3: (!start_constraints && startEq && bRev) */ OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */ OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */ |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 | && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } if( zStartAff ){ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); | | | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); } if( zStartAff ){ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); } nConstraint += nBtm; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); if( sqlite3ExprIsVector(pRight)==0 ){ disableTerm(pLevel, pRangeStart); }else{ startEq = 1; } |
︙ | ︙ | |||
2197 2198 2199 2200 2201 2202 2203 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } if( pLevel->iLeftJoin==0 ){ /* If a partial index is driving the loop, try to eliminate WHERE clause ** terms from the query that must be true due to the WHERE clause of | | > | | | | | 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } if( pLevel->iLeftJoin==0 ){ /* If a partial index is driving the loop, try to eliminate WHERE clause ** terms from the query that must be true due to the WHERE clause of ** the partial index. This optimization does not work on an outer join, ** as shown by: ** ** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN) ** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN) */ if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){ whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC); } }else{ testcase( pIdx->pPartIdxWhere ); /* The following assert() is not a requirement, merely an observation: ** The OR-optimization doesn't work for the right hand table of ** a LEFT JOIN: */ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ); } /* Record the instruction used to terminate the loop. */ if( (pLoop->wsFlags & WHERE_ONEROW) || (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop)) ){ pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; |
︙ | ︙ | |||
2601 2602 2603 2604 2605 2606 2607 | ** ** This loop may run between one and three times, depending on the ** constraints to be generated. The value of stack variable iLoop ** determines the constraints coded by each iteration, as follows: ** ** iLoop==1: Code only expressions that are entirely covered by pIdx. ** iLoop==2: Code remaining expressions that do not contain correlated | | | 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 | ** ** This loop may run between one and three times, depending on the ** constraints to be generated. The value of stack variable iLoop ** determines the constraints coded by each iteration, as follows: ** ** iLoop==1: Code only expressions that are entirely covered by pIdx. ** iLoop==2: Code remaining expressions that do not contain correlated ** sub-queries. ** iLoop==3: Code all remaining expressions. ** ** An effort is made to skip unnecessary iterations of the loop. ** ** This optimization of causing simple query restrictions to occur before ** more complex one is call the "push-down" optimization in MySQL. Here ** in SQLite, the name is "MySQL push-down", since there is also another |
︙ | ︙ | |||
2872 2873 2874 2875 2876 2877 2878 | mAll |= pWInfo->a[k].pWLoop->maskSelf; if( pRight->fg.viaCoroutine ){ Subquery *pSubq; assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 ); pSubq = pRight->u4.pSubq; assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 ); sqlite3VdbeAddOp3( | | | 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 | mAll |= pWInfo->a[k].pWLoop->maskSelf; if( pRight->fg.viaCoroutine ){ Subquery *pSubq; assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 ); pSubq = pRight->u4.pSubq; assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 ); sqlite3VdbeAddOp3( v, OP_Null, 0, pSubq->regResult, pSubq->regResult + pSubq->pSelect->pEList->nExpr-1 ); } sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); iIdxCur = pWInfo->a[k].iIdxCur; if( iIdxCur ){ sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
927 928 929 930 931 932 933 | /* ** 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 | > | | | | | | | > > > > > > > | | | > > > > | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 | /* ** 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 operator is not IS or else the query does not contain RIGHT JOIN ** 5. The affinities of A and B must be compatible ** 6a. Both operands use the same collating sequence OR ** 6b. 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, SrcList *pSrc){ char aff1, aff2; CollSeq *pColl; if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */ if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */ assert( pSrc!=0 ); if( pExpr->op==TK_IS && pSrc->nSrc && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* (4) */ } aff1 = sqlite3ExprAffinity(pExpr->pLeft); aff2 = sqlite3ExprAffinity(pExpr->pRight); if( aff1!=aff2 && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2)) ){ return 0; /* (5) */ } pColl = sqlite3ExprCompareCollSeq(pParse, pExpr); if( !sqlite3IsBinary(pColl) && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){ return 0; /* (6) */ } return 1; } /* ** Recursively walk the expressions of a SELECT statement and generate ** a bitmask indicating which tables are used in that expression ** tree. */ |
︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | int nLeft; /* Number of elements on left side vector */ if( db->mallocFailed ){ return; } assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); pMaskSet->bVarSelect = 0; prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; | > > > | 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | int nLeft; /* Number of elements on left side vector */ if( db->mallocFailed ){ return; } assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; #ifdef SQLITE_DEBUG pTerm->iTerm = idxTerm; #endif pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); pMaskSet->bVarSelect = 0; prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; |
︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 | 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; | | | | 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | 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; assert( pWInfo->pTabList!=0 ); if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){ pTerm->eOperator |= WO_EQUIV; eExtraOp = WO_EQUIV; } }else{ pDup = pExpr; pNew = pTerm; } |
︙ | ︙ |
Added test/dblwidth-a.sql.
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* ** Run this script using "sqlite3" to confirm that the command-line ** shell properly handles the output of double-width characters. ** ** https://sqlite.org/forum/forumpost/008ac80276 */ .mode box CREATE TABLE data(word TEXT, description TEXT); INSERT INTO data VALUES('〈οὐκέτι〉','Greek without dblwidth <...>'); .print .mode box SELECT * FROM data; .mode table .print .mode table SELECT * FROM data; .mode qbox .print .mode qbox SELECT * FROM data; .mode column .print .mode column SELECT * FROM data; |
Changes to test/fts3join.test.
︙ | ︙ | |||
93 94 95 96 97 98 99 | do_eqp_test 4.2 { SELECT * FROM t4 LEFT JOIN ( SELECT docid, * FROM ft4 WHERE ft4 MATCH ? ) AS rr ON t4.rowid=rr.docid WHERE t4.y = ?; } { QUERY PLAN | < < < | | 93 94 95 96 97 98 99 100 101 102 103 104 | do_eqp_test 4.2 { SELECT * FROM t4 LEFT JOIN ( SELECT docid, * FROM ft4 WHERE ft4 MATCH ? ) AS rr ON t4.rowid=rr.docid WHERE t4.y = ?; } { QUERY PLAN |--SCAN t4 `--SCAN ft4 VIRTUAL TABLE INDEX 3: LEFT-JOIN } finish_test |
Changes to test/func9.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | } {text} do_catchsql_test func9-120 { SELECT concat(); } {1 {wrong number of arguments to function concat()}} do_execsql_test func9-130 { SELECT concat_ws(',',1,2,3,4,5,6,7,8,NULL,9,10,11,12); } {1,2,3,4,5,6,7,8,9,10,11,12} do_execsql_test func9-140 { SELECT concat_ws(NULL,1,2,3,4,5,6,7,8,NULL,9,10,11,12); } {{}} do_catchsql_test func9-150 { SELECT concat_ws(); } {1 {wrong number of arguments to function concat_ws()}} do_catchsql_test func9-160 { | > > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | } {text} do_catchsql_test func9-120 { SELECT concat(); } {1 {wrong number of arguments to function concat()}} do_execsql_test func9-130 { SELECT concat_ws(',',1,2,3,4,5,6,7,8,NULL,9,10,11,12); } {1,2,3,4,5,6,7,8,9,10,11,12} do_execsql_test func9-131 { SELECT concat_ws(',',1,2,3,4,'',6,7,8,NULL,9,10,11,12); } {1,2,3,4,,6,7,8,9,10,11,12} do_execsql_test func9-140 { SELECT concat_ws(NULL,1,2,3,4,5,6,7,8,NULL,9,10,11,12); } {{}} do_catchsql_test func9-150 { SELECT concat_ws(); } {1 {wrong number of arguments to function concat_ws()}} do_catchsql_test func9-160 { |
︙ | ︙ |
Changes to test/hook.test.
︙ | ︙ | |||
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | "] [list $X] } proc preupdate_hook {args} { set type [lindex $args 0] eval lappend ::preupdate $args if {$type != "INSERT"} { for {set i 0} {$i < [db preupdate count]} {incr i} { lappend ::preupdate [db preupdate old $i] } } if {$type != "DELETE"} { for {set i 0} {$i < [db preupdate count]} {incr i} { set rc [catch { db preupdate new $i } v] lappend ::preupdate $v } } } | > > > > > > > > > > | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | "] [list $X] } proc preupdate_hook {args} { set type [lindex $args 0] eval lappend ::preupdate $args if {$type != "INSERT"} { set x [catch {db preupdate old [db preupdate count]}] if {!$x} { lappend "ERROR: sqlite3_preupdate_old() accepted an out-of-bounds\ column index" } for {set i 0} {$i < [db preupdate count]} {incr i} { lappend ::preupdate [db preupdate old $i] } } if {$type != "DELETE"} { set x [catch {db preupdate new [db preupdate count]}] if {!$x} { lappend "ERROR: sqlite3_preupdate_old() accepted an out-of-bounds\ column index" } for {set i 0} {$i < [db preupdate count]} {incr i} { set rc [catch { db preupdate new $i } v] lappend ::preupdate $v } } } |
︙ | ︙ |
Changes to test/join.test.
︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 | INSERT INTO t0(c0) VALUES (0); SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1); } {} do_execsql_test join-20.2 { CREATE INDEX t1x ON t1(0) WHERE NULL IN (c1); SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1); } {} # 2019-11-30 ticket 7f39060a24b47353 # Do not allow a WHERE clause term to qualify a partial index on the # right table of a LEFT JOIN. # do_execsql_test join-21.10 { DROP TABLE t0; | > > > > > > > > > > > > > > > | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 | INSERT INTO t0(c0) VALUES (0); SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1); } {} do_execsql_test join-20.2 { CREATE INDEX t1x ON t1(0) WHERE NULL IN (c1); SELECT * FROM t0 LEFT JOIN t1 WHERE NULL IN (c1); } {} # 2025-05-29 forum post 7dee41d32506c4ae # The complaint in the forum post appears to be the same as for the # ticket on 2019-11-02, only for RIGHT JOIN instead of LEFT JOIN. Note # that RIGHT JOIN did not yet exist in SQLite when the ticket was # written and fixed. # do_execsql_test join-20.3 { DROP TABLE t1; CREATE TABLE t1(x INT); INSERT INTO t1(x) VALUES(1); CREATE TABLE t2(y BOOLEAN); INSERT INTO t2(y) VALUES(false); CREATE TABLE t3(z INT); INSERT INTO t3(z) VALUES(3); CREATE INDEX t2y ON t2(y) WHERE y; SELECT quote(z) FROM t1 RIGHT JOIN t2 ON y LEFT JOIN t3 ON y; } {NULL} # 2019-11-30 ticket 7f39060a24b47353 # Do not allow a WHERE clause term to qualify a partial index on the # right table of a LEFT JOIN. # do_execsql_test join-21.10 { DROP TABLE t0; |
︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 1291 1292 | WHERE x <= y; } {} do_execsql_test join-30.3 { SELECT DISTINCT a, b FROM t0 JOIN t1 ON z=a RIGHT JOIN t2 ON a=b LEFT JOIN v5 ON false WHERE x <= y; } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 | WHERE x <= y; } {} do_execsql_test join-30.3 { SELECT DISTINCT a, b FROM t0 JOIN t1 ON z=a RIGHT JOIN t2 ON a=b LEFT JOIN v5 ON false WHERE x <= y; } {} # 2025-05-30 https://sqlite.org/forum/forumpost/4fc70203b61c7e12 # # When converting a USING(x) or NATURAL into the constraint expression # t1.x==t2.x, mark the t1.x term as EP_CanBeNull if it is the left table # of a RIGHT JOIN. # reset_db db null NULL do_execsql_test join-31.1 { CREATE TABLE t1(c0 INT , c1 INT); INSERT INTO t1(c0, c1) VALUES(NULL,11); CREATE TABLE t2(c0 INT NOT NULL); CREATE TABLE t2n(c0 INT); CREATE TABLE t3(x INT); INSERT INTO t3(x) VALUES(3); CREATE TABLE t4(y INT); INSERT INTO t4(y) VALUES(4); CREATE TABLE t5(c0 INT, x INT); INSERT INTO t5 VALUES(NULL, 5); } do_execsql_test join-31.2 { SELECT * FROM t2 RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0); } {NULL 3 NULL} do_execsql_test join-31.3 { SELECT * FROM t2 RIGHT JOIN t3 ON true NATURAL LEFT JOIN t1; } {NULL 3 NULL} do_execsql_test join-31.4 { SELECT * FROM t2n RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0); } {NULL 3 NULL} do_execsql_test join-31.5 { SELECT * FROM t5 LEFT JOIN t1 USING(c0); } {NULL 5 NULL} do_execsql_test join-31.6 { SELECT * FROM t3 LEFT JOIN t2 ON true LEFT JOIN t1 USING(c0); } {3 NULL NULL} do_execsql_test join-31.7 { SELECT * FROM t3 LEFT JOIN t2 ON true NATURAL LEFT JOIN t1; } {3 NULL NULL} do_execsql_test join-31.8 { SELECT * FROM t3 LEFT JOIN t2 ON true JOIN t4 ON true NATURAL LEFT JOIN t1; } {3 NULL 4 NULL} # 2025-06-16 https://sqlite.org/forum/forumpost/68f29a2005 # # The transitive-constraint optimization was not working for RIGHT JOIN. # reset_db db null NULL do_execsql_test join-32.1 { CREATE TABLE t0(w INT); CREATE TABLE t1(x INT); CREATE TABLE t2(y INT UNIQUE); CREATE VIEW v0(z) AS SELECT CAST(x AS INT) FROM t1 LEFT JOIN t2 ON true; INSERT INTO t1(x) VALUES(123); INSERT INTO t2(y) VALUES(NULL); } do_execsql_test join-32.2 { SELECT * FROM t0 JOIN v0 ON w=z RIGHT JOIN t1 ON true INNER JOIN t2 ON y IS z; } {NULL NULL 123 NULL} do_execsql_test join-32.3 { SELECT * FROM t0 JOIN v0 ON w=z RIGHT JOIN t1 ON true INNER JOIN t2 ON +y IS z; } {NULL NULL 123 NULL} finish_test |
Changes to test/joinH.test.
︙ | ︙ | |||
336 337 338 339 340 341 342 343 344 | SELECT a1.a, sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t4 ON a=x GROUP BY a1.a ORDER BY 1; } {NULL NULL 1 -592 4 192 16 48} do_execsql_test 13.4 { SELECT sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t3 ON true GROUP BY a1.a ORDER BY 1; } {-1480 240 480} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | SELECT a1.a, sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t4 ON a=x GROUP BY a1.a ORDER BY 1; } {NULL NULL 1 -592 4 192 16 48} do_execsql_test 13.4 { SELECT sum( a1.a+a1.b ) FROM t3 AS a1 RIGHT JOIN t3 ON true GROUP BY a1.a ORDER BY 1; } {-1480 240 480} #------------------------------------------------------------------------- # 2025-05-30 # https://sqlite.org/forum/forumpost/5028c785b6 # reset_db do_execsql_test 14.0 { CREATE TABLE t1(c0 INT); CREATE TABLE t2(c0 BLOB); CREATE TABLE t3(c0 BLOB); CREATE TABLE t4(c4 BLOB); INSERT INTO t1(c0) VALUES(0); INSERT INTO t3(c0) VALUES('0'); } do_execsql_test 14.1.1 { SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3; } {0} do_execsql_test 14.1.2 { SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3 FULL JOIN t4 ON true; } {0 {}} do_execsql_test 14.1.3 { SELECT * FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) FULL JOIN t4 ON true; } {0 {}} do_execsql_test 14.1.4 { SELECT * FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) AS qq FULL JOIN t4 ON true; } {0 {}} do_execsql_test 14.2.1 { SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1; } {0} do_execsql_test 14.2.2 { SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1 FULL JOIN t4 ON true; } {0 {}} do_execsql_test 14.2.3 { SELECT * FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) FULL JOIN t4 ON true; } {0 {}} do_execsql_test 14.2.4 { SELECT * FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) AS qq FULL JOIN t4 ON true; } {0 {}} # 2025-06-01 # reset_db do_execsql_test 15.1 { CREATE TABLE t0(c0); CREATE TABLE t1(c0); CREATE TABLE t2(c0); INSERT INTO t0 VALUES ('1.0'); INSERT INTO t2(c0) VALUES (9); SELECT t0.c0,t2.c0 FROM (SELECT CAST(t0.c0 as REAL) AS c0 FROM t0) as subquery NATURAL LEFT JOIN t1 NATURAL JOIN t0 RIGHT JOIN t2 ON 1; } {1.0 9} do_execsql_test 15.2 { CREATE TABLE x1(x COLLATE nocase); CREATE TABLE x2(x); CREATE TABLE x3(x); CREATE TABLE t4(y); INSERT INTO x1 VALUES('ABC'); INSERT INTO x3 VALUES('abc'); SELECT lower(x), quote(y) FROM x1 LEFT JOIN x2 USING (x) JOIN x3 USING (x) FULL JOIN t4; } {abc NULL} finish_test |
Changes to test/snapshot3.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | file size test.db-wal } 0 do_test 1.8 { execsql BEGIN db3 list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); | > > > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | file size test.db-wal } 0 do_test 1.8 { execsql BEGIN db3 list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg } {1 SQLITE_ERROR_SNAPSHOT} db3 close db2 close #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); |
︙ | ︙ |
Changes to test/strict1.test.
︙ | ︙ | |||
157 158 159 160 161 162 163 164 165 | SELECT * FROM transactions; } {{} 250.0 250.0} do_execsql_test strict1-8.2 { CREATE TABLE t1(x REAL, y REAL AS (x)) STRICT; INSERT INTO t1 VALUES(5),(4611686018427387904); SELECT *, '|' FROM t1; } {/5.0 5.0 4.6116\d*e\+18 4.6116\d+e\+18 |/} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | SELECT * FROM transactions; } {{} 250.0 250.0} do_execsql_test strict1-8.2 { CREATE TABLE t1(x REAL, y REAL AS (x)) STRICT; INSERT INTO t1 VALUES(5),(4611686018427387904); SELECT *, '|' FROM t1; } {/5.0 5.0 4.6116\d*e\+18 4.6116\d+e\+18 |/} # 2025-06-18 https://sqlite.org/forum/forumpost/6caf195248a849e4 # # Enforce STRICT table type constraints on STORED generated columns # do_execsql_test strict1-9.1 { CREATE TABLE strict ( k INTEGER PRIMARY KEY, c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) STORED, c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) STORED, c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) STORED, c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) STORED, c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) STORED ) STRICT; INSERT INTO strict(k) VALUES(11); INSERT INTO strict(k) VALUES(12); INSERT INTO strict(k) VALUES(22); INSERT INTO strict(k) VALUES(31); INSERT INTO strict(k) VALUES(32); INSERT INTO strict(k) VALUES(33); INSERT INTO strict(k) VALUES(44); PRAGMA integrity_check; } {ok} do_catchsql_test strict1-9.2.13 { INSERT INTO strict(k) VALUES(13); } {1 {cannot store TEXT value in REAL column strict.c1}} do_catchsql_test strict1-9.2.14 { INSERT INTO strict(k) VALUES(14); } {1 {cannot store BLOB value in REAL column strict.c1}} do_catchsql_test strict1-9.2.21 { INSERT INTO strict(k) VALUES(21); } {1 {cannot store REAL value in INT column strict.c2}} do_catchsql_test strict1-9.2.23 { INSERT INTO strict(k) VALUES(23); } {1 {cannot store TEXT value in INT column strict.c2}} do_catchsql_test strict1-9.2.24 { INSERT INTO strict(k) VALUES(24); } {1 {cannot store BLOB value in INT column strict.c2}} do_catchsql_test strict1-9.2.34 { INSERT INTO strict(k) VALUES(34); } {1 {cannot store BLOB value in TEXT column strict.c3}} do_catchsql_test strict1-9.2.41 { INSERT INTO strict(k) VALUES(41); } {1 {cannot store REAL value in BLOB column strict.c4}} do_catchsql_test strict1-9.2.42 { INSERT INTO strict(k) VALUES(42); } {1 {cannot store INT value in BLOB column strict.c4}} do_catchsql_test strict1-9.2.43 { INSERT INTO strict(k) VALUES(43); } {1 {cannot store TEXT value in BLOB column strict.c4}} do_execsql_test strict1-9.3 { DROP TABLE strict; CREATE TABLE strict ( k INTEGER PRIMARY KEY, c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) VIRTUAL, c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) VIRTUAL, c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) VIRTUAL, c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) VIRTUAL, c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) VIRTUAL ) STRICT; INSERT INTO strict(k) VALUES(11); INSERT INTO strict(k) VALUES(12); INSERT INTO strict(k) VALUES(22); INSERT INTO strict(k) VALUES(31); INSERT INTO strict(k) VALUES(32); INSERT INTO strict(k) VALUES(33); INSERT INTO strict(k) VALUES(44); PRAGMA integrity_check; } {ok} do_catchsql_test strict1-9.4.13 { INSERT INTO strict(k) VALUES(13); } {1 {cannot store TEXT value in REAL column strict.c1}} do_catchsql_test strict1-9.4.14 { INSERT INTO strict(k) VALUES(14); } {1 {cannot store BLOB value in REAL column strict.c1}} do_catchsql_test strict1-9.4.21 { INSERT INTO strict(k) VALUES(21); } {1 {cannot store REAL value in INT column strict.c2}} do_catchsql_test strict1-9.4.23 { INSERT INTO strict(k) VALUES(23); } {1 {cannot store TEXT value in INT column strict.c2}} do_catchsql_test strict1-9.4.24 { INSERT INTO strict(k) VALUES(24); } {1 {cannot store BLOB value in INT column strict.c2}} do_catchsql_test strict1-9.4.34 { INSERT INTO strict(k) VALUES(34); } {1 {cannot store BLOB value in TEXT column strict.c3}} do_catchsql_test strict1-9.4.41 { INSERT INTO strict(k) VALUES(41); } {1 {cannot store REAL value in BLOB column strict.c4}} do_catchsql_test strict1-9.4.42 { INSERT INTO strict(k) VALUES(42); } {1 {cannot store INT value in BLOB column strict.c4}} do_catchsql_test strict1-9.4.43 { INSERT INTO strict(k) VALUES(43); } {1 {cannot store TEXT value in BLOB column strict.c4}} finish_test |
Changes to test/tclsqlite.test.
1 2 3 4 5 6 7 8 9 10 11 | # 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 file implements regression tests for TCL interface to the | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 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 file implements regression tests for TCL interface to the # SQLite library. # # Actually, all tests are based on the TCL interface, so the main # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # # $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $ |
︙ | ︙ | |||
117 118 119 120 121 122 123 | set v [catch {db complete} msg] lappend v $msg } {1 {wrong # args: should be "db complete SQL"}} } do_test tcl-1.14 { set v [catch {db eval} msg] lappend v $msg | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | set v [catch {db complete} msg] lappend v $msg } {1 {wrong # args: should be "db complete SQL"}} } do_test tcl-1.14 { set v [catch {db eval} msg] lappend v $msg } {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?"}} do_test tcl-1.15 { set v [catch {db function} msg] lappend v $msg } {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}} do_test tcl-1.16 { set v [catch {db last_insert_rowid xyz} msg] lappend v $msg |
︙ | ︙ | |||
354 355 356 357 358 359 360 361 362 363 364 365 366 367 | db function ret_dbl {return [expr {rand()*0.5}]} execsql {SELECT typeof(ret_dbl())} } {real} do_test tcl-9.3 { db function ret_int {return [expr {int(rand()*200)}]} execsql {SELECT typeof(ret_int())} } {integer} # Recursive calls to the same user-defined function # ifcapable tclvar { do_test tcl-9.10 { proc userfunc_r1 {n} { if {$n<=0} {return 0} | > > > > > > > > > > > > > | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | db function ret_dbl {return [expr {rand()*0.5}]} execsql {SELECT typeof(ret_dbl())} } {real} do_test tcl-9.3 { db function ret_int {return [expr {int(rand()*200)}]} execsql {SELECT typeof(ret_int())} } {integer} proc breakAsNullUdf args { if {"1" eq [lindex $args 0]} {return -code break} } do_test tcl-9.4 { db function banu breakAsNullUdf execsql {SELECT typeof(banu()), typeof(banu(1))} } {text null} do_test tcl-9.5 { db nullvalue banunull db eval {SELECT banu(), banu(1)} } {{} banunull} # Recursive calls to the same user-defined function # ifcapable tclvar { do_test tcl-9.10 { proc userfunc_r1 {n} { if {$n<=0} {return 0} |
︙ | ︙ | |||
461 462 463 464 465 466 467 | } }] } {2} do_test tcl-10.13 { db eval {SELECT * FROM t4} } {1 2 5 6 7} | | | | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | } }] } {2} do_test tcl-10.13 { db eval {SELECT * FROM t4} } {1 2 5 6 7} # Now test that [db transaction] commands may be nested with # the expected results. # do_test tcl-10.14 { db transaction { db eval { DELETE FROM t4; INSERT INTO t4 VALUES('one'); } catch { db transaction { db eval { INSERT INTO t4 VALUES('two') } db transaction { db eval { INSERT INTO t4 VALUES('three') } error "throw an error!" } } |
︙ | ︙ | |||
670 671 672 673 674 675 676 | db exists {SELECT a FROM t1 WHERE a>2} } {1} do_test tcl-15.5 { db exists {SELECT a FROM t1 WHERE a>3} } {0} | | | | | | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 | db exists {SELECT a FROM t1 WHERE a>2} } {1} do_test tcl-15.5 { db exists {SELECT a FROM t1 WHERE a>3} } {0} # 2017-06-26: The -withoutnulls flag to "db eval". # # In the "db eval -withoutnulls SQL TARGET" form, NULL results cause the # corresponding target entry to be unset. The default behavior (without # the -withoutnulls flags) is for the corresponding target value to get # the [db nullvalue] string. # catch {db close} forcedelete test.db sqlite3 db test.db do_execsql_test tcl-16.100 { CREATE TABLE t1(a,b); |
︙ | ︙ | |||
716 717 718 719 720 721 722 | #------------------------------------------------------------------------- # Test the -type option to [db function]. # reset_db proc add {a b} { return [expr $a + $b] } proc ret {a} { return $a } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | #------------------------------------------------------------------------- # Test the -type option to [db function]. # reset_db proc add {a b} { return [expr $a + $b] } proc ret {a} { return $a } db function add_i -returntype integer add db function add_r -ret real add db function add_t -return text add db function add_b -returntype blob add db function add_a -returntype any add db function ret_i -returntype int ret db function ret_r -returntype real ret db function ret_t -returntype text ret db function ret_b -returntype blob ret db function ret_a -r any ret do_execsql_test 17.0 { SELECT quote( add_i(2, 3) ); SELECT quote( add_r(2, 3) ); SELECT quote( add_t(2, 3) ); SELECT quote( add_b(2, 3) ); SELECT quote( add_a(2, 3) ); } {5 5.0 '5' X'35' 5} do_execsql_test 17.1 { SELECT quote( add_i(2.2, 3.3) ); SELECT quote( add_r(2.2, 3.3) ); SELECT quote( add_t(2.2, 3.3) ); SELECT quote( add_b(2.2, 3.3) ); SELECT quote( add_a(2.2, 3.3) ); } {5.5 5.5 '5.5' X'352E35' 5.5} do_execsql_test 17.2 { SELECT quote( ret_i(2.5) ); SELECT quote( ret_r(2.5) ); SELECT quote( ret_t(2.5) ); SELECT quote( ret_b(2.5) ); SELECT quote( ret_a(2.5) ); } {2.5 2.5 '2.5' X'322E35' 2.5} do_execsql_test 17.3 { SELECT quote( ret_i('2.5') ); SELECT quote( ret_r('2.5') ); SELECT quote( ret_t('2.5') ); SELECT quote( ret_b('2.5') ); SELECT quote( ret_a('2.5') ); } {2.5 2.5 '2.5' X'322E35' '2.5'} do_execsql_test 17.4 { SELECT quote( ret_i('abc') ); SELECT quote( ret_r('abc') ); SELECT quote( ret_t('abc') ); SELECT quote( ret_b('abc') ); SELECT quote( ret_a('abc') ); } {'abc' 'abc' 'abc' X'616263' 'abc'} do_execsql_test 17.5 { SELECT quote( ret_i(X'616263') ); SELECT quote( ret_r(X'616263') ); SELECT quote( ret_t(X'616263') ); SELECT quote( ret_b(X'616263') ); SELECT quote( ret_a(X'616263') ); } {'abc' 'abc' 'abc' X'616263' X'616263'} do_test 17.6.1 { list [catch { db function xyz -return object ret } msg] $msg } {1 {bad type "object": must be integer, real, text, blob, or any}} do_test 17.6.2 { |
︙ | ︙ | |||
844 845 846 847 848 849 850 851 | db bind_fallback bind_fallback_does_not_exist } {} do_catchsql_test 19.911 { SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi); } {1 {invalid command name "bind_fallback_does_not_exist"}} db bind_fallback {} #------------------------------------------------------------------------- | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | | > | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | db bind_fallback bind_fallback_does_not_exist } {} do_catchsql_test 19.911 { SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi); } {1 {invalid command name "bind_fallback_does_not_exist"}} db bind_fallback {} # 2025-05-05: the -asdict eval flag # do_test 20.0 { execsql {CREATE TABLE tad(a,b)} execsql {INSERT INTO tad(a,b) VALUES('aa','bb'),('AA','BB')} db eval -asdict { SELECT a, b FROM tad WHERE 0 } D {} set D } {* {a b}} do_test 20.1 { unset D set i 0 set res {} set colNames {} db eval -asdict { SELECT a, b FROM tad ORDER BY a } D { dict set D i [incr i] lappend res $i [dict get $D a] [dict get $D b] if {1 == $i} { set colNames [dict get $D *] } } lappend res $colNames unset D set res } {1 AA BB 2 aa bb {a b}} do_test 20.2 { set res {} db eval -asdict -withoutnulls { SELECT n, a, b FROM ( SELECT 1 as n, 'aa' as a, NULL as b UNION ALL SELECT 2 as n, NULL as a, 'bb' as b ) ORDER BY n } D { dict unset D * lappend res [dict values $D] } unset D execsql {DROP TABLE tad} set res } {{1 aa} {2 bb}} #------------------------------------------------------------------------- do_test 21.0 { db transaction { db close } } {} do_test 21.1 { sqlite3 db test.db set rc [catch { db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close } } msg] list $rc $msg } {1 {invalid command name "db"}} proc closedb {} { db close return 10 } proc func1 {} { return 1 } sqlite3 db test.db db func closedb closedb db func func1 func1 do_test 21.2 { set rc [catch { db eval { SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40 } } msg] list $rc $msg } {0 {10 1 20 30 30 40}} sqlite3 db :memory: do_test 22.1 { catch {db eval {SELECT 1 2 3;}} msg db erroroffset } {9} finish_test |
Changes to test/vacuum.test.
︙ | ︙ | |||
396 397 398 399 400 401 402 403 404 | CREATE TABLE t8(a, b); INSERT INTO t8 VALUES('a', 'b'); INSERT INTO t8 VALUES('c', 'd'); PRAGMA count_changes = 1; } } {} do_test vacuum-10.2 { execsql VACUUM } {} finish_test | > > > > > > > > > > > > > > > > > > > > > | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | CREATE TABLE t8(a, b); INSERT INTO t8 VALUES('a', 'b'); INSERT INTO t8 VALUES('c', 'd'); PRAGMA count_changes = 1; } } {} do_test vacuum-10.2 { execsql VACUUM } {} # Verify that VACUUM still works if ATTACH is disabled. # do_execsql_test vacuum-11.1 { PRAGMA page_size=1024; VACUUM; PRAGMA page_size; } {1024} sqlite3_db_config db ATTACH_CREATE 0 do_execsql_test vacuum-11.2 { PRAGMA page_size=2048; VACUUM; PRAGMA page_size; } {2048} sqlite3_db_config db ATTACH_CREATE 1 sqlite3_db_config db ATTACH_WRITE 0 do_execsql_test vacuum-11.3 { PRAGMA page_size=4096; VACUUM; PRAGMA page_size; } {4096} finish_test |
Changes to test/walcksum.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } # Read and return the contents of file $filename. Treat the content as # binary data. # proc readfile {filename} { set fd [open $filename] fconfigure $fd -translation binary | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } set testprefix walcksum # Read and return the contents of file $filename. Treat the content as # binary data. # proc readfile {filename} { set fd [open $filename] fconfigure $fd -translation binary |
︙ | ︙ | |||
326 327 328 329 330 331 332 333 | execsql { PRAGMA integrity_check; SELECT count(*) FROM t1; } db2 } {ok 256} catch { db close } catch { db2 close } | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | execsql { PRAGMA integrity_check; SELECT count(*) FROM t1; } db2 } {ok 256} catch { db close } catch { db2 close } #------------------------------------------------------------------------- # Test cases based on the bug reported at: # # <https://sqlite.org/forum/forumpost/b490f726db> # reset_db do_execsql_test 3.0 { PRAGMA auto_vacuum = 0; PRAGMA synchronous = NORMAL; PRAGMA journal_mode = WAL; PRAGMA cache_size = 1; CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, randomblob(2048), 'one'); } {wal 0 2 2} do_execsql_test 3.1 { BEGIN; INSERT INTO t1 VALUES(2, randomblob(2048), 'two'); SAVEPOINT one; INSERT INTO t1 VALUES(3, randomblob(2048), 'three'); INSERT INTO t1 VALUES(4, randomblob(2048), 'four'); INSERT INTO t1 VALUES(5, randomblob(2048), 'five'); INSERT INTO t1 VALUES(6, randomblob(2048), 'six'); INSERT INTO t1 VALUES(7, randomblob(2048), 'seven'); UPDATE t1 SET b=randomblob(2048) WHERE i=5; UPDATE t1 SET b=randomblob(2048) WHERE i=6; UPDATE t1 SET b=randomblob(2048) WHERE i=7; ROLLBACK TO one; INSERT INTO t1 VALUES(8, NULL, 'eight'); COMMIT; } {} do_execsql_test 3.2 { SELECT i, t FROM t1 } {1 one 2 two 8 eight} forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db do_test 1.3 { execsql { SELECT i, t FROM t1 } db2 } {1 one 2 two 8 eight} catch { db2 close } #------------------------------------------------------------------------- reset_db do_execsql_test 4.0 { PRAGMA auto_vacuum = 0; PRAGMA synchronous = NORMAL; PRAGMA journal_mode = WAL; PRAGMA cache_size = 1; CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, randomblob(2048), 'one'); } {wal 0 2 2} do_execsql_test 4.1.1 { SAVEPOINT one; INSERT INTO t1 VALUES(2, randomblob(2048), 'two'); INSERT INTO t1 VALUES(3, randomblob(2048), 'three'); INSERT INTO t1 VALUES(4, randomblob(2048), 'four'); INSERT INTO t1 VALUES(5, randomblob(2048), 'five'); INSERT INTO t1 VALUES(6, randomblob(2048), 'six'); INSERT INTO t1 VALUES(7, randomblob(2048), 'seven'); UPDATE t1 SET b=randomblob(2048) WHERE i=5; UPDATE t1 SET b=randomblob(2048) WHERE i=6; UPDATE t1 SET b=randomblob(2048) WHERE i=7; } do_execsql_test 4.1.2 { ROLLBACK TO one; INSERT INTO t1 VALUES(8, NULL, 'eight'); RELEASE one; } {} do_execsql_test 4.2 { SELECT i, t FROM t1 } {1 one 8 eight} forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db do_test 4.3 { execsql { SELECT i, t FROM t1 } db2 } {1 one 8 eight} catch { db2 close } #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { PRAGMA auto_vacuum = 0; PRAGMA synchronous = NORMAL; PRAGMA journal_mode = WAL; PRAGMA cache_size = 1; CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT); INSERT INTO t1 VALUES(1, randomblob(2048), 'one'); INSERT INTO t1 VALUES(2, randomblob(2048), 'two'); INSERT INTO t1 VALUES(3, randomblob(2048), 'three'); PRAGMA wal_checkpoint; } {wal 0 14 14} do_execsql_test 5.1 { BEGIN; SELECT count(*) FROM t1; SAVEPOINT one; INSERT INTO t1 VALUES(4, randomblob(2048), 'four'); INSERT INTO t1 VALUES(5, randomblob(2048), 'five'); INSERT INTO t1 VALUES(6, randomblob(2048), 'six'); INSERT INTO t1 VALUES(7, randomblob(2048), 'seven'); ROLLBACK TO one; INSERT INTO t1 VALUES(8, randomblob(2048), 'eight'); INSERT INTO t1 VALUES(9, randomblob(2048), 'nine'); COMMIT; } {3} forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db do_test 5.2 { execsql { SELECT i, t FROM t1 } db2 } {1 one 2 two 3 three 8 eight 9 nine} db2 close do_execsql_test 5.3 { SELECT i, t FROM t1 } {1 one 2 two 3 three 8 eight 9 nine} finish_test |
Changes to test/walsetlk2.test.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | tvfs delete #------------------------------------------------------------------------- # Check that if sqlite3_setlk_timeout() is used, blocking locks timeout # but other operations do not use the retry mechanism. # reset_db do_execsql_test 2.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2), (3, 4); } sqlite3_setlk_timeout db 2000 | > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | tvfs delete #------------------------------------------------------------------------- # Check that if sqlite3_setlk_timeout() is used, blocking locks timeout # but other operations do not use the retry mechanism. # reset_db db close sqlite3 db test.db -fullmutex 1 do_execsql_test 2.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2), (3, 4); } sqlite3_setlk_timeout db 2000 |
︙ | ︙ |
Added test/walsetlk_recover.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 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 36 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | # 2025 May 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. # #*********************************************************************** # # TESTRUNNER: slow # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix walsetlk_recover ifcapable !wal {finish_test ; return } # ifcapable !setlk_timeout {finish_test ; return } do_execsql_test 1.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); } {wal} db_save_and_close db_restore testfixture_nb myvar { testvfs tvfs -fullshm 1 sqlite3 db test.db -vfs tvfs tvfs script vfs_callback tvfs filter xRead set ::done 0 proc vfs_callback {method file args} { if {$::done==0 && [string match *wal $file]} { after 4000 set ::done 1 } return "SQLITE_OK" } db eval { SELECT * FROM t1 } db close } # Give the [testfixture_nb] command time to start after 1000 {set xyz 1} vwait xyz testvfs tvfs -fullshm 1 sqlite3 db test.db -vfs tvfs tvfs script sleep_callback tvfs filter xSleep set ::sleep_count 0 proc sleep_callback {args} { incr ::sleep_count } sqlite3 db test.db -vfs tvfs db timeout 500 set tm [lindex [time { catch { db eval {SELECT * FROM t1} } msg }] 0] do_test 1.2 { set ::msg } {database is locked} do_test 1.3.($::tm) { expr $::tm>400000 && $::tm<2000000 } 1 vwait myvar do_execsql_test 1.4 { SELECT * FROM t1 } {1 2 3 4 5 6} db close tvfs delete # All SQLite builds should pass the tests above. SQLITE_ENABLE_SETLK_TIMEOUT=1 # builds do so without calling the VFS xSleep method. if {$::sqlite_options(setlk_timeout)==1} { do_test 1.5.1 { set ::sleep_count } 0 } else { do_test 1.5.2 { expr $::sleep_count>0 } 1 } finish_test |
Added test/walsetlk_snapshot.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 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 36 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # 2025 May 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. # #*********************************************************************** # # TESTRUNNER: slow # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix walsetlk_snapshot ifcapable !wal {finish_test ; return } ifcapable !snapshot {finish_test; return} db close testvfs tvfs -fullshm 1 sqlite3 db test.db -vfs tvfs tvfs script sleep_callback tvfs filter xSleep set ::sleep_count 0 proc sleep_callback {args} { incr ::sleep_count } do_execsql_test 1.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); } {wal} do_test 1.1 { db eval BEGIN set ::snap [sqlite3_snapshot_get db main] db eval { INSERT INTO t1 VALUES(7, 8); COMMIT; } } {} testfixture_nb myvar { testvfs tvfs -fullshm 1 sqlite3 db test.db -vfs tvfs tvfs script vfs_callback tvfs filter {xWrite} set ::done 0 proc vfs_callback {args} { if {$::done==0} { after 4000 set ::done 1 } return "SQLITE_OK" } db eval { PRAGMA wal_checkpoint; } db close } # Give the [testfixture_nb] command time to start after 1000 {set xyz 1} vwait xyz db timeout 500 set tm [lindex [time { catch { db eval BEGIN sqlite3_snapshot_open db main $::snap } msg }] 0] do_test 1.2 { set ::msg } {SQLITE_BUSY} do_test 1.3.($::tm) { expr $::tm<2000000 } 1 do_execsql_test 1.4 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} sqlite3_snapshot_free $::snap vwait myvar # All SQLite builds should pass the tests above. SQLITE_ENABLE_SETLK_TIMEOUT=1 # builds do so without calling the VFS xSleep method. if {$::sqlite_options(setlk_timeout)==1} { do_test 1.5.1 { set ::sleep_count } 0 } else { do_test 1.5.2 { expr $::sleep_count>0 } 1 } finish_test |
Changes to tool/buildtclext.tcl.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | --build-only Only build the extension, don't install it --cc COMPILER Build using this compiler --info Show info on existing SQLite TCL extension installs --install-only Install an extension previously build --uninstall Uninstall the extension --version-check Check extension version against this source tree --destdir DIR Installation root (used by "make install DESTDIR=...") Other options are retained and passed through into the compiler.} set build 1 set install 1 set uninstall 0 set infoonly 0 set versioncheck 0 set CC {} set OPTS {} set DESTDIR ""; # --destdir "$(DESTDIR)" for {set ii 0} {$ii<[llength $argv]} {incr ii} { set a0 [lindex $argv $ii] if {$a0=="--install-only"} { set build 0 } elseif {$a0=="--build-only"} { set install 0 } elseif {$a0=="--uninstall"} { | > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | --build-only Only build the extension, don't install it --cc COMPILER Build using this compiler --info Show info on existing SQLite TCL extension installs --install-only Install an extension previously build --uninstall Uninstall the extension --version-check Check extension version against this source tree --destdir DIR Installation root (used by "make install DESTDIR=...") --tclConfig.sh FILE Use this tclConfig.sh instead of looking for one Other options are retained and passed through into the compiler.} set build 1 set install 1 set uninstall 0 set infoonly 0 set versioncheck 0 set CC {} set OPTS {} set DESTDIR ""; # --destdir "$(DESTDIR)" set tclConfigSh ""; # --tclConfig.sh FILE for {set ii 0} {$ii<[llength $argv]} {incr ii} { set a0 [lindex $argv $ii] if {$a0=="--install-only"} { set build 0 } elseif {$a0=="--build-only"} { set install 0 } elseif {$a0=="--uninstall"} { |
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 | set versioncheck 1 } elseif {$a0=="--cc" && $ii+1<[llength $argv]} { incr ii set CC [lindex $argv $ii] } elseif {$a0=="--destdir" && $ii+1<[llength $argv]} { incr ii set DESTDIR [lindex $argv $ii] } elseif {[string match -* $a0]} { append OPTS " $a0" } else { puts stderr "Unknown option: \"$a0\"\n" puts stderr $help exit 1 } | > > > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | set versioncheck 1 } elseif {$a0=="--cc" && $ii+1<[llength $argv]} { incr ii set CC [lindex $argv $ii] } elseif {$a0=="--destdir" && $ii+1<[llength $argv]} { incr ii set DESTDIR [lindex $argv $ii] } elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} { incr ii set tclConfigSh [lindex $argv $ii] } elseif {[string match -* $a0]} { append OPTS " $a0" } else { puts stderr "Unknown option: \"$a0\"\n" puts stderr $help exit 1 } |
︙ | ︙ | |||
84 85 86 87 88 89 90 | puts "Unable to build on Windows using the builttclext.tcl script." puts "To build, run\n" puts " \"nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll" exit 1 } set OUT tclsqlite3.dll } else { | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > | | < | | | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | puts "Unable to build on Windows using the builttclext.tcl script." puts "To build, run\n" puts " \"nmake /f Makefile.msc pkgIndex.tcl tclsqlite3.dll" exit 1 } set OUT tclsqlite3.dll } else { # Read the tclConfig.sh file into the $tclConfig variable # if {"" eq $tclConfigSh} { # Figure out the location of the tclConfig.sh file used by the # tclsh that is executing this script. # if {[catch { set LIBDIR [tcl::pkgconfig get libdir,install] }]} { puts stderr "$argv0: tclsh does not support tcl::pkgconfig." exit 1 } if {![file exists $LIBDIR]} { puts stderr "$argv0: cannot find the tclConfig.sh file." puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\ does not exist." exit 1 } if {![file exists $LIBDIR/tclConfig.sh] || [file size $LIBDIR/tclConfig.sh]<5000} { set n1 $LIBDIR/tcl$::tcl_version if {[file exists $n1/tclConfig.sh] && [file size $n1/tclConfig.sh]>5000} { set LIBDIR $n1 } else { puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1" exit 1 } } #puts "using $LIBDIR/tclConfig.sh" set fd [open $LIBDIR/tclConfig.sh rb] set tclConfig [read $fd] close $fd } else { # User-provided tclConfig.sh # set fd [open $tclConfigSh rb] set tclConfig [read $fd] close $fd } # Extract parameter we will need from the tclConfig.sh file # set TCLMAJOR 8 regexp {TCL_MAJOR_VERSION='(\d)'} $tclConfig all TCLMAJOR set SUFFIX so regexp {TCL_SHLIB_SUFFIX='\.([^']+)'} $tclConfig all SUFFIX |
︙ | ︙ |
Changes to tool/lemon.c.
︙ | ︙ | |||
2019 2020 2021 2022 2023 2024 2025 | offset = (unsigned long)((char*)next - (char*)list); for(i=0; i<LISTSIZE; i++) set[i] = 0; while( list ){ ep = list; list = NEXT(list); NEXT(ep) = 0; for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ | | | | 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 | offset = (unsigned long)((char*)next - (char*)list); for(i=0; i<LISTSIZE; i++) set[i] = 0; while( list ){ ep = list; list = NEXT(list); NEXT(ep) = 0; for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ ep = merge(set[i],ep,cmp,offset); set[i] = 0; } set[i] = merge(set[i],ep,cmp,offset); } ep = 0; for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset); return ep; } /************************ From the file "option.c" **************************/ static char **g_argv; |
︙ | ︙ | |||
5921 5922 5923 5924 5925 5926 5927 | return array; } /* Hash a configuration */ PRIVATE unsigned confighash(struct config *a) { unsigned h=0; | | | 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 | return array; } /* Hash a configuration */ PRIVATE unsigned confighash(struct config *a) { unsigned h=0; h = a->rp->index*37 + a->dot; return h; } /* There is one instance of the following structure for each ** associative array of type "x4". */ struct s_x4 { |
︙ | ︙ |
Changes to tool/mkshellc.tcl.
︙ | ︙ | |||
58 59 60 61 62 63 64 | set in2 [open $topdir/src/$cfile] fconfigure $in2 -translation binary while {![eof $in2]} { set lx [omit_redundant_typedefs [gets $in2]] if {[regexp {^# *include "sqlite} $lx]} { set lx "/* $lx */" } | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | set in2 [open $topdir/src/$cfile] fconfigure $in2 -translation binary while {![eof $in2]} { set lx [omit_redundant_typedefs [gets $in2]] if {[regexp {^# *include "sqlite} $lx]} { set lx "/* $lx */" } if {[regexp {^# *include "windirent.h"} $lx]} { set lx "/* $lx */" } set lx [string map [list __declspec(dllexport) {}] $lx] puts $out $lx } close $in2 puts $out "/************************* End $cfile ********************/" |
︙ | ︙ |
Changes to tool/sqlite3_rsync.c.
︙ | ︙ | |||
1534 1535 1536 1537 1538 1539 1540 | if( p->zDebugFile ) debugMessage(p, "-> ORIGIN_READY\n"); }else{ sqlite3_finalize(pCkHash); sqlite3_finalize(pCkHashN); sqlite3_finalize(pInsHash); pCkHash = 0; pInsHash = 0; | | | 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 | if( p->zDebugFile ) debugMessage(p, "-> ORIGIN_READY\n"); }else{ sqlite3_finalize(pCkHash); sqlite3_finalize(pCkHashN); sqlite3_finalize(pInsHash); pCkHash = 0; pInsHash = 0; if( mxHash<=p->nPage ){ runSql(p, "WITH RECURSIVE c(n) AS" " (VALUES(%d) UNION ALL SELECT n+1 FROM c WHERE n<%d)" " INSERT INTO badHash SELECT n, 1 FROM c", mxHash, p->nPage); } runSql(p, "DELETE FROM badHash WHERE pgno=%d", lockBytePage); pStmt = prepareStmt(p, |
︙ | ︙ | |||
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | rc = sqlite3_open(":memory:", &p->db); if( rc ){ reportError(p, "cannot open in-memory database: %s", sqlite3_errmsg(p->db)); closeDb(p); break; } runSql(p, "ATTACH %Q AS 'replica'", p->zReplica); if( p->wrongEncoding ){ p->wrongEncoding = 0; runSql(p, "PRAGMA encoding=utf16le"); runSql(p, "ATTACH %Q AS 'replica'", p->zReplica); if( p->wrongEncoding ){ p->wrongEncoding = 0; | > | 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 | rc = sqlite3_open(":memory:", &p->db); if( rc ){ reportError(p, "cannot open in-memory database: %s", sqlite3_errmsg(p->db)); closeDb(p); break; } sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); runSql(p, "ATTACH %Q AS 'replica'", p->zReplica); if( p->wrongEncoding ){ p->wrongEncoding = 0; runSql(p, "PRAGMA encoding=utf16le"); runSql(p, "ATTACH %Q AS 'replica'", p->zReplica); if( p->wrongEncoding ){ p->wrongEncoding = 0; |
︙ | ︙ |