Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e1c2f0483 | |||
| 86d9c2d9f3 | |||
| d3a13f7d25 | |||
| 6ed5aa4b9b | |||
| 67f708298f | |||
| 792d1d1b6d | |||
| 6a5e74cbf0 | |||
| 23e59b34e9 | |||
| a09a4fbac9 | |||
| 6a23ff5a07 | |||
| 5706b316c3 | |||
| 90ba0d4995 | |||
| f091f423ad | |||
| 4c323ba4be | |||
| 368c549044 | |||
| b1929b7117 | |||
| 6facd9566d | |||
| 26370358b6 | |||
| a29b138692 | |||
| 1d151e6d25 | |||
| df724c893a | |||
| 140748f949 | |||
| 2bd9f69d40 | |||
| 333b07b18d | |||
| 9269b212bf | |||
| 69ce758efa | |||
| 342ef63e63 | |||
| cfee69fbe4 | |||
| eb9a145711 | |||
| d84bbac8be | |||
| a3fcd7c79e | |||
| 8658a8df59 | |||
| 7590bfd7fc | |||
| d4c224b833 | |||
| f18bf8997b | |||
| c0190101d1 | |||
| 977b0f8813 | |||
| 0d3e5ca28e | |||
| 51e3f855b8 | |||
| 5248693924 | |||
| 420233e375 | |||
| 1ff4233f90 | |||
| 10206572b6 | |||
| b504aab848 | |||
| d930d7ef14 | |||
| ded1959120 | |||
| dd16539e71 | |||
| 88ed38ca6d | |||
| f42ceb9075 | |||
| 7ac10ec8b5 | |||
| 8ae57fab64 | |||
| b65326f51a | |||
| 0148820fd7 | |||
| d2b230a488 | |||
| f429845a60 | |||
| b163f66de0 | |||
| 3f52361352 | |||
| b3c1884b65 | |||
| b3bcf489a4 | |||
| f08f71a21d | |||
| f96d44e5de | |||
| 209894c2f5 | |||
| 93394ebc27 | |||
| 8f06aed1df | |||
| 3f01048954 | |||
| 45fa2347fe | |||
| a01b7adb13 | |||
| c5031b578b | |||
| 81a2f7ba8f | |||
| 85f37eba16 | |||
| c1ea1a6d4d | |||
| 96e16194b8 | |||
| 4a0b7a332f | |||
| 79c792d5d9 | |||
| 890de76cf5 | |||
| a58208a214 | |||
| acf95a3217 | |||
| 953e450e8e |
+11
-6
@@ -1623,7 +1623,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test_thread.c \
|
||||
$(TOP)\src\test_vdbecov.c \
|
||||
$(TOP)\src\test_vfs.c \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_window.c \
|
||||
$(TOP)\src\test_wsd.c \
|
||||
$(TOP)\ext\fts3\fts3_term.c \
|
||||
@@ -2395,12 +2394,11 @@ SHELL_DEP = \
|
||||
$(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 \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_windirent.h
|
||||
$(TOP)\ext\recover\sqlite3recover.h
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
#
|
||||
@@ -2585,7 +2583,7 @@ sqlite_tcl.h:
|
||||
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) -I$(TOP)\ext\misc \
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
@@ -2674,7 +2672,14 @@ srctree-check: $(TOP)\tool\srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest:
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ install: install-lib
|
||||
#
|
||||
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)
|
||||
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib) $(LDFLAGS.math)
|
||||
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
|
||||
sqlite3-shell-deps.0 = $(libsqlite3.DLL)
|
||||
#
|
||||
|
||||
+51
-28
@@ -146,7 +146,7 @@ LDFLAGS.shlib = @SH_LDFLAGS@
|
||||
# sources passed to [teaish-src-add], but may also be appended to by
|
||||
# teaish.make.
|
||||
#
|
||||
tx.src =@TEAISH_EXT_SRC@
|
||||
tx.src = @TEAISH_EXT_SRC@
|
||||
|
||||
#
|
||||
# tx.CFLAGS is typically set by teaish.make, whereas TEAISH_CFLAGS
|
||||
@@ -167,6 +167,11 @@ tx.LDFLAGS =
|
||||
#
|
||||
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 = \
|
||||
@@ -199,9 +204,14 @@ $(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \
|
||||
@AUTODEPS@
|
||||
|
||||
@if TEAISH_TESTER_TCL_IN
|
||||
@TEAISH_TESTER_TCL_IN@:
|
||||
@TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
|
||||
config.log: @TEAISH_TESTER_TCL@
|
||||
@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
|
||||
|
||||
#
|
||||
@@ -217,7 +227,7 @@ CC.tcl = \
|
||||
#
|
||||
CC.dll = \
|
||||
$(CC.tcl) $(tx.src) $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS.configure) $(LDFLAGS) $(tx.LDFLAGS) $(TCL_STUB_LIB_SPEC)
|
||||
$(tx.LDFLAGS) $(LDFLAGS.configure) $(LDFLAGS) $(TCL_STUB_LIB_SPEC)
|
||||
|
||||
@if TEAISH_ENABLE_DLL
|
||||
#
|
||||
@@ -248,16 +258,25 @@ test-extension: # this name is reserved for use by teaish.make[.in]
|
||||
test-prepre: $(tx.dll)
|
||||
@endif
|
||||
@if TEAISH_TESTER_TCL
|
||||
test-core.args = @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-prepre: @TEAISH_TESTER_TCL@
|
||||
$(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
|
||||
@@ -288,7 +307,7 @@ distclean-core: distclean-pre
|
||||
@endif
|
||||
@endif
|
||||
@if TEAISH_TESTER_TCL_IN
|
||||
rm -f @TEAISH_TESTER_TCL@
|
||||
rm -f $(teaish.tester.tcl)
|
||||
@endif
|
||||
@if TEAISH_PKGINDEX_TCL_IN
|
||||
rm -f @TEAISH_PKGINDEX_TCL@
|
||||
@@ -355,10 +374,15 @@ install-core: install-pre
|
||||
@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; ' \
|
||||
'set c 0; ' $$xtra \
|
||||
'@TEAISH_POSTINST_PREREQUIRE@' \
|
||||
'if {[catch {package require $(tx.name.pkg) $(tx.version)}]} {incr c};' \
|
||||
'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"; \
|
||||
@@ -406,7 +430,7 @@ config.log: $(teaish.makefile.in)
|
||||
# recognized when running in --teaish-install mode, causing
|
||||
# the sub-configure to fail.
|
||||
dist.flags = --with-tclsh=$(TCLSH)
|
||||
dist.reconfig = $(teaish.dir)/configure $(dist.flags)
|
||||
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.
|
||||
@@ -414,24 +438,23 @@ teaish__dist.tmp.zip = teaish__dist_zip
|
||||
#
|
||||
# Make a distribution zip file...
|
||||
#
|
||||
dist.basename = $(tx.name.dist)-$(tx.version)
|
||||
dist.zip = $(dist.basename).zip
|
||||
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)/$(dist.basename)
|
||||
@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)/$(dist.basename)
|
||||
@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)/$(dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
|
||||
--teaish-install=$(teaish__dist.tmp.zip)/$(tx.dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
|
||||
@endif
|
||||
@rm -f $(dist.basename)/tmp.tar $(dist.zip)
|
||||
@cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(dist.basename)
|
||||
@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)
|
||||
@@ -447,23 +470,23 @@ undist: undist-zip
|
||||
# Make a distribution tarball...
|
||||
#
|
||||
teaish__dist.tmp.tgz = teaish__dist_tgz
|
||||
dist.tgz = $(dist.basename).tar.gz
|
||||
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)/$(dist.basename)
|
||||
@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)/$(dist.basename)
|
||||
@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)/$(dist.basename)/pkgIndex.tcl.in; # kludge
|
||||
@rm -f $(teaish__dist.tmp.tgz)/$(tx.dist.basename)/pkgIndex.tcl.in; # kludge
|
||||
@$(dist.reconfig) \
|
||||
--teaish-install=$(teaish__dist.tmp.tgz)/$(dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
|
||||
--teaish-install=$(teaish__dist.tmp.tgz)/$(tx.dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
|
||||
@endif
|
||||
@rm -f $(dist.basename)/tmp.tar $(dist.tgz)
|
||||
@cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(dist.basename)
|
||||
@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)
|
||||
|
||||
+28
-33
@@ -41,24 +41,32 @@ 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
|
||||
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?
|
||||
And info about the extension's Tcl interface can be found at:
|
||||
|
||||
This TEA builder is derived from code 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
|
||||
|
||||
The SQLite developers do not understand how it works. It seems to
|
||||
work for us. It might also work for you. But we cannot promise that.
|
||||
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
|
||||
@@ -70,30 +78,17 @@ 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 more information about the build process, see
|
||||
the tcl/unix/README file in the Tcl src dist. The following minimal
|
||||
example will install the extension in the /opt/tcl directory.
|
||||
Building under most UNIX systems is easy, just run the configure
|
||||
script and then run make. For example:
|
||||
|
||||
$ cd sqlite-*-tea
|
||||
$ ./configure --prefix=/opt/tcl
|
||||
$ make
|
||||
$ ./configure --with-tcl=/path/to/tcl/install/root
|
||||
$ make test
|
||||
$ make install
|
||||
|
||||
WINDOWS BUILD
|
||||
=============
|
||||
|
||||
The recommended method to build extensions under windows is to use the
|
||||
Msys + Mingw build process. This provides a Unix-style build while
|
||||
generating native Windows binaries. Using the Msys + Mingw build tools
|
||||
means that you can use the same configure script as per the Unix build
|
||||
to create a Makefile. See the tcl/win/README file for the URL of
|
||||
the Msys + Mingw download.
|
||||
|
||||
If you have VC++ then you may wish to use the files in the win
|
||||
subdirectory and build the extension using just VC++. These files have
|
||||
been designed to be as generic as possible but will require some
|
||||
additional maintenance by the project developer to synchronise with
|
||||
the TEA configure.in and Makefile.in files. Instructions for using the
|
||||
VC++ makefile are written in the first part of the Makefile.vc
|
||||
file.
|
||||
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.
|
||||
|
||||
@@ -21,7 +21,8 @@ if {[llength [lindex $::argv 0]] > 0} {
|
||||
# ----^^^^^^^ needed on Haiku when argv 0 is just a filename, else
|
||||
# load cannot find the file.
|
||||
}
|
||||
source -encoding utf-8 [lindex $::argv 2]; # teaish/tester.tcl
|
||||
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]
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
.TH sqlite3 n 4.1 "Tcl-Extensions"
|
||||
.HS sqlite3 tcl
|
||||
.BS
|
||||
.SH NAME
|
||||
sqlite3 \- an interface to the SQLite3 database engine
|
||||
.SH SYNOPSIS
|
||||
\fBsqlite3\fI command_name ?filename?\fR
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
SQLite3 is a self-contains, zero-configuration, transactional SQL database
|
||||
engine. This extension provides an easy to use interface for accessing
|
||||
SQLite database files from Tcl.
|
||||
.PP
|
||||
For full documentation see \fIhttps://sqlite.org/\fR and
|
||||
in particular \fIhttps://sqlite.org/tclsqlite.html\fR.
|
||||
@@ -67,6 +67,7 @@ apply {{dir} {
|
||||
-vsatisfies 8.6-
|
||||
-libDir sqlite$version
|
||||
-pragmas $pragmas
|
||||
-src generic/tclsqlite3.c
|
||||
}
|
||||
}} [teaish-get -dir]
|
||||
|
||||
@@ -119,8 +120,6 @@ proc teaish-options {} {
|
||||
proc teaish-configure {} {
|
||||
use teaish/feature
|
||||
|
||||
teaish-src-add -dist -dir generic/tclsqlite3.c
|
||||
|
||||
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]
|
||||
|
||||
+387
-123
@@ -60,10 +60,11 @@
|
||||
# $proj__Config is an internal-use-only array for storing whatever generic
|
||||
# internal stuff we need stored.
|
||||
#
|
||||
array set ::proj__Config {
|
||||
self-tests 1
|
||||
}
|
||||
|
||||
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
|
||||
@@ -75,7 +76,6 @@ array set ::proj__Config {
|
||||
# See: proj-dot-ins-append and proj-dot-ins-process
|
||||
#
|
||||
set ::proj__Config(dot-in-files) [list]
|
||||
set ::proj__Config(isatty) [isatty? stdout]
|
||||
|
||||
#
|
||||
# @proj-warn msg
|
||||
@@ -85,28 +85,29 @@ set ::proj__Config(isatty) [isatty? stdout]
|
||||
#
|
||||
proc proj-warn {args} {
|
||||
show-notices
|
||||
puts stderr [join [list "WARNING: \[[proj-scope 1]\]: " {*}$args] " "]
|
||||
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 argv} {
|
||||
#
|
||||
proc proj__faterr {failMode args} {
|
||||
show-notices
|
||||
set lvl 1
|
||||
while {"-up" eq [lindex $argv 0]} {
|
||||
set argv [lassign $argv -]
|
||||
while {"-up" eq [lindex $args 0]} {
|
||||
set args [lassign $args -]
|
||||
incr lvl
|
||||
}
|
||||
if {$failMode} {
|
||||
puts stderr [join [list "FATAL: \[[proj-scope $lvl]]: " {*}$argv]]
|
||||
puts stderr [join [list "FATAL:" \[ [proj-scope $lvl] \]: {*}$args]]
|
||||
exit 1
|
||||
} else {
|
||||
error [join [list "\[[proj-scope $lvl]]:" {*}$argv]]
|
||||
error [join [list in \[ [proj-scope $lvl] \]: {*}$args]]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# @proj-fatal ?-up...? msg...
|
||||
#
|
||||
@@ -118,7 +119,7 @@ proc proj__faterr {failMode argv} {
|
||||
# additional level.
|
||||
#
|
||||
proc proj-fatal {args} {
|
||||
tailcall proj__faterr 1 $args
|
||||
tailcall proj__faterr 1 {*}$args
|
||||
}
|
||||
|
||||
#
|
||||
@@ -127,10 +128,9 @@ proc proj-fatal {args} {
|
||||
# Works like proj-fatal but uses [error] intead of [exit].
|
||||
#
|
||||
proc proj-error {args} {
|
||||
tailcall proj__faterr 0 $args
|
||||
tailcall proj__faterr 0 {*}$args
|
||||
}
|
||||
|
||||
set ::proj__Config(verbose-assert) [get-env proj-assert-verbose 0]
|
||||
#
|
||||
# @proj-assert script ?message?
|
||||
#
|
||||
@@ -147,7 +147,7 @@ proc proj-assert {script {msg ""}} {
|
||||
if {"" eq $msg} {
|
||||
set msg $script
|
||||
}
|
||||
proj-fatal "Assertion failed in \[[proj-scope 1]\]: $msg"
|
||||
tailcall proj__faterr 1 "Assertion failed:" $msg
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,7 +885,9 @@ proc proj-looks-like-windows {{key host}} {
|
||||
#
|
||||
proc proj-looks-like-mac {{key host}} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*apple* {
|
||||
*-*-darwin {
|
||||
# https://sqlite.org/forum/forumpost/7b218c3c9f207646
|
||||
# There's at least one Linux out there which matches *apple*.
|
||||
return 1
|
||||
}
|
||||
default {
|
||||
@@ -927,17 +929,13 @@ proc proj-exe-extension {} {
|
||||
#
|
||||
proc proj-dll-extension {} {
|
||||
set inner {{key} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*apple* {
|
||||
return ".dylib"
|
||||
}
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
return ".dll"
|
||||
}
|
||||
default {
|
||||
return ".so"
|
||||
}
|
||||
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]
|
||||
@@ -1665,7 +1663,7 @@ proc proj-dot-ins-append {fileIn args} {
|
||||
proj-fatal "Too many arguments: $fileIn $args"
|
||||
}
|
||||
}
|
||||
#puts "******* [proj-scope]: adding $fileIn"
|
||||
#puts "******* [proj-scope]: adding [llength $fileIn]-length item: $fileIn"
|
||||
lappend ::proj__Config(dot-in-files) $fileIn
|
||||
}
|
||||
|
||||
@@ -1703,17 +1701,18 @@ proc proj-dot-ins-list {} {
|
||||
# makes proj-dot-ins-append available for re-use.
|
||||
#
|
||||
proc proj-dot-ins-process {args} {
|
||||
proj-parse-simple-flags args flags {
|
||||
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"
|
||||
"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
|
||||
@@ -1753,7 +1752,7 @@ proc proj-validate-no-unresolved-ats {args} {
|
||||
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]} {
|
||||
if {[regexp {(@[A-Za-z0-9_\.]+@)} $line match]} {
|
||||
error "Unresolved reference to $match at line $lnno of $f"
|
||||
}
|
||||
}
|
||||
@@ -1893,7 +1892,7 @@ proc proj-define-amend {args} {
|
||||
#
|
||||
proc proj-define-to-cflag {args} {
|
||||
set rv {}
|
||||
proj-parse-simple-flags args flags {
|
||||
proj-parse-flags args flags {
|
||||
-list 0 {expr 1}
|
||||
-quote 0 {expr 1}
|
||||
-zero-undef 0 {expr 1}
|
||||
@@ -2001,7 +2000,7 @@ proc proj-cache-key {arg {addLevel 0}} {
|
||||
# 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-simple-flags args flags {
|
||||
proj-parse-flags args flags {
|
||||
-key => 0
|
||||
-level => 0
|
||||
}
|
||||
@@ -2037,7 +2036,7 @@ proc proj-cache-remove {{key 0} {addLevel 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-simple-flags args flags {
|
||||
proj-parse-flags args flags {
|
||||
-key => 0
|
||||
-level => 0
|
||||
}
|
||||
@@ -2070,147 +2069,316 @@ proc proj-coalesce {args} {
|
||||
}
|
||||
|
||||
#
|
||||
# @proj-parse-simple-flags ...
|
||||
# @proj-parse-flags argvListName targetArrayName {prototype}
|
||||
#
|
||||
# A helper to parse flags from proc argument lists.
|
||||
#
|
||||
# Expects a list of arguments to parse, an array name to store any
|
||||
# -flag values to, and a prototype object which declares the flags.
|
||||
# The first argument is the name of a var holding the args to
|
||||
# parse. It will be overwritten, possibly with a smaller list.
|
||||
#
|
||||
# The prototype must be a list in one of the following forms:
|
||||
# The second argument is the name of an array variable to create in
|
||||
# the caller's scope.
|
||||
#
|
||||
# -flag defaultValue {script}
|
||||
# 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
|
||||
# -----^--^ (with spaces there!)
|
||||
# -flag defaultValue ?-literal|-call|-apply?
|
||||
# script|number|incr|proc-name|{apply $aLambda}
|
||||
#
|
||||
# Repeated for each flag.
|
||||
# -flag* ...as above...
|
||||
#
|
||||
# The first form represents a basic flag with no associated
|
||||
# following argument. The second form extracts its value
|
||||
# from the following argument in $argvName.
|
||||
# -flag => defaultValue ?-call proc-name-and-args|-apply lambdaExpr?
|
||||
#
|
||||
# The first argument to this function is the name of a var holding the
|
||||
# args to parse. It will be overwritten, possibly with a smaller list.
|
||||
# -flag* => ...as above...
|
||||
#
|
||||
# The second argument the name of an array variable to create in the
|
||||
# caller's scope. (Pneumonic: => points to the next argument.)
|
||||
# :PRAGMA
|
||||
#
|
||||
# For the first form of flag, $script is run in the caller's scope if
|
||||
# $argv contains -flag, and the result of that script is the new value
|
||||
# for $tgtArrayName(-flag). This function intercepts [return $val]
|
||||
# from $script. Any empty script will result in the flag having ""
|
||||
# assigned to it.
|
||||
# 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.
|
||||
#
|
||||
# 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).
|
||||
# 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. If "--" is the first non-flag argument, the "--" flag is
|
||||
# removed from the results but all remaining arguments are passed
|
||||
# through. If "--" appears after the first non-flag, it is retained.
|
||||
# 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.
|
||||
#
|
||||
# This function assumes that each flag is unique, and using a flag
|
||||
# more than once behaves in a last-one-wins fashion.
|
||||
# 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.
|
||||
#
|
||||
# Any argvName entries not described in $prototype are not treated as
|
||||
# flags.
|
||||
#
|
||||
# Returns the number of flags it processed in $argvName.
|
||||
# Returns the number of flags it processed in $argvName, not counting
|
||||
# "--".
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# set args [list -foo -bar {blah} 8 9 10 -theEnd]
|
||||
# proj-parse-simple-flags args flags {
|
||||
# -foo 0 {expr 1}
|
||||
# -bar => 0
|
||||
# -no-baz 2 {return 0}
|
||||
# }
|
||||
## 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 2}
|
||||
# After that $flags would contain {-foo 1 -bar {blah} -no-baz 1 -z 2}
|
||||
# and $args would be {8 9 10 -theEnd}.
|
||||
#
|
||||
# Potential TODOs: consider using lappend instead of set so that any
|
||||
# given flag can be used more than once. Or add a syntax to indicate
|
||||
# that multiples are allowed. Also consider searching the whole
|
||||
# argv list, rather than stopping at the first non-flag
|
||||
# Pragmas:
|
||||
#
|
||||
proc proj-parse-simple-flags {argvName tgtArrayName prototype} {
|
||||
# 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 tgt
|
||||
array set dflt {}
|
||||
array set scripts {}
|
||||
array set consuming {}
|
||||
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]
|
||||
# Figure out what our flags are...
|
||||
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"
|
||||
proj-assert {[string match -* $k]} \
|
||||
"Invalid flag value: $k"
|
||||
set v ""
|
||||
set s ""
|
||||
switch -exact -- [lindex $prototype [expr {$i + 1}]] {
|
||||
=> {
|
||||
incr i 2
|
||||
if {$i >= $n} {
|
||||
proj-error "Missing argument for $k => flag"
|
||||
}
|
||||
set consuming($k) 1
|
||||
set v [lindex $prototype $i]
|
||||
}
|
||||
default {
|
||||
set v [lindex $prototype [incr i]]
|
||||
set s [lindex $prototype [incr i]]
|
||||
set scripts($k) $s
|
||||
|
||||
# Check for :PRAGMA...
|
||||
switch -exact -- $k {
|
||||
:all-flags {
|
||||
set incrSkip 0
|
||||
continue
|
||||
}
|
||||
}
|
||||
#puts "**** #$i of $n k=$k v=$v s=$s"
|
||||
set dflt($k) $v
|
||||
|
||||
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
|
||||
}
|
||||
# Now look for those flags in the source list
|
||||
array set tgt [array get dflt]
|
||||
unset dflt
|
||||
#puts "-- flags"; parray flags
|
||||
#puts "-- blob"; parray blob
|
||||
set rc 0
|
||||
set rv {}
|
||||
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} {
|
||||
incr skipMode
|
||||
} elseif {[info exists tgt($arg)]} {
|
||||
if {[info exists consuming($arg)]} {
|
||||
if {$i + 1 >= $n} {
|
||||
proj-assert 0 {Cannot happen - bounds already checked}
|
||||
# "--" 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 tgt($arg) [lindex $argv [incr i]]
|
||||
} elseif {"" eq $scripts($arg)} {
|
||||
set tgt($arg) ""
|
||||
set vv [lindex $argv $i]
|
||||
} elseif {[info exists blob(${arg}.script)]} {
|
||||
set vMode 1
|
||||
set vv $blob(${arg}.script)
|
||||
} else {
|
||||
#puts "**** running scripts($arg) $scripts($arg)"
|
||||
set code [catch {uplevel 1 $scripts($arg)} xrc xopt]
|
||||
#puts "**** tgt($arg)=$scripts($arg) code=$code rc=$rc"
|
||||
if {$code in {0 2}} {
|
||||
set tgt($arg) $xrc
|
||||
} else {
|
||||
return {*}$xopt $xrc
|
||||
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 {
|
||||
incr skipMode
|
||||
# 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]}
|
||||
@@ -2233,4 +2401,100 @@ if {$::proj__Config(self-tests)} {
|
||||
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
|
||||
|
||||
@@ -616,7 +616,7 @@ proc sqlite-check-common-system-deps {} {
|
||||
|
||||
# Check for needed/wanted functions
|
||||
cc-check-functions gmtime_r isnan localtime_r localtime_s \
|
||||
malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64
|
||||
strchrnul usleep utime pread pread64 pwrite pwrite64
|
||||
|
||||
apply {{} {
|
||||
set ldrt ""
|
||||
|
||||
+79
-56
@@ -92,6 +92,7 @@ array set teaish__Config [proj-strip-hash-comments {
|
||||
-tm.tcl.in TEAISH_TM_TCL_IN
|
||||
-options {}
|
||||
-pragmas {}
|
||||
-src {}
|
||||
}
|
||||
|
||||
#
|
||||
@@ -331,29 +332,33 @@ proc teaish-configure-core {} {
|
||||
-url - -v ""
|
||||
-tm.tcl - -v ""
|
||||
-tm.tcl.in - -v ""
|
||||
-src - -v ""
|
||||
} {
|
||||
#proj-assert 0 {Just testing}
|
||||
set isPIFlag [expr {"-" ne $pflag}]
|
||||
if {$isPIFlag} {
|
||||
if {[info exists ::teaish__PkgInfo($pflag)]} {
|
||||
# Was already set - skip it.
|
||||
continue;
|
||||
}
|
||||
proj-assert {{-} eq $key}
|
||||
proj-assert {{-} eq $key};# "Unexpected pflag=$pflag key=$key type=$type val=$val"
|
||||
set key $f2d($pflag)
|
||||
}
|
||||
proj-assert {"" ne $key}
|
||||
set got [get-define $key "<nope>"]
|
||||
if {"<nope>" ne $got} {
|
||||
# Was already set - skip it.
|
||||
continue
|
||||
if {"" ne $key} {
|
||||
if {"<nope>" ne [get-define $key "<nope>"]} {
|
||||
# Was already set - skip it.
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch -exact -- $type {
|
||||
-v {}
|
||||
-e { set val [eval $val] }
|
||||
default { proj-error "Invalid type flag: $type" }
|
||||
}
|
||||
#puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag got=$got"
|
||||
define $key $val
|
||||
#puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag"
|
||||
if {$key ne ""} {
|
||||
define $key $val
|
||||
}
|
||||
if {$isPIFlag} {
|
||||
set ::teaish__PkgInfo($pflag) $val
|
||||
}
|
||||
@@ -522,7 +527,7 @@ proc teaish__configure_phase1 {} {
|
||||
set vputs "puts \[ $vsat \]"
|
||||
#puts "*** vputs = $vputs"
|
||||
scan [exec echo $vputs | $tclsh] %d vvcheck
|
||||
if {0 == $vvcheck} {
|
||||
if {![info exists vvcheck] || 0 == $vvcheck} {
|
||||
proj-fatal -up $tclsh "check failed:" $vsat
|
||||
}
|
||||
}
|
||||
@@ -585,7 +590,8 @@ proc teaish__configure_phase1 {} {
|
||||
#
|
||||
if {0x0f & $::teaish__Config(pkginit-policy)} {
|
||||
file delete -force -- [get-define TEAISH_PKGINIT_TCL]
|
||||
proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN]
|
||||
proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN] \
|
||||
[get-define TEAISH_PKGINIT_TCL]
|
||||
}
|
||||
if {0x0f & $::teaish__Config(tm-policy)} {
|
||||
file delete -force -- [get-define TEAISH_TM_TCL]
|
||||
@@ -595,17 +601,20 @@ proc teaish__configure_phase1 {} {
|
||||
apply {{} {
|
||||
# Queue up any remaining dot-in files
|
||||
set dotIns [list]
|
||||
foreach d {
|
||||
TEAISH_TESTER_TCL_IN
|
||||
TEAISH_TEST_TCL_IN
|
||||
TEAISH_MAKEFILE_IN
|
||||
foreach {dIn => dOut} {
|
||||
TEAISH_TESTER_TCL_IN => TEAISH_TESTER_TCL
|
||||
TEAISH_TEST_TCL_IN => TEAISH_TEST_TCL
|
||||
TEAISH_MAKEFILE_IN => TEAISH_MAKEFILE
|
||||
} {
|
||||
lappend dotIns [get-define $d ""]
|
||||
lappend dotIns [get-define $dIn ""] [get-define $dOut ""]
|
||||
}
|
||||
lappend dotIns $::autosetup(srcdir)/Makefile.in; # must be after TEAISH_MAKEFILE_IN
|
||||
foreach f $dotIns {
|
||||
if {"" ne $f} {
|
||||
proj-dot-ins-append $f
|
||||
lappend dotIns $::autosetup(srcdir)/Makefile.in Makefile; # must be after TEAISH_MAKEFILE_IN.
|
||||
# Much later: probably because of timestamps for deps purposes :-?
|
||||
#puts "dotIns=$dotIns"
|
||||
foreach {i o} $dotIns {
|
||||
if {"" ne $i && "" ne $o} {
|
||||
#puts " pre-dot-ins-append: \[$i\] -> \[$o\]"
|
||||
proj-dot-ins-append $i $o
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -640,10 +649,10 @@ proc teaish__configure_phase1 {} {
|
||||
#
|
||||
# NO [define]s after this point!
|
||||
#
|
||||
proj-dot-ins-process -validate
|
||||
proj-if-opt-truthy teaish-dump-defines {
|
||||
proj-file-write config.defines.txt $tdefs
|
||||
}
|
||||
proj-dot-ins-process -validate
|
||||
|
||||
}; # teaish__configure_phase1
|
||||
|
||||
@@ -817,7 +826,9 @@ proc teaish__check_tcl {} {
|
||||
if {"" ne $withSh &&
|
||||
[catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} {
|
||||
foreach i $result {
|
||||
if {[file isdirectory $i]} {
|
||||
if {![string match //zip* $i] && [file isdirectory $i]} {
|
||||
# isdirectory actually passes on //zipfs:/..., but those are
|
||||
# useless for our purposes
|
||||
set tcllibdir $i/$extDirName
|
||||
break
|
||||
}
|
||||
@@ -1066,7 +1077,7 @@ If you are attempting an out-of-tree build, use
|
||||
]]} {
|
||||
if {[string match *.in $extM]} {
|
||||
define TEAISH_MAKEFILE_IN $extM
|
||||
define TEAISH_MAKEFILE [file rootname [file tail $extM]]
|
||||
define TEAISH_MAKEFILE _[file rootname [file tail $extM]]
|
||||
} else {
|
||||
define TEAISH_MAKEFILE_IN ""
|
||||
define TEAISH_MAKEFILE $extM
|
||||
@@ -1134,8 +1145,8 @@ If you are attempting an out-of-tree build, use
|
||||
set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl]
|
||||
if {[proj-first-file-found ttt $flist]} {
|
||||
if {[string match *.in $ttt]} {
|
||||
# Generate teaish.test.tcl from $ttt
|
||||
set xt [file rootname [file tail $ttt]]
|
||||
# Generate _teaish.test.tcl from $ttt
|
||||
set xt _[file rootname [file tail $ttt]]
|
||||
file delete -force -- $xt; # ensure no stale copy is used
|
||||
define TEAISH_TEST_TCL $xt
|
||||
define TEAISH_TEST_TCL_IN $ttt
|
||||
@@ -1302,7 +1313,6 @@ proc teaish-ldflags-prepend {args} {
|
||||
# object files (which are typically in the build tree)).
|
||||
#
|
||||
proc teaish-src-add {args} {
|
||||
set i 0
|
||||
proj-parse-simple-flags args flags {
|
||||
-dist 0 {expr 1}
|
||||
-dir 0 {expr 1}
|
||||
@@ -1387,7 +1397,7 @@ proc teaish__cleanup_rule {{tgt clean}} {
|
||||
return ${tgt}-_${x}_
|
||||
}
|
||||
|
||||
# @teaish-make-obj objfile srcfile ?...args?
|
||||
# @teaish-make-obj ?flags? ?...args?
|
||||
#
|
||||
# Uses teaish-make-add to inject makefile rules for $objfile from
|
||||
# $srcfile, which is assumed to be C code which uses libtcl. Unless
|
||||
@@ -1401,43 +1411,45 @@ proc teaish__cleanup_rule {{tgt clean}} {
|
||||
# Any arguments after the 2nd may be flags described below or, if no
|
||||
# -recipe is provided, flags for the compiler call.
|
||||
#
|
||||
# -obj obj-filename.o
|
||||
#
|
||||
# -src src-filename.c
|
||||
#
|
||||
# -recipe {...}
|
||||
# Uses the trimmed value of {...} as the recipe, prefixing it with
|
||||
# a single hard-tab character.
|
||||
#
|
||||
# -deps {...}
|
||||
# List of extra files to list as dependencies of $o. Good luck
|
||||
# escaping non-trivial cases properly.
|
||||
# List of extra files to list as dependencies of $o.
|
||||
#
|
||||
# -clean
|
||||
# Generate cleanup rules as well.
|
||||
proc teaish-make-obj {o src args} {
|
||||
set consume 0
|
||||
set clean 0
|
||||
set flag ""
|
||||
array set flags {}
|
||||
set xargs {}
|
||||
foreach arg $args {
|
||||
if {$consume} {
|
||||
set consume 0
|
||||
set flags($flag) $arg
|
||||
continue
|
||||
}
|
||||
switch -exact -- $arg {
|
||||
-clean {incr clean}
|
||||
-recipe -
|
||||
-deps {
|
||||
set flag $arg
|
||||
incr consume
|
||||
}
|
||||
default {
|
||||
lappend xargs $arg
|
||||
}
|
||||
proc teaish-make-obj {args} {
|
||||
proj-parse-simple-flags args flags {
|
||||
-clean 0 {expr 1}
|
||||
-recipe => {}
|
||||
-deps => {}
|
||||
-obj => {}
|
||||
-src => {}
|
||||
}
|
||||
#parray flags
|
||||
if {"" eq $flags(-obj)} {
|
||||
set args [lassign $args flags(-obj)]
|
||||
if {"" eq $flags(-obj)} {
|
||||
proj-error "Missing -obj flag."
|
||||
}
|
||||
}
|
||||
foreach f {-deps -src} {
|
||||
set flags($f) [string trim [string map {\n " "} $flags($f)]]
|
||||
}
|
||||
foreach f {-deps -src} {
|
||||
set flags($f) [string trim $flags($f)]
|
||||
}
|
||||
#parray flags
|
||||
#puts "-- args=$args"
|
||||
teaish-make-add \
|
||||
"# [proj-scope 1] -> [proj-scope] $o $src" -nl \
|
||||
"$o: $src $::teaish__Config(teaish.tcl)"
|
||||
"# [proj-scope 1] -> [proj-scope] $flags(-obj) $flags(-src)" -nl \
|
||||
"$flags(-obj): $flags(-src) $::teaish__Config(teaish.tcl)"
|
||||
if {[info exists flags(-deps)]} {
|
||||
teaish-make-add " " [join $flags(-deps)]
|
||||
}
|
||||
@@ -1445,12 +1457,12 @@ proc teaish-make-obj {o src args} {
|
||||
if {[info exists flags(-recipe)]} {
|
||||
teaish-make-add [string trim $flags(-recipe)] -nl
|
||||
} else {
|
||||
teaish-make-add [join [list \$(CC.tcl) -c $src {*}$xargs]] -nl
|
||||
teaish-make-add [join [list \$(CC.tcl) -c $flags(-src) {*}$args]] -nl
|
||||
}
|
||||
if {$clean} {
|
||||
if {$flags(-clean)} {
|
||||
set rule [teaish__cleanup_rule]
|
||||
teaish-make-add \
|
||||
"clean: $rule\n$rule:\n\trm -f \"$o\"\n"
|
||||
"clean: $rule\n$rule:\n\trm -f \"$flags(-obj)\"\n"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2078,6 +2090,17 @@ proc teaish-pkginfo-set {args} {
|
||||
set v $x
|
||||
}
|
||||
|
||||
-src {
|
||||
set d $::teaish__Config(extension-dir)
|
||||
foreach f $v {
|
||||
lappend ::teaish__Config(dist-files) $f
|
||||
lappend ::teaish__Config(extension-src) $d/$f
|
||||
lappend ::teaish__PkgInfo(-src) $f
|
||||
# ^^^ so that default-value initialization in
|
||||
# teaish-configure-core recognizes that it's been set.
|
||||
}
|
||||
}
|
||||
|
||||
-tm.tcl -
|
||||
-tm.tcl.in {
|
||||
if {0x30 & $::teaish__Config(pkgindex-policy)} {
|
||||
@@ -2515,7 +2538,7 @@ proc teaish__install {{dDest ""}} {
|
||||
] {
|
||||
teaish__verbose 1 msg-result "Copying files to $destDir..."
|
||||
file mkdir $destDir
|
||||
foreach f [glob -directory $srcDir *] {
|
||||
foreach f [glob -nocomplain -directory $srcDir *] {
|
||||
if {[string match {*~} $f] || [string match "#*#" [file tail $f]]} {
|
||||
# Editor-generated backups and emacs lock files
|
||||
continue
|
||||
|
||||
@@ -99,7 +99,7 @@ proc test__affert {failMode args} {
|
||||
lassign $args script msg
|
||||
}
|
||||
incr ::test__Counters($what)
|
||||
if {![uplevel 1 [concat expr [list $script]]]} {
|
||||
if {![uplevel 1 expr [list $script]]} {
|
||||
if {"" eq $msg} {
|
||||
set msg $script
|
||||
}
|
||||
@@ -136,6 +136,40 @@ proc assert {args} {
|
||||
tailcall test__affert 1 {*}$args
|
||||
}
|
||||
|
||||
#
|
||||
# @assert-matches ?-e? pattern ?-e? rhs ?msg?
|
||||
#
|
||||
# Equivalent to assert {[string match $pattern $rhs]} except that
|
||||
# if either of those are prefixed with an -e flag, they are eval'd
|
||||
# and their results are used.
|
||||
#
|
||||
proc assert-matches {args} {
|
||||
set evalLhs 0
|
||||
set evalRhs 0
|
||||
if {"-e" eq [lindex $args 0]} {
|
||||
incr evalLhs
|
||||
set args [lassign $args -]
|
||||
}
|
||||
set args [lassign $args pattern]
|
||||
if {"-e" eq [lindex $args 0]} {
|
||||
incr evalRhs
|
||||
set args [lassign $args -]
|
||||
}
|
||||
set args [lassign $args rhs msg]
|
||||
|
||||
if {$evalLhs} {
|
||||
set pattern [uplevel 1 $pattern]
|
||||
}
|
||||
if {$evalRhs} {
|
||||
set rhs [uplevel 1 $rhs]
|
||||
}
|
||||
#puts "***pattern=$pattern\n***rhs=$rhs"
|
||||
tailcall test__affert 1 \
|
||||
[join [list \[ string match [list $pattern] [list $rhs] \]]] $msg
|
||||
# why does this not work? [list \[ string match [list $pattern] [list $rhs] \]] $msg
|
||||
# "\[string match [list $pattern] [list $rhs]\]"
|
||||
}
|
||||
|
||||
#
|
||||
# @test-assert testId script ?msg?
|
||||
#
|
||||
@@ -157,7 +191,7 @@ proc test-expect {testId script result} {
|
||||
puts "test $testId"
|
||||
set x [string trim [uplevel 1 $script]]
|
||||
set result [string trim $result]
|
||||
tailcall test__affert 0 [list $x eq $result] \
|
||||
tailcall test__affert 0 [list "{$x}" eq "{$result}"] \
|
||||
"\nEXPECTED: <<$result>>\nGOT: <<$x>>"
|
||||
}
|
||||
|
||||
@@ -169,7 +203,7 @@ proc test-expect {testId script result} {
|
||||
#
|
||||
proc test-catch {cmd args} {
|
||||
if {[catch {
|
||||
$cmd {*}$args
|
||||
uplevel 1 $cmd {*}$args
|
||||
} rc xopts]} {
|
||||
puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc"
|
||||
return 1
|
||||
@@ -177,6 +211,37 @@ proc test-catch {cmd args} {
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# @test-catch-matching pattern (script|cmd args...)
|
||||
#
|
||||
# Works like test-catch, but it expects its argument(s) to to throw an
|
||||
# error matching the given string (checked with [string match]). If
|
||||
# they do not throw, or the error does not match $pattern, this
|
||||
# function throws, else it returns 1.
|
||||
#
|
||||
# If there is no second argument, the $cmd is assumed to be a script,
|
||||
# and will be eval'd in the caller's scope.
|
||||
#
|
||||
# TODO: add -glob and -regex flags to control matching flavor.
|
||||
#
|
||||
proc test-catch-matching {pattern cmd args} {
|
||||
if {[catch {
|
||||
#puts "**** catch-matching cmd=$cmd args=$args"
|
||||
if {0 == [llength $args]} {
|
||||
uplevel 1 $cmd {*}$args
|
||||
} else {
|
||||
$cmd {*}$args
|
||||
}
|
||||
} rc xopts]} {
|
||||
if {[string match $pattern $rc]} {
|
||||
return 1
|
||||
} else {
|
||||
error "[test-current-scope] exception does not match {$pattern}: {$rc}"
|
||||
}
|
||||
}
|
||||
error "[test-current-scope] expecting to see an error matching {$pattern}"
|
||||
}
|
||||
|
||||
if {![array exists ::teaish__BuildFlags]} {
|
||||
array set ::teaish__BuildFlags {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -213,7 +213,7 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
|
||||
@@ -79,7 +80,7 @@ typedef sqlite3_uint64 u64;
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
|
||||
+18
-5
@@ -539,6 +539,7 @@ static int fts5StorageDeleteFromIndex(
|
||||
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;
|
||||
@@ -555,11 +556,22 @@ static int fts5StorageDeleteFromIndex(
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pSeek ){
|
||||
pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
|
||||
if( 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,6 +587,7 @@ static int fts5StorageDeleteFromIndex(
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
sqlite3_value_free(pFree);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && p->nTotalRow<1 ){
|
||||
|
||||
@@ -325,5 +325,25 @@ ifcapable foreignkey {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
|
||||
@@ -28,4 +28,34 @@ 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
|
||||
|
||||
@@ -120,7 +120,7 @@ public abstract class AggregateFunction<T> implements SQLFunction {
|
||||
argument, the context is set to the given initial value. On all other
|
||||
calls, the 2nd argument is ignored.
|
||||
|
||||
@see SQLFunction.PerContextState#getAggregateState
|
||||
@see AggregateFunction.PerContextState#getAggregateState
|
||||
*/
|
||||
protected final ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
|
||||
return map.getAggregateState(cx, initialValue);
|
||||
@@ -130,7 +130,7 @@ public abstract class AggregateFunction<T> implements SQLFunction {
|
||||
To be called from the implementation's xFinal() method to fetch
|
||||
the final state of the UDF and remove its mapping.
|
||||
|
||||
see SQLFunction.PerContextState#takeAggregateState
|
||||
see AggregateFunction.PerContextState#takeAggregateState
|
||||
*/
|
||||
protected final T takeAggregateState(sqlite3_context cx){
|
||||
return map.takeAggregateState(cx);
|
||||
|
||||
+100
-47
@@ -67,6 +67,7 @@
|
||||
** 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.
|
||||
@@ -92,13 +93,11 @@ SQLITE_EXTENSION_INIT1
|
||||
# include <dirent.h>
|
||||
# include <utime.h>
|
||||
# include <sys/time.h>
|
||||
# define STRUCT_STAT struct stat
|
||||
#else
|
||||
# include "windows.h"
|
||||
# include <io.h>
|
||||
# include "windirent.h"
|
||||
# include <direct.h>
|
||||
# include "test_windirent.h"
|
||||
# define dirent DIRENT
|
||||
# define stat _stat
|
||||
# define STRUCT_STAT struct _stat
|
||||
# define chmod(path,mode) fileio_chmod(path,mode)
|
||||
# define mkdir(path,mode) fileio_mkdir(path)
|
||||
#endif
|
||||
@@ -116,14 +115,16 @@ SQLITE_EXTENSION_INIT1
|
||||
/*
|
||||
** Structure of the fsdir() table-valued function
|
||||
*/
|
||||
/* 0 1 2 3 4 5 */
|
||||
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
|
||||
/* 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_PATH 4 /* Path to top of search */
|
||||
#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
|
||||
#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
|
||||
@@ -289,7 +290,7 @@ LPWSTR utf8_to_utf16(const char *z){
|
||||
*/
|
||||
static void statTimesToUtc(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
STRUCT_STAT *pStatBuf
|
||||
){
|
||||
HANDLE hFindFile;
|
||||
WIN32_FIND_DATAW fd;
|
||||
@@ -317,7 +318,7 @@ static void statTimesToUtc(
|
||||
*/
|
||||
static int fileStat(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
STRUCT_STAT *pStatBuf
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
sqlite3_int64 sz = strlen(zPath);
|
||||
@@ -341,7 +342,7 @@ static int fileStat(
|
||||
*/
|
||||
static int fileLinkStat(
|
||||
const char *zPath,
|
||||
struct stat *pStatBuf
|
||||
STRUCT_STAT *pStatBuf
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
return fileStat(zPath, pStatBuf);
|
||||
@@ -374,7 +375,7 @@ static int makeDirectory(
|
||||
int i = 1;
|
||||
|
||||
while( rc==SQLITE_OK ){
|
||||
struct stat sStat;
|
||||
STRUCT_STAT sStat;
|
||||
int rc2;
|
||||
|
||||
for(; zCopy[i]!='/' && i<nCopy; i++);
|
||||
@@ -424,7 +425,7 @@ static int writeFile(
|
||||
** 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;
|
||||
STRUCT_STAT sStat;
|
||||
if( errno!=EEXIST
|
||||
|| 0!=fileStat(zFile, &sStat)
|
||||
|| !S_ISDIR(sStat.st_mode)
|
||||
@@ -620,13 +621,14 @@ 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 */
|
||||
STRUCT_STAT sStat; /* Current lstat() results */
|
||||
char *zPath; /* Path to current entry */
|
||||
sqlite3_int64 iRowid; /* Current rowid */
|
||||
};
|
||||
@@ -738,7 +740,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
|
||||
mode_t m = pCur->sStat.st_mode;
|
||||
|
||||
pCur->iRowid++;
|
||||
if( S_ISDIR(m) ){
|
||||
if( S_ISDIR(m) && pCur->iLvl+3<pCur->mxLvl ){
|
||||
/* Descend into this directory */
|
||||
int iNew = pCur->iLvl + 1;
|
||||
FsdirLevel *pLvl;
|
||||
@@ -846,7 +848,11 @@ static int fsdirColumn(
|
||||
}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.
|
||||
@@ -880,8 +886,11 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
|
||||
/*
|
||||
** xFilter callback.
|
||||
**
|
||||
** idxNum==1 PATH parameter only
|
||||
** idxNum==2 Both PATH and DIR supplied
|
||||
** idxNum bit Meaning
|
||||
** 0x01 PATH=N
|
||||
** 0x02 DIR=N
|
||||
** 0x04 LEVEL<N
|
||||
** 0x08 LEVEL<=N
|
||||
*/
|
||||
static int fsdirFilter(
|
||||
sqlite3_vtab_cursor *cur,
|
||||
@@ -892,20 +901,31 @@ static int fsdirFilter(
|
||||
fsdir_cursor *pCur = (fsdir_cursor*)cur;
|
||||
(void)idxStr;
|
||||
fsdirResetCursor(pCur);
|
||||
int i;
|
||||
|
||||
if( idxNum==0 ){
|
||||
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
assert( argc==idxNum && (argc==1 || argc==2) );
|
||||
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;
|
||||
}
|
||||
if( argc==2 ){
|
||||
pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
|
||||
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;
|
||||
@@ -934,10 +954,11 @@ static int fsdirFilter(
|
||||
** In this implementation idxNum is used to represent the
|
||||
** query plan. idxStr is unused.
|
||||
**
|
||||
** The query plan is represented by values of idxNum:
|
||||
** The query plan is represented by bits in idxNum:
|
||||
**
|
||||
** (1) The path value is supplied by argv[0]
|
||||
** (2) Path is in argv[0] and dir is in argv[1]
|
||||
** 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,
|
||||
@@ -946,6 +967,9 @@ static int fsdirBestIndex(
|
||||
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;
|
||||
@@ -953,25 +977,48 @@ static int fsdirBestIndex(
|
||||
(void)tab;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
||||
switch( pConstraint->iColumn ){
|
||||
case FSDIR_COLUMN_PATH: {
|
||||
if( pConstraint->usable ){
|
||||
idxPath = i;
|
||||
seenPath = 0;
|
||||
}else if( idxPath<0 ){
|
||||
seenPath = 1;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSDIR_COLUMN_DIR: {
|
||||
if( pConstraint->usable ){
|
||||
idxDir = i;
|
||||
seenDir = 0;
|
||||
}else if( idxDir<0 ){
|
||||
seenDir = 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -988,14 +1035,20 @@ static int fsdirBestIndex(
|
||||
}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 = 2;
|
||||
pIdxInfo->idxNum = 2;
|
||||
pIdxInfo->estimatedCost = 10.0;
|
||||
}else{
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->estimatedCost = 100.0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -240,7 +240,7 @@ static int vtablogConnect(
|
||||
|
||||
|
||||
/*
|
||||
** This method is the destructor for vtablog_cursor objects.
|
||||
** This method is the destructor for vtablog_vtab objects.
|
||||
*/
|
||||
static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
@@ -252,7 +252,7 @@ static int vtablogDisconnect(sqlite3_vtab *pVtab){
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for vtablog_cursor objects.
|
||||
** This method is (also) the destructor for vtablog_vtab objects.
|
||||
*/
|
||||
static int vtablogDestroy(sqlite3_vtab *pVtab){
|
||||
vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
|
||||
|
||||
@@ -0,0 +1,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) */
|
||||
+4
-2
@@ -64,6 +64,8 @@
|
||||
#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
|
||||
@@ -95,7 +97,7 @@ typedef unsigned int u32;
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#ifndef offsetof
|
||||
#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
@@ -2848,7 +2850,7 @@ static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Insert cell pCell into node pNode. Node pNode is the head of a
|
||||
** subtree iHeight high (leaf nodes have iHeight==0).
|
||||
|
||||
@@ -96,6 +96,22 @@ do_test 1.5 {
|
||||
$iter finalize
|
||||
grp delete
|
||||
|
||||
do_test 1.6 {
|
||||
set C [changeset_from_sql {
|
||||
INSERT INTO t1 VALUES(1001, hex(randomblob(10000)), hex(randomblob(10000)));
|
||||
INSERT INTO t1 VALUES(2001, hex(randomblob(10000)), hex(randomblob(10000)));
|
||||
INSERT INTO t1 VALUES(3001, hex(randomblob(10000)), hex(randomblob(10000)));
|
||||
}]
|
||||
|
||||
sqlite3changegroup grp
|
||||
set iter [sqlite3changeset_start $C]
|
||||
while {[$iter next]=="SQLITE_ROW"} {
|
||||
grp add_change $iter
|
||||
}
|
||||
$iter finalize
|
||||
} SQLITE_OK
|
||||
|
||||
grp delete
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -3396,14 +3396,15 @@ int sqlite3changeset_start_v2_strm(
|
||||
** object and the buffer is full, discard some data to free up space.
|
||||
*/
|
||||
static void sessionDiscardData(SessionInput *pIn){
|
||||
if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
|
||||
int nMove = pIn->buf.nBuf - pIn->iNext;
|
||||
if( pIn->xInput && pIn->iCurrent>=sessions_strm_chunk_size ){
|
||||
int nMove = pIn->buf.nBuf - pIn->iCurrent;
|
||||
assert( nMove>=0 );
|
||||
if( nMove>0 ){
|
||||
memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove);
|
||||
memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iCurrent], nMove);
|
||||
}
|
||||
pIn->buf.nBuf -= pIn->iNext;
|
||||
pIn->iNext = 0;
|
||||
pIn->buf.nBuf -= pIn->iCurrent;
|
||||
pIn->iNext -= pIn->iCurrent;
|
||||
pIn->iCurrent = 0;
|
||||
pIn->nData = pIn->buf.nBuf;
|
||||
}
|
||||
}
|
||||
@@ -3757,8 +3758,8 @@ static int sessionChangesetNextOne(
|
||||
p->rc = sessionInputBuffer(&p->in, 2);
|
||||
if( p->rc!=SQLITE_OK ) return p->rc;
|
||||
|
||||
sessionDiscardData(&p->in);
|
||||
p->in.iCurrent = p->in.iNext;
|
||||
sessionDiscardData(&p->in);
|
||||
|
||||
/* If the iterator is already at the end of the changeset, return DONE. */
|
||||
if( p->in.iNext>=p->in.nData ){
|
||||
@@ -6117,14 +6118,19 @@ int sqlite3changegroup_add_change(
|
||||
sqlite3_changegroup *pGrp,
|
||||
sqlite3_changeset_iter *pIter
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( pIter->in.iCurrent==pIter->in.iNext
|
||||
|| pIter->rc!=SQLITE_OK
|
||||
|| pIter->bInvert
|
||||
){
|
||||
/* Iterator does not point to any valid entry or is an INVERT iterator. */
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pIter->in.bNoDiscard = 1;
|
||||
rc = sessionOneChangeToHash(pGrp, pIter, 0);
|
||||
}
|
||||
return sessionOneChangeToHash(pGrp, pIter, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1459,6 +1459,9 @@ struct TestChangegroup {
|
||||
typedef struct TestChangeIter TestChangeIter;
|
||||
struct TestChangeIter {
|
||||
sqlite3_changeset_iter *pIter;
|
||||
|
||||
/* If this iter uses streaming. */
|
||||
TestStreamInput in;
|
||||
};
|
||||
|
||||
|
||||
@@ -1681,6 +1684,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_start(
|
||||
sqlite3_changeset_iter *pIter = 0;
|
||||
int flags = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int nAlloc = 0; /* Bytes of space to allocate */
|
||||
|
||||
static int iCmd = 1;
|
||||
char zCmd[64];
|
||||
@@ -1696,18 +1700,36 @@ static int SQLITE_TCLAPI test_sqlite3changeset_start(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
flags = isInvert ? SQLITE_CHANGESETSTART_INVERT : 0;
|
||||
pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[objc-1], &nChangeset);
|
||||
rc = sqlite3changeset_start_v2(&pIter, (int)nChangeset, pChangeset, flags);
|
||||
flags = isInvert ? SQLITE_CHANGESETSTART_INVERT : 0;
|
||||
|
||||
nAlloc = sizeof(TestChangeIter);
|
||||
if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
|
||||
nAlloc += nChangeset;
|
||||
}
|
||||
pNew = (TestChangeIter*)ckalloc(nAlloc);
|
||||
memset(pNew, 0, nAlloc);
|
||||
if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
|
||||
pNew->in.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
|
||||
pNew->in.nData = nChangeset;
|
||||
pNew->in.aData = (unsigned char*)&pNew[1];
|
||||
memcpy(pNew->in.aData, pChangeset, nChangeset);
|
||||
}
|
||||
|
||||
if( pNew->in.nStream ){
|
||||
void *pCtx = (void*)&pNew->in;
|
||||
rc = sqlite3changeset_start_v2_strm(&pIter, testStreamInput, pCtx, flags);
|
||||
}else{
|
||||
rc = sqlite3changeset_start_v2(&pIter, (int)nChangeset, pChangeset, flags);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
char *zErr = sqlite3_mprintf(
|
||||
"error in sqlite3changeset_start_v2() - %d", rc
|
||||
);
|
||||
Tcl_AppendResult(interp, zErr, (char*)0);
|
||||
ckfree(pNew);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
pNew = (TestChangeIter*)ckalloc(sizeof(TestChangeIter));
|
||||
pNew->pIter = pIter;
|
||||
|
||||
sprintf(zCmd, "csiter%d", iCmd++);
|
||||
|
||||
@@ -410,7 +410,7 @@ DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
# -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)
|
||||
$(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 \
|
||||
@@ -597,6 +597,7 @@ emcc.flags += -v
|
||||
# -v is _very_ loud but also informative about what it's doing
|
||||
endif
|
||||
|
||||
|
||||
########################################################################
|
||||
# emcc flags for .c/.o.
|
||||
emcc.cflags :=
|
||||
@@ -615,8 +616,9 @@ emcc.jsflags += -sDYNAMIC_EXECUTION=0
|
||||
emcc.jsflags += -sNO_POLYFILL
|
||||
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
|
||||
emcc.exportedRuntimeMethods := \
|
||||
-sEXPORTED_RUNTIME_METHODS=wasmMemory
|
||||
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
|
||||
-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
|
||||
|
||||
@@ -1157,7 +1157,7 @@ const char * sqlite3__wasm_enum_json(void){
|
||||
{ /* 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;
|
||||
const sqlite3_index_info siiCheck = {0};
|
||||
#define IndexSzCheck(T,M) \
|
||||
(sizeof(T) == sizeof(*siiCheck.M))
|
||||
if(!IndexSzCheck(sqlite3_index_constraint,aConstraint)
|
||||
|
||||
@@ -328,7 +328,7 @@ static void mk_lib_mode(const char *zName /* build name */,
|
||||
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 ){
|
||||
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
|
||||
|
||||
@@ -772,7 +772,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vdbecov.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_window.c \
|
||||
$(TOP)/src/test_wsd.c \
|
||||
$(TOP)/ext/fts3/fts3_term.c \
|
||||
@@ -996,6 +995,7 @@ FUZZCHECK_OPT += \
|
||||
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
|
||||
-DSQLITE_ENABLE_STAT4 \
|
||||
-DSQLITE_ENABLE_STMT_SCANSTATUS \
|
||||
-DSQLITE_JSON_MAX_DEPTH=500 \
|
||||
-DSQLITE_MAX_MEMORY=50000000 \
|
||||
-DSQLITE_MAX_MMAP_SIZE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
@@ -1834,6 +1834,12 @@ mdevtest: srctree-check has_tclsh85
|
||||
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.
|
||||
@@ -2323,12 +2329,12 @@ SHELL_DEP = \
|
||||
$(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 \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_windirent.h
|
||||
$(TOP)/ext/recover/sqlite3recover.h
|
||||
|
||||
|
||||
shell.c: $(SHELL_DEP) $(TOP)/tool/mkshellc.tcl $(B.tclsh)
|
||||
$(B.tclsh) $(TOP)/tool/mkshellc.tcl shell.c
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
C Minor\stcl\sdoc\supdate.
|
||||
D 2025-05-17T10:35:11.233
|
||||
C proj.tcl\sportability\sfixes\sand\scleanups\ssuggested\sin\s[forum:7b218c3c9f|forum\spost\s7b218c3c9f].\sBranching\sso\sthat\sit\scan\sbe\stested\son\smsys/cygwin/haiku\sbefore\scommitting\sto\sit.
|
||||
D 2025-06-17T14:37:31.325
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
|
||||
F Makefile.in c3e414df4dc8dfb12f1f6baf129fcb6d18cd0ebd3c9109370fb3fceeeef9a37a
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 0206f28988bb6634c7e8aff05bf6cfa65d6dfe1d2b6bd95160dd99290a83dfc7
|
||||
F Makefile.msc ec2011bbdfc917d6a1c7c173dabb29c14ead0dd8e2e0b67278a00ae4ba576a77
|
||||
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
|
||||
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
|
||||
F VERSION 16eddb43056a79c1977427ab7a05f3457c373fa159dcdced8754eb89ce7e06b8
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -17,20 +17,19 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
|
||||
F auto.def 82c32443a91c1062f7a48beec37dbb2d8d03447b1286bce8df5ebb6d8d353f8a
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.in 36516827bb5d2309422bbcbf53e873fa22ef179f5c25b1d3dc6a7255e63270b7
|
||||
F autoconf/Makefile.in d0926d2309e563b5ebdfd711e5c218533acab79829a05eef4e97c3a92e17bf42
|
||||
F autoconf/Makefile.msc f15ad424ca2820df8e39d9157965710af0a64d87773706706a12ea4f96e3a0d8
|
||||
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
|
||||
F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
|
||||
F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
|
||||
F autoconf/tea/Makefile.in 14c6a79ce87e10d8a35398f2d0e04e1d83a88eb52ee16ebf0eeaccf005ff84b3
|
||||
F autoconf/tea/README.txt 656d4686c509d375f5988ff3deda94f65fe6cd8358cd55d1f1dcc7b6e2ff73aa
|
||||
F autoconf/tea/_teaish.tester.tcl.in ed5445512e91c12afbbb99771efb68a23be4a046d52d61213fb5b6f010118129
|
||||
F autoconf/tea/Makefile.in bf6b43eafcd18766d81a8f0085cfc9cb051d8abae9031a8e7c3f5f1246e8f166
|
||||
F autoconf/tea/README.txt 23475876343498ef2b514cc7510e8f1559a17e8e03fbc7a41c1c8a3b89e7b7e3
|
||||
F autoconf/tea/_teaish.tester.tcl.in 8253b44be88e2e3f21de95a65d3a90c2be8e70b7bdd08a5b80e337ba7402f8f1
|
||||
F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079db417529
|
||||
F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
|
||||
F autoconf/tea/doc/sqlite3.n 9a97f4f717ceab73004ea412af7960625c1cb24b5c25e4ae4c8b5d8fa4300f4e
|
||||
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
|
||||
F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
|
||||
F autoconf/tea/teaish.tcl 81571a9f9ae5c70735595b05586cb2de9d2aea7e32aad10417c4982f2e2f01c8
|
||||
F autoconf/tea/teaish.tcl a2224762a039ed30c45cc1ce4b2fde5667fb0aa2569bb56590f5cb5d45d7410b
|
||||
F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
|
||||
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
|
||||
F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e
|
||||
@@ -47,13 +46,13 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e
|
||||
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
|
||||
F autosetup/jimsh0.c 563b966c137a4ce3c9333e5196723b7ac0919140a9d7989eb440463cd855c367
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl c4a77735b57f3c016a185bff048212a197b77723f9bea6cfafe396e4b542c666
|
||||
F autosetup/sqlite-config.tcl 7ff986f6c3951f3aec5608522cbf772d8d04a0d26cc894289e2ca4836e018719
|
||||
F autosetup/proj.tcl d2428ea25745d25a090b938647737818accd5b802511776a186c9f1bcce53420
|
||||
F autosetup/sqlite-config.tcl ccda82e43e377b832aae72a1678b1dc17dcaff36ed0ebbd8f0cfc88612ae8de3
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
|
||||
F autosetup/teaish/core.tcl 1ebbe849d8e716424a3ffe9384c7e8b352b3e1194d3d4a153b125cc5176b3715
|
||||
F autosetup/teaish/core.tcl aee092fc71986d1272b835ea7492bb55ffc213a289502e4f14da80cf67b7e3c3
|
||||
F autosetup/teaish/feature.tcl 18194fb79a24d30e5bbdeab40999616f39278b53a27525349ded033af2fd73be
|
||||
F autosetup/teaish/tester.tcl 091745984473faea6985254b9986c6dfd0cce06f68bc515ba4afc1e6b3742fa8
|
||||
F autosetup/teaish/tester.tcl 1799514c2652db49561b3386c5242b94534d1663f2cfac861a955e071895fdd0
|
||||
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
|
||||
F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
@@ -82,7 +81,7 @@ F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 4f02858ab845a97bedf06e6cc1fba49a81fe5e00a26df68d0ad0f00a5814fa70
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 53f00a0d037c81174af1089ad7776563dcbccb5ed4697405256d3d4260d9fccc
|
||||
F ext/fts3/fts3Int.h d0f70d602be987501cf6eff86a06a0b5d0389929c6abe24972d59594e6f4cb03
|
||||
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
|
||||
F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
|
||||
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
|
||||
@@ -108,7 +107,7 @@ F ext/fts3/unicode/mkunicode.tcl cbf5f7b5c8ce8014bad731f246f2e520eece908465de477
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
|
||||
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
|
||||
F ext/fts5/fts5Int.h bffbd0acdcdf509899681f4e1cfeef1c955030acd9fe15ff9082410f80c3bead
|
||||
F ext/fts5/fts5Int.h cc1e6ed28e1fbde71e4427ba6d15b0c73a4f8f119adeb4f7bcc97e3336fbbeac
|
||||
F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
|
||||
F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
|
||||
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
|
||||
@@ -116,7 +115,7 @@ F ext/fts5/fts5_expr.c be9e5f7f11d87e7bd3680832c93c13050fe351994b5052b0215c2ef40
|
||||
F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
|
||||
F ext/fts5/fts5_index.c d171f2a507abccb3d524bf461b01f0d3971a9bf221be622ac7c671a991cb62ee
|
||||
F ext/fts5/fts5_main.c 57933c18efe1058d8871199875c7a59744dabc3904f3aefbf9ff4a4e11fc79e2
|
||||
F ext/fts5/fts5_storage.c 1ad05dab4830a4e2eaf2900bb143477f93bc17437093582f36f4b818809e88d8
|
||||
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
|
||||
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
|
||||
@@ -193,7 +192,7 @@ F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e
|
||||
F ext/fts5/test/fts5faultF.test 4abef99f86e99d9f0c6460dd68c586a766b6b9f1f660ada55bf2e8266bd1bbc1
|
||||
F ext/fts5/test/fts5faultG.test 0544411ffcb3e19b42866f757a8a5e0fb8fef3a62c06f61d14deebc571bb7ea9
|
||||
F ext/fts5/test/fts5faultH.test 2b2b5b8cb1b3fd7679f488c06e22af44107fbc6137eaf45b3e771dc7b149312d
|
||||
F ext/fts5/test/fts5faultI.test 9b33d664bccee4bbde0f275a48b2df3ea2f05d41f6d1d171aa2e844382cba621
|
||||
F ext/fts5/test/fts5faultI.test 4e3d5a9d3e3b3f17d5e5087ee069414632667719dcfccafd715bc87c72838c72
|
||||
F ext/fts5/test/fts5first.test bfd685b96905bf541d99d8644e0a7219d1d833455a08ab64e344071a613b6ba9
|
||||
F ext/fts5/test/fts5full.test 97d263c1072f4a560929cca31e70f65d2ae232610e17e6affcf7e979df59547b
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
@@ -261,7 +260,7 @@ F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d059264
|
||||
F ext/fts5/test/fts5unicode.test 41898f7e476e6515cd4b737c02a442cda5a580a74509788aa9072a2074948e0e
|
||||
F ext/fts5/test/fts5unicode2.test 3bbd30152f9f760bf13886e5b1e5ec23ff62f56758ddda5d9c775a6082fb4c7c
|
||||
F ext/fts5/test/fts5unicode3.test f4891a3dac3b49c3d7c0fdb29566e9eb0ecff35263370c89f9661b1952b20818
|
||||
F ext/fts5/test/fts5unicode4.test 728c8f0caafb05567f524ad313d9f8b780fa45987b8a8df04eff87923c74b4d0
|
||||
F ext/fts5/test/fts5unicode4.test 6d70dbe56e5179bb1990cfb22e62fdf2aae9458e443ade856e598ce95832fe9b
|
||||
F ext/fts5/test/fts5unindexed.test 168838d2c385e131120bbf5b516d2432a5fabc4caa2259c932e1d49ae209a4ae
|
||||
F ext/fts5/test/fts5unindexed2.test 516236eceaac05ace322290a0d3705b4c4ffe4760d8eb9d014d9d27d56dfcc02
|
||||
F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
|
||||
@@ -296,7 +295,7 @@ F ext/jni/src/org/sqlite/jni/annotation/NotNull.java be6cc3e8e114485822331630097
|
||||
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 56e3dee1f3f703a545dfdeddc1c3d64d1581172b1ad01ffcae95c18547fafd90
|
||||
F ext/jni/src/org/sqlite/jni/annotation/package-info.java 977b374aed9d5853cbf3438ba3b0940abfa2ea4574f702a2448ee143b98ac3ca
|
||||
F ext/jni/src/org/sqlite/jni/capi/AbstractCollationCallback.java 1afa90d3f236f79cc7fcd2497e111992644f7596fbc8e8bcf7f1908ae00acd6c
|
||||
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63418129656daa9a9f30e7e7be982bd5ab394b1dbd0
|
||||
F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0e28a0df51368c7127e505f1e9acd92a7e66e035bcd6288463aa691cb300c9af
|
||||
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
|
||||
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
|
||||
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
|
||||
@@ -418,7 +417,7 @@ F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f82
|
||||
F ext/misc/decimal.c 228d47e9ef4de60daf5851da19e3ac9ac1eda9e94432816914469501db6a1129
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
|
||||
F ext/misc/fileio.c 34993b810514c58ff99d7b4254d4a388d844a4774ea77bec68a1dafe8de5ce41
|
||||
F ext/misc/fileio.c 5e1aff478ea12455a76be25dff321e1e9517b189fffb1d547a019625c49c1880
|
||||
F ext/misc/fossildelta.c 0aeb099e9627eea693cf21ae47826ecd1e0319b93143bed23090838b2ef0c162
|
||||
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
|
||||
F ext/misc/ieee754.c c9dd9d77c8e8e18e0a5706f8ffcccf4ccb6562073709f7453d4d73f5122f4362
|
||||
@@ -457,9 +456,10 @@ F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505
|
||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||
F ext/misc/vfsstat.c 0b23c0a69a2b63dc0ef0af44f9c1fc977300c480a1f7a9814500369d8211f56e
|
||||
F ext/misc/vfstrace.c 0e4b8b17ac0675ea90f6d168d8214687e06ca3efbc0060aad4814994d82b41fb
|
||||
F ext/misc/vtablog.c 1100250ce8782db37c833e3a9a5c9a3ecf1af5e15b8325572b82e6e0a138ffb5
|
||||
F ext/misc/vtablog.c a197addbbd1e267a5476274b74953e1b6f050e28516f0a5fe7d6382753165ee6
|
||||
F ext/misc/vtshim.c e5bce24ab8c532f4fdc600148718fe1802cb6ed57417f1c1032d8961f72b0e8f
|
||||
F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f65b4fc0668
|
||||
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
|
||||
F ext/misc/zipfile.c b62147ac4985eaac4e368d529b1f4f43ad6bc9ac13d6805d907fff3afdac64d3
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
@@ -539,7 +539,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
|
||||
F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
|
||||
F ext/rtree/rtree.c 99dade93b5ca1c1fa4a5ba1381140d88b27a52573a92897827d9eb2a8059a460
|
||||
F ext/rtree/rtree.c a1f04a2013bc8f982307760615d1cee591355ac4723c74c3761c128d5c6954ab
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
@@ -601,7 +601,7 @@ F ext/session/sessionalter.test e852acb3d2357aac7d0b920a2109da758c4331bfdf85b41d
|
||||
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194d64a39d8faff00a
|
||||
F ext/session/sessionchange.test 77c4702050f24270b58070e2cf01c95c3d232a3ef164b70f31974b386ce69903
|
||||
F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
|
||||
F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
|
||||
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
|
||||
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
|
||||
@@ -617,11 +617,11 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c 7a8816d56940c464c74706dfb02f18129b290655df1ccb8648228a7d436141f2
|
||||
F ext/session/sqlite3session.c 6b0877fe1ab832aa4b85eaca72606dfd1630a1363a1be7af10ee1042a5ec719e
|
||||
F ext/session/sqlite3session.h 9bb1a6687b467764b35178dc29bbd2c57ab8cd3acdc8a62f088c34ad17e4fe2b
|
||||
F ext/session/test_session.c af162108e8dc40cb9fe0e876e0155cecabcb49e82e5939677d21451e36160283
|
||||
F ext/session/test_session.c 2ddff73ea368d827028c32851b291416e1008845832feb27b751d15e57e13cc3
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile 24d7e6f446528fa67f5ade6c3c7d7e46e1ac52649d6264cbe24539c1dab608e1
|
||||
F ext/wasm/GNUmakefile e315b903c33b28ca074367041849de9dd2681c96d1437c11a5e9596abc265012
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -650,7 +650,7 @@ F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 0f68a64e508598910e7c01214ae27d603dfc8baec6a184506fafac603a901931
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
||||
F ext/wasm/api/sqlite3-wasm.c 6a4cd40267eaf08400895c5b9de39c56976c3b97b3c1bbe53fc2e80fa074e9c7
|
||||
F ext/wasm/api/sqlite3-wasm.c 7ea3d4a286a2241f6fcc65c9ff10fc04ee5590f80f40763a57001dd5e93aa4c4
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc65debfe43b81fc39fb25c40ad0cc1946bd82580fbf644351107b544d6177ee
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
@@ -682,7 +682,7 @@ F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf1
|
||||
F ext/wasm/index.html bcaa00eca521b372a6a62c7e7b17a870b0fcdf3e418a5921df1fd61e5344080d
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 6e4f26d0edb5c2e7d381b7eff1924832a040a12274afab2d1e1789027e9f6c5c
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 1128e3563e7eff90b5a373395251fc76cb32386fad1fea6075b0f34a8f1b9bdf
|
||||
F ext/wasm/mkwasmbuilds.c 6e0b22002bc520b7af053681571a96d30049a51f7f1389e81c524e8d420f5d40
|
||||
F ext/wasm/mkwasmbuilds.c 5b096a3c9fdf6e67eb20329dc685f995e820248a67fa970633c2c8f49bf472ad
|
||||
F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -709,7 +709,7 @@ F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk a41fa9e96ef139452d21a9ca5db4561ce053363e04d07da803f5e1cefb44c65e
|
||||
F main.mk 17744293e7af7c39936c3f220ebb8eaff4f0ad1be1e186efb584dbc34bbea2c1
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -719,37 +719,37 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
|
||||
F src/alter.c 6a21a487290ed0990a0fac9db6b0b09c63de4b1cdaa6ba3fa3872e6f26b87768
|
||||
F src/alter.c fc7bbbeb9e89c7124bf5772ce474b333b7bdc18d6e080763211a40fde69fb1da
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
|
||||
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 782cc29b42b47e7ec6348eb0aaf9ffe60063f498387e7249f458d445af4b53e9
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c 00fcee37947641f48d4b529d96143e74d056b7afa8f26d61292c90ee59c056b2
|
||||
F src/btree.c 53a9c7b243e94c992853d90f1dac0959028433b4b0d27e04409cee04e001b508
|
||||
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
|
||||
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
|
||||
F src/dbpage.c fcb1aafe00872a8aff9a7aa0ef7ff1b01e5817ec7bbd521f8f3e1e674ac8d609
|
||||
F src/dbpage.c b3e218f8ed74fcbb7fa805df8ca669a3718d397617b3d8a8aac3307dc315c4d6
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
|
||||
F src/expr.c 6f184da1f36576ad1ecc48a03f14774235373c64f88d462c710834930ee6c145
|
||||
F src/expr.c f16fa5cbd849991462edf1d31bb7def5b970bb9611afcb4ea21c77e88e52a220
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
|
||||
F src/func.c 7686ea382b20e8bfe2ab9de76150c99ee7b6e83523561f3c7787e0f68cb435c2
|
||||
F src/func.c de47a8295503aa130baae5e6d9868ecf4f7c4dbffa65d83ad1f70bdbac0ee2d6
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c d05934dfab2c5c0c480fc6fd2038f11215661de08ea6ff38d2563216bd555c1b
|
||||
F src/json.c 2406a6b0dd849ee0fd107d5cfef9fec2cdc2fbe631ece3183c31d6f85e0ec988
|
||||
F src/json.c cb87977b1ee25ee7d27505d65a9261b687395bf895342c8ba566b7c01aee2047
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 07f78d917ffcdf327982840cfd8e855fd000527a2ea5ace372ce4febcbd0bf97
|
||||
F src/loadext.c d7edd8e671237539d795d30daaf888908a2c82e99bade4c78f3be021e8b7d655
|
||||
F src/main.c eb46066bf2f0bec2dd89229572de5a9c479c47da134e2422e7a0056e9510cbee
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -770,10 +770,10 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 410185df4900817c218c0efdb8064b3481af88cb3f7cea7392f820b6eebc7889
|
||||
F src/os_win.c caab8bc13f1d64a2ba6b8af35d660ffe25083df3493d9082d7a461a5e9950a50
|
||||
F src/os_unix.c 04e054ab86d86a7be99ebe5265922687791a40df5afc781d059beb47f4a40acd
|
||||
F src/os_win.c b8d3cfdf2f40e2f9715b7d8df64f3c0c7ee18743a2dd0c4fc70c1d57fa1aadc7
|
||||
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
|
||||
F src/pager.c 9fbb541b46125dfa8914827575e6bb4d15048caa008073b1709112d495d7983b
|
||||
F src/pager.c 23c0f17deb892da6b32fef1f465507df7ab5cd01d774288cb43695658a649259
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y e426d7323311554c75b0aebc426d0fe3c88d9777ffefed236f343ad9e661dc4c
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
@@ -781,22 +781,22 @@ F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c 30b535d0a66348df844ee36f890617b4cf45e9a22dcbc47ec3ca92909c50aaf1
|
||||
F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
|
||||
F src/printf.c 3b91c334f528359145f4dde0dedd945bbb21044d0825ea064934d7222d61662c
|
||||
F src/printf.c 71b6d3a0093bf23f473e25480ca0024e8962681506c75f4ffd3d343a3f0ab113
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ee072fe20566119a195a5a3df454479bb6e944de7aef7006ff0b4d4612f9cb86
|
||||
F src/shell.c.in ba53a52dafb167ac6320703da741386c34fbcabe8c078a188bb9f89808e3ef8f
|
||||
F src/select.c 882d739e0d5e6c7a8b46a3cca3ada37fe1a56301f1360d6b141312c666bbe482
|
||||
F src/shell.c.in 4ae9ff8e8b23d9a309e50d5b5ef2768b9bb18f748ece2acc2641a3c23b71e2b9
|
||||
F src/sqlite.h.in 22882ddd3a70751aa8864c81993ee4562ed54c2c508b6270f75e223ffee38e1b
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h ded2e1527c84603d9d91adccb63dda460d96a2e2f98111d0438a479aa0dbe4e3
|
||||
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
|
||||
F src/sqliteInt.h 493202a7dec31d58ac246252b7f03645160e3709102255a79136b4aa8f863e74
|
||||
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
|
||||
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 767a11d470b031e85f51b8924a0e8929b2362ff1975aee3474a10eba3c2e0d36
|
||||
F src/tclsqlite.c 3c604c49e6cf4211960a9ddb9505280fd22cde32175f40884c641c0f5a286036
|
||||
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
|
||||
F src/test1.c 9b54135e5f1352f06b1d23d7c183f124c1f33de6ea8997cd801f0f215c43591d
|
||||
F src/test1.c 13cc07851f989141b29f7ca3c6c90f6d18f90081ab423c66716c8cb29d277d1f
|
||||
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
|
||||
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
|
||||
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
|
||||
@@ -813,7 +813,7 @@ F src/test_config.c 7f412406592794636d6226268e26d413850a9f799bc5f3c01afc2820b165
|
||||
F src/test_delete.c d0e8f6dc55cfc98a7c27c057fb88d512260564bf0b611482656c68b8f7f401ed
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
F src/test_fs.c 6711fd4c6c05914b613cfc99918a24978452f999ce03fc8f89c9794c03b20a5b
|
||||
F src/test_fs.c a946408c81231feff4b6a2c18068f20aefe254dc82288687128af8b7520d32cb
|
||||
F src/test_func.c 858d4dddb7acf88222ebcba7cffb585f6dde83e4a15b838c0d05ccdf8d5219b9
|
||||
F src/test_hexio.c a90baa0a8ab5e7cfe2216a61c9a31cfd1f8378353a3d23e25fa94c09aa755bb0
|
||||
F src/test_init.c 1649e02448f536e53172f6b1ff873254fe9a0c6c8a4502a2d25c0cc7b11945ea
|
||||
@@ -841,8 +841,6 @@ F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e04
|
||||
F src/test_thread.c 3edb4a5b5aeb1a6e9a275dccc848ac95acab7f496b3e9230f6d2d04953a2b862
|
||||
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
|
||||
F src/test_vfs.c b4135c1308516adf0dfd494e6d6c33114e03732be899eace0502919b674586b5
|
||||
F src/test_windirent.c cbee2b9a118b56b5a26b99c895adcbc861587bc66d24b88d1ad6e4c1d09dad7b
|
||||
F src/test_windirent.h f8245d8002aa0d4322192d35b0f8bbfc757479e90d60fd0beb386d3913f72cdd
|
||||
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
@@ -851,28 +849,28 @@ F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc6227
|
||||
F src/trigger.c 3ffb8ed6b64dbcc0ccae6e82435d01be3bf547e13b814e2d46f7df9bef84748e
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 3a20cbae9688af4c1e3754cc2520189d00762e37f60c2deb0b303360d166bba6
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
|
||||
F src/vacuum.c d580ceb395c1ae3d59da41cbfea60683ff7dd2b94ddf4d0f5657620159e2eeb7
|
||||
F src/vdbe.c 0feab5781141acca67bd5de84172fff902304274ec5cfe58609f005b8d160050
|
||||
F src/vdbe.h 31eddcffc1d14c76c2a20fe4e137e1ee43d44f370896fae14a067052801a3625
|
||||
F src/vdbeInt.h 5446f60e89b2aa7cdf3ab0ec4e7b01b8732cd9d52d9092a0b8b1bf700768f784
|
||||
F src/vdbeapi.c 28fab30ed0acc981aecfdcaab0a421503609078e29850eb28494816682baf0a7
|
||||
F src/vdbeaux.c 948c379976885a073b54cc7d8ffda087dc1a1095d1f5bb8df218796f8c933ac3
|
||||
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
|
||||
F src/vdbe.c 714fab7aa7c516edbcf5e4f653ae8f548a3e24c0ed19086d7383bb5851983992
|
||||
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
|
||||
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
|
||||
F src/vdbeapi.c 613a6f29efacd6ed83e886b6e52db0fe52ba80a596b0a137608db1948bad90a9
|
||||
F src/vdbeaux.c fd2c6b19a8892c31a2adc719f156f313560f9cc490cdbd04ff08fdae5d7aedb7
|
||||
F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
|
||||
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
|
||||
F src/vdbesort.c 49e366d0216c782eba287bf602384e4330d2526a22f1275492d2785ce103c79b
|
||||
F src/vdbesort.c cb6f472e83ca12c46aa7de0ac0a9d11458b357986f2617a1c90dfb19a542ecbe
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c bcf40795a09b699ad7e42624dd6282b13335164fbabcd5a98a717758cebef451
|
||||
F src/wal.c b0f848cfba8dd057f77073493cdd542f9125b4cf87941f53e9d0db21604155c8
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 1d06561f7310af61bef8a046fa95d463ad88f855be9036fec9091f984520afc5
|
||||
F src/whereInt.h ecdbfb5551cf394f04ec7f0bc7ad963146d80eee3071405ac29aa84950128b8e
|
||||
F src/wherecode.c d67fadf5430c2647773b5f702a47b82eb4af50a317f8978c0c82363cc1a5107f
|
||||
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
|
||||
F src/where.c a99fa3061a0155d2cb0e2c91df76dbf834750272a8d79ec5e2dce3ed4e6abad6
|
||||
F src/whereInt.h 02b646ea41a8342815b3628f8064c32618ea2e0f20b83216ea08cad11f0ac5aa
|
||||
F src/wherecode.c 9710e62379c000189476404f923d4d1b192d0def222fdd287b820cc085a0d555
|
||||
F src/whereexpr.c cf86bb36c5c4560aa13f81853bc8a345da441a0cce5cccbb634a80ea517f6cc0
|
||||
F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
|
||||
@@ -1084,6 +1082,7 @@ F test/dbfuzz.c fc566102f72c8af84ae8077b4faf7f056c571e6fa7a32e98b66e42b7505f47b6
|
||||
F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8ba8e9c3
|
||||
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
|
||||
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
|
||||
F test/dblwidth-a.sql eb4141518610e52f931a55a984310075e98dc31eee5a28ae806b1e35377be85a
|
||||
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
|
||||
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
@@ -1222,7 +1221,7 @@ F test/fts3fault3.test ccdd2292dd2d4e21e30fc5f4c8e064f79e516087eec5ff57ab6bc4f6a
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3fuzz001.test c78afcd8ad712ea0b8d2ed50851a8aab3bc9dc52c64a536291e07112f519357c
|
||||
F test/fts3integrity.test 0c6fe7353d7b24d78862f4272ee9df4da2f32b3ff30fa3396945cda8119580a8
|
||||
F test/fts3join.test 1a4d786539b2b79a41c28ef2ac22cacd92a8ee830249b68a7dee4a020848e3bb
|
||||
F test/fts3join.test de31d304ba479043a7d33d2f201c514b3e1da809da6797d7a58704d00e8da2e6
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
|
||||
F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
|
||||
@@ -1274,7 +1273,7 @@ F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d8
|
||||
F test/func6.test 3bc89ec0f2605736d3a118f43d25ef58115a7db4dba8ae939a363917d815c0bb
|
||||
F test/func7.test 7e009275f52c52954c8c028fdb62f8bc16cc47276fcc8753c1d2b22c6e074598
|
||||
F test/func8.test c4e2ecacf9f16e47a245e7a25fbabcc7e78f9c7c41a80f158527cdfdc6dd299d
|
||||
F test/func9.test 62750dbbbcc9a2d241918b5f999f59e2126084d5f81904f9e1d8ee466666a19d
|
||||
F test/func9.test d56aa5b0f7d0e4fec01cb19b797671221dece2b00714bb71679588666be7530d
|
||||
F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0
|
||||
F test/fuzz.test 819ea7e483bcee91209aacbe6f9eaf3287baa1841479ee5f639f57c5e7c42b86
|
||||
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
@@ -1361,7 +1360,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d520
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
|
||||
F test/join.test 0cc86e5fd579780b98cc01c9d6fc5b69f6ecc777f1c4daa501a14d1a74f56a6b
|
||||
F test/join.test 2fcfd84640cfd9ff48f31b4b0d370c4d5498c355ae4384544668ca54d37ae186
|
||||
F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
@@ -1376,7 +1375,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
|
||||
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
|
||||
F test/joinH.test fd76024ff104baec16417db5cafc0894ad4e0863e70803e63c1bba0322706339
|
||||
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
|
||||
@@ -1388,7 +1387,7 @@ F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd286
|
||||
F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307
|
||||
F test/json/json-speed-check.sh 7d5898808ce7542762318306ae6075a30f5e7ee115c4a409f487e123afe91d88 x
|
||||
F test/json/jsonb-q1.txt 1e180fe6491efab307e318b22879e3a736ac9a96539bbde7911a13ee5b33abc7
|
||||
F test/json101.test 11024e20fe298f7214878947b8f85a2dbe593593e04b4173c14a5857afbb986c
|
||||
F test/json101.test 8237a484c256965eab1678fd950a32ac56325bb7d0dadbd095a46b0ddd95d62b
|
||||
F test/json102.test 9b2e5ada10845ff84853b3feaae2ce51ce7145ae458f74c6a6cecc6ef6ee3ae1
|
||||
F test/json103.test 355746a6b66aa438f214b4fae454b13068fad2444b5f693e0d538ad1c059b264
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
@@ -1664,7 +1663,7 @@ F test/skipscan5.test 0672103fd2c8f96bd114133f356192b35ece45c794fe3677e1d9e5e310
|
||||
F test/skipscan6.test e2b256cf5d538a605beb97dc97ca5e2836dfc24c5e1d9b7a09e13c069a3b8b49
|
||||
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
|
||||
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
|
||||
F test/snapshot3.test 41350216abc6c7da37113ad462259c070786e5ad70bdc8709daaed148b1b3a2c
|
||||
F test/snapshot3.test 2e0328ba019aa981848e10aded4d7dcd6094ec1f9c6290a34ab18415be0c44eb
|
||||
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
|
||||
F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a
|
||||
F test/snapshot_up.test 77dc7853bfb2b4fa249f76e1714cfa1e596826165d9ef22c06ac3a0b7b778d9a
|
||||
@@ -1686,7 +1685,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest.md ee958457ae1b729d9715ae33c0320600000bf1d9ddea1a88dcf79f56729d6fad
|
||||
F test/speedtest.tcl 926d1e168f4a14e6fb68c5dc174de743536b547f365264bd5bac533b3621a4a0 x
|
||||
F test/speedtest.tcl 405411356fbc54af15987b7ffeec330a49138f71584220fb8fe1948b2f7ac907 x
|
||||
F test/speedtest1.c 64b8804b053a796eab22f8b23fb181000f05d7b3e2aa44f022117ea543bc5a2a
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
@@ -1725,7 +1724,7 @@ F test/tabfunc01.test 8a484fe8b19fc24844f72ca1ceb7c9ae8c9a6bca000a5c6ccab5d89f5c
|
||||
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
|
||||
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
|
||||
F test/tclsqlite.test 3f697424cfc1cdc9c076ec0cadb0e700f059400a3e3ce134b7d856fc9f880e1c
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
@@ -1735,7 +1734,7 @@ F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 463ae33b8bf75ac77451df19bd65e7c415c2e9891227c7c9e657d0a2d8e1074a
|
||||
F test/testrunner.tcl 614c4a28f7f730acd7bec53e17d76602fb480e0d538b6ec548169e03a093f92d x
|
||||
F test/testrunner_data.tcl 8d5fa3851c48bc94e26db0be325202e44f6ca4ed838272b8d5b10c23817621e6
|
||||
F test/testrunner_data.tcl 02dd645b647d907c959fbf232b7ff7d869c2ae430d5117443fc1e16a0d32243a
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1959,7 +1958,7 @@ F test/uri.test 1250724af9beeed2d6c3716f5b990c483200c54f408d3c0ec9543a3c7961f8fc
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
|
||||
F test/vacuum-into.test 5a489714feecfdabfc7b293be4111564a173dee92c0d6818dd0207f3ade65783
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum.test f3b2257a4fcd659513c866a5d9e5f70999cc58fd5d74e979290385fa350b79ee
|
||||
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
|
||||
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
|
||||
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
|
||||
@@ -2034,8 +2033,10 @@ F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b
|
||||
F test/walsetlk.test 9079cd8ef82570b8cf0067f31e049a72bec353fb2d5f0cc88f1736dc42ba9704
|
||||
F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
|
||||
F test/walsetlk2.test 4a67823b1e759ac5a4fe78a83c1f857c3c5761bf8d755421c8b55907957f23dd
|
||||
F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
|
||||
F test/walsetlk_recover.test adccbffc59e365063a4efd2da6b661ae2fcf15d775b6719fe46acd87face08ff
|
||||
F test/walsetlk_snapshot.test 86d5588380f9927d8fcbbd75133b0a34fddf959378d6823c6f164a390123f70a
|
||||
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
|
||||
F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23
|
||||
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
|
||||
@@ -2143,7 +2144,7 @@ F tool/genfkey.README e550911fa984c8255ebed2ef97824125d83806eb5232582700de949edf
|
||||
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/lemon.c f51a488369046cd4f4212d755a214a57673ded400cbeb01e298cbf63539e1d8c
|
||||
F tool/lemon.c 8f6c122e5727cb0e5f302b8efc91489b1947a8d98206d7a1b1cfc0ed685b6e7c
|
||||
F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
@@ -2160,7 +2161,7 @@ F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61
|
||||
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 3801ce32f8c55fe63a3b279f231fb26c2c1a2ea9a09d2dd599239d87a609acec
|
||||
F tool/mkshellc.tcl 9ce74de0fa904a2c56a96f8d8b5261246bacb0eaa8d7e184f9e18ff94145ebbc
|
||||
F tool/mkshellc.tcl bab0a72a68384181a5706712dfdf6815f6526446d4e8aacace2de5e80cda91b2
|
||||
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
|
||||
F tool/mksqlite3c-noext.tcl 351c55256213154cabb051a3c870ef9f4487de905015141ae50dc7578a901b84
|
||||
F tool/mksqlite3c.tcl f11b63445c4840509248bd4aa151a81aea25d5415fef71943c8d436eba4f3b3c
|
||||
@@ -2186,13 +2187,13 @@ F tool/showwal.c 11eca547980a066b081f512636151233350ac679f29ecf4ebfce7f4530230b3
|
||||
F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdaddf
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 07e18a1d8cc3f6b3a4a1f3528e63c9b29a5c8a7bca0b8d394b231da464ce1247
|
||||
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
|
||||
F tool/sqldiff.c 134be7866be19f8beb32043d5aea5657f01aaeae2df8d33d758ff722c78666b9
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c e8659970e839d71d2ef04b96d48ad65f1d4298a41636affaf93c32ed71f3f879
|
||||
F tool/sqlite3_rsync.c c1e1a737ebb458a4ccbbaa21e5eaa878448fef1aaa71b879b9a685785e28987f
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05bbb4
|
||||
F tool/src-verify.c 6c655d9a8d6b30f3648fc78a79bf3838ed68f8543869d380c43ea9f17b3b8501
|
||||
F tool/srcck1.c 559e703c6cca1d70398bdba1d7f91036c1a71adf718a1aaa6401a562ccaed154
|
||||
F tool/srctree-check.tcl fa4d82dd3e8a38d5cbce7d6ade8abef2f42b9eca0394484d521dc8d086739460
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
@@ -2205,10 +2206,13 @@ F tool/vdbe-compress.tcl fa2f37ab39b2a0087fafb6a7f3ce19503e25e624ffa8ed9951717ab
|
||||
F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e
|
||||
F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
|
||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 15bd9e581a6d6ebe281b091adc04dca4d1c7fa9bbb582bcbab8c401b4f976753
|
||||
R 39ca8780111060790d2845d7852fde6d
|
||||
P 9441fff52cc4e19c44df1a77ffe474f409d519b270c7166ce17f99e6ea48fc1e
|
||||
R 521cd36fd533b38f39517faf822f8bdc
|
||||
T *branch * linux-named-apple
|
||||
T *sym-linux-named-apple *
|
||||
T -sym-trunk * Cancelled\sby\sbranch.
|
||||
U stephan
|
||||
Z f2bd0f683f4792863565410791d20518
|
||||
Z 5f5e8471bf9be6c3059712dd72eeed12
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
43259e8c3fab13b4597cdd1c670df00ec756a6fefdeb7d4ba2e0644e4ad47113
|
||||
89552e9137b7ebba9600443720e936e8dc4f7ab021d2ac3f0bb01b74071e130c
|
||||
|
||||
+2
-2
@@ -1223,10 +1223,10 @@ static int renameEditSql(
|
||||
}
|
||||
|
||||
assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
|
||||
zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1));
|
||||
zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1);
|
||||
}else{
|
||||
assert( nSql>0 );
|
||||
zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3);
|
||||
zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3);
|
||||
if( zOut ){
|
||||
zBuf1 = &zOut[nSql*2+1];
|
||||
zBuf2 = &zOut[nSql*4+2];
|
||||
|
||||
+99
-15
@@ -107,6 +107,7 @@ struct Bitvec {
|
||||
} 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
|
||||
@@ -216,7 +217,9 @@ bitvec_set_rehash:
|
||||
}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 - 1)/BITVEC_NPTR;
|
||||
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]);
|
||||
@@ -293,6 +296,52 @@ 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
|
||||
@@ -304,6 +353,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
#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.
|
||||
**
|
||||
@@ -312,7 +362,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
** by 0, 1, or 3 operands, depending on the opcode. Another
|
||||
** opcode follows immediately after the last operand.
|
||||
**
|
||||
** There are 6 opcodes numbered from 0 through 5. 0 is the
|
||||
** 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
|
||||
@@ -321,18 +371,25 @@ u32 sqlite3BitvecSize(Bitvec *p){
|
||||
** 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.
|
||||
** 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;
|
||||
@@ -343,10 +400,15 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
|
||||
/* Allocate the Bitvec to be tested and a linear array of
|
||||
** bits to act as the reference */
|
||||
pBitvec = sqlite3BitvecCreate( sz );
|
||||
pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
|
||||
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 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
|
||||
if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end;
|
||||
|
||||
/* NULL pBitvec tests */
|
||||
sqlite3BitvecSet(0, 1);
|
||||
@@ -355,6 +417,24 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
/* 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:
|
||||
@@ -376,12 +456,12 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
pc += nx;
|
||||
i = (i & 0x7fffffff)%sz;
|
||||
if( (op & 1)!=0 ){
|
||||
SETBIT(pV, (i+1));
|
||||
if( pV ) SETBIT(pV, (i+1));
|
||||
if( op!=5 ){
|
||||
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
|
||||
}
|
||||
}else{
|
||||
CLEARBIT(pV, (i+1));
|
||||
if( pV ) CLEARBIT(pV, (i+1));
|
||||
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
|
||||
}
|
||||
}
|
||||
@@ -391,14 +471,18 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
||||
** match (rc==0). Change rc to non-zero if a discrepancy
|
||||
** is found.
|
||||
*/
|
||||
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;
|
||||
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 */
|
||||
|
||||
+10
-1
@@ -872,7 +872,7 @@ static int btreeMoveto(
|
||||
assert( nKey==(i64)(int)nKey );
|
||||
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
|
||||
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
|
||||
sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
|
||||
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
@@ -2856,6 +2856,7 @@ static int removeFromSharingList(BtShared *pBt){
|
||||
sqlite3_mutex_leave(pMainMtx);
|
||||
return removed;
|
||||
#else
|
||||
UNUSED_PARAMETER( pBt );
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
@@ -3697,6 +3698,13 @@ static SQLITE_NOINLINE int btreeBeginTrans(
|
||||
(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);
|
||||
@@ -11317,6 +11325,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
|
||||
*/
|
||||
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);
|
||||
|
||||
+7
-6
@@ -227,7 +227,7 @@ static int dbpageEof(sqlite3_vtab_cursor *pCursor){
|
||||
** idxStr is not used
|
||||
*/
|
||||
static int dbpageFilter(
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
@@ -237,10 +237,11 @@ static int dbpageFilter(
|
||||
sqlite3 *db = pTab->db;
|
||||
Btree *pBt;
|
||||
|
||||
(void)idxStr;
|
||||
|
||||
UNUSED_PARAMETER(idxStr);
|
||||
UNUSED_PARAMETER(argc);
|
||||
|
||||
/* Default setting is no rows of result */
|
||||
pCsr->pgno = 1;
|
||||
pCsr->pgno = 1;
|
||||
pCsr->mxPgno = 0;
|
||||
|
||||
if( idxNum & 2 ){
|
||||
@@ -275,8 +276,8 @@ static int dbpageFilter(
|
||||
}
|
||||
|
||||
static int dbpageColumn(
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
sqlite3_context *ctx,
|
||||
sqlite3_vtab_cursor *pCursor,
|
||||
sqlite3_context *ctx,
|
||||
int i
|
||||
){
|
||||
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
|
||||
|
||||
+6
-2
@@ -73,7 +73,9 @@ char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
|
||||
);
|
||||
}
|
||||
if( op==TK_VECTOR ){
|
||||
if( op==TK_VECTOR
|
||||
|| (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER)
|
||||
){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
|
||||
}
|
||||
@@ -266,7 +268,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
p = p->pLeft;
|
||||
continue;
|
||||
}
|
||||
if( op==TK_VECTOR ){
|
||||
if( op==TK_VECTOR
|
||||
|| (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER)
|
||||
){
|
||||
assert( ExprUseXList(p) );
|
||||
p = p->x.pList->a[0].pExpr;
|
||||
continue;
|
||||
|
||||
+3
-3
@@ -1667,7 +1667,7 @@ static void concatFuncCore(
|
||||
int nSep,
|
||||
const char *zSep
|
||||
){
|
||||
i64 j, k, n = 0;
|
||||
i64 j, n = 0;
|
||||
int i;
|
||||
char *z;
|
||||
for(i=0; i<argc; i++){
|
||||
@@ -1681,8 +1681,8 @@ static void concatFuncCore(
|
||||
}
|
||||
j = 0;
|
||||
for(i=0; i<argc; i++){
|
||||
k = sqlite3_value_bytes(argv[i]);
|
||||
if( k>0 ){
|
||||
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 ){
|
||||
|
||||
+11
-7
@@ -1285,8 +1285,10 @@ static int jsonBlobChangePayloadSize(
|
||||
nExtra = 1;
|
||||
}else if( szType==13 ){
|
||||
nExtra = 2;
|
||||
}else{
|
||||
}else if( szType==14 ){
|
||||
nExtra = 4;
|
||||
}else{
|
||||
nExtra = 8;
|
||||
}
|
||||
if( szPayload<=11 ){
|
||||
nNeeded = 0;
|
||||
@@ -4850,18 +4852,20 @@ static void jsonObjectStep(
|
||||
UNUSED_PARAMETER(argc);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
z = (const char*)sqlite3_value_text(argv[0]);
|
||||
n = sqlite3Strlen30(z);
|
||||
if( pStr->zBuf==0 ){
|
||||
jsonStringInit(pStr, ctx);
|
||||
jsonAppendChar(pStr, '{');
|
||||
}else if( pStr->nUsed>1 ){
|
||||
}else if( pStr->nUsed>1 && z!=0 ){
|
||||
jsonAppendChar(pStr, ',');
|
||||
}
|
||||
pStr->pCtx = ctx;
|
||||
z = (const char*)sqlite3_value_text(argv[0]);
|
||||
n = sqlite3Strlen30(z);
|
||||
jsonAppendString(pStr, z, n);
|
||||
jsonAppendChar(pStr, ':');
|
||||
jsonAppendSqlValue(pStr, argv[1]);
|
||||
if( z!=0 ){
|
||||
jsonAppendString(pStr, z, n);
|
||||
jsonAppendChar(pStr, ':');
|
||||
jsonAppendSqlValue(pStr, argv[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
||||
|
||||
+3
-1
@@ -517,7 +517,9 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_stmt_explain,
|
||||
/* Version 3.44.0 and later */
|
||||
sqlite3_get_clientdata,
|
||||
sqlite3_set_clientdata
|
||||
sqlite3_set_clientdata,
|
||||
/* Version 3.50.0 and later */
|
||||
sqlite3_setlk_timeout
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
@@ -1861,6 +1861,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
|
||||
#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);
|
||||
@@ -1872,6 +1873,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
|
||||
}
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
#endif
|
||||
#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
|
||||
UNUSED_PARAMETER(db);
|
||||
|
||||
+5
-6
@@ -5035,21 +5035,20 @@ static int unixShmLock(
|
||||
/* Check that, if this to be a blocking lock, no locks that occur later
|
||||
** in the following list than the lock being obtained are already held:
|
||||
**
|
||||
** 1. Checkpointer lock (ofst==1).
|
||||
** 2. Write lock (ofst==0).
|
||||
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
|
||||
** 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.
|
||||
**
|
||||
** It is not permitted to block on the RECOVER lock.
|
||||
*/
|
||||
#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) /* not RECOVER */
|
||||
(ofst!=2 || lockMask==0)
|
||||
&& (ofst!=1 || lockMask==0 || lockMask==2)
|
||||
&& (ofst!=0 || lockMask<3)
|
||||
&& (ofst<3 || lockMask<(1<<ofst))
|
||||
|
||||
+12
-113
@@ -2722,7 +2722,11 @@ static int winHandleLockTimeout(
|
||||
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;
|
||||
@@ -4208,13 +4212,13 @@ static void *winConvertFromUtf8Filename(const char *zFilename){
|
||||
|
||||
if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
|
||||
&& winIsDirSep(zFilename[2])) ){
|
||||
int nByte;
|
||||
i64 nByte;
|
||||
int convertflag = CCP_POSIX_TO_WIN_W;
|
||||
if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
|
||||
nByte = (int)osCygwin_conv_path(convertflag,
|
||||
nByte = (i64)osCygwin_conv_path(convertflag,
|
||||
zFilename, 0, 0);
|
||||
if( nByte>0 ){
|
||||
zConverted = sqlite3MallocZero(nByte+12);
|
||||
zConverted = sqlite3MallocZero(12+(u64)nByte);
|
||||
if ( zConverted==0 ){
|
||||
return zConverted;
|
||||
}
|
||||
@@ -4533,21 +4537,20 @@ static int winShmLock(
|
||||
/* Check that, if this to be a blocking lock, no locks that occur later
|
||||
** in the following list than the lock being obtained are already held:
|
||||
**
|
||||
** 1. Checkpointer lock (ofst==1).
|
||||
** 2. Write lock (ofst==0).
|
||||
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
|
||||
** 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.
|
||||
**
|
||||
** It is not permitted to block on the RECOVER lock.
|
||||
*/
|
||||
#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) /* not RECOVER */
|
||||
(ofst!=2 || lockMask==0)
|
||||
&& (ofst!=1 || lockMask==0 || lockMask==2)
|
||||
&& (ofst!=0 || lockMask<3)
|
||||
&& (ofst<3 || lockMask<(1<<ofst))
|
||||
@@ -5097,27 +5100,6 @@ static winVfsAppData winNolockAppData = {
|
||||
** sqlite3_vfs object.
|
||||
*/
|
||||
|
||||
#if 0 /* No longer necessary */
|
||||
/*
|
||||
** Convert a filename from whatever the underlying operating system
|
||||
** supports for filenames into UTF-8. Space to hold the result is
|
||||
** obtained from malloc and must be freed by the calling function.
|
||||
*/
|
||||
static char *winConvertToUtf8Filename(const void *zFilename){
|
||||
char *zConverted = 0;
|
||||
if( osIsNT() ){
|
||||
zConverted = winUnicodeToUtf8(zFilename);
|
||||
}
|
||||
#ifdef SQLITE_WIN32_HAS_ANSI
|
||||
else{
|
||||
zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
|
||||
}
|
||||
#endif
|
||||
/* caller will handle out of memory */
|
||||
return zConverted;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function returns non-zero if the specified UTF-8 string buffer
|
||||
** ends with a directory separator character or one was successfully
|
||||
@@ -5257,42 +5239,6 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
|
||||
break;
|
||||
}
|
||||
sqlite3_free(zConverted);
|
||||
#if 0 /* No longer necessary */
|
||||
}else{
|
||||
zConverted = sqlite3MallocZero( nMax+1 );
|
||||
if( !zConverted ){
|
||||
sqlite3_free(zBuf);
|
||||
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
||||
return SQLITE_IOERR_NOMEM_BKPT;
|
||||
}
|
||||
if( osCygwin_conv_path(
|
||||
CCP_POSIX_TO_WIN_W, zDir,
|
||||
zConverted, nMax+1)<0 ){
|
||||
sqlite3_free(zConverted);
|
||||
sqlite3_free(zBuf);
|
||||
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
|
||||
return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
|
||||
"winGetTempname2", zDir);
|
||||
}
|
||||
if( winIsDir(zConverted) ){
|
||||
/* At this point, we know the candidate directory exists and should
|
||||
** be used. However, we may need to convert the string containing
|
||||
** its name into UTF-8 (i.e. if it is UTF-16 right now).
|
||||
*/
|
||||
char *zUtf8 = winConvertToUtf8Filename(zConverted);
|
||||
if( !zUtf8 ){
|
||||
sqlite3_free(zConverted);
|
||||
sqlite3_free(zBuf);
|
||||
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
||||
return SQLITE_IOERR_NOMEM_BKPT;
|
||||
}
|
||||
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
|
||||
sqlite3_free(zUtf8);
|
||||
sqlite3_free(zConverted);
|
||||
break;
|
||||
}
|
||||
sqlite3_free(zConverted);
|
||||
#endif /* No longer necessary */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6191,34 +6137,6 @@ static int winFullPathnameNoMutex(
|
||||
}
|
||||
}
|
||||
#endif /* __CYGWIN__ */
|
||||
#if 0 /* This doesn't work correctly at all! See:
|
||||
<https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
|
||||
*/
|
||||
SimulateIOError( return SQLITE_ERROR );
|
||||
UNUSED_PARAMETER(nFull);
|
||||
assert( nFull>=pVfs->mxPathname );
|
||||
char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
|
||||
if( !zOut ){
|
||||
return SQLITE_IOERR_NOMEM_BKPT;
|
||||
}
|
||||
if( osCygwin_conv_path(
|
||||
CCP_POSIX_TO_WIN_W,
|
||||
zRelative, zOut, pVfs->mxPathname+1)<0 ){
|
||||
sqlite3_free(zOut);
|
||||
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
|
||||
"winFullPathname2", zRelative);
|
||||
}else{
|
||||
char *zUtf8 = winConvertToUtf8Filename(zOut);
|
||||
if( !zUtf8 ){
|
||||
sqlite3_free(zOut);
|
||||
return SQLITE_IOERR_NOMEM_BKPT;
|
||||
}
|
||||
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
|
||||
sqlite3_free(zUtf8);
|
||||
sqlite3_free(zOut);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
|
||||
#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32)
|
||||
SimulateIOError( return SQLITE_ERROR );
|
||||
@@ -6364,27 +6282,8 @@ static int winFullPathname(
|
||||
*/
|
||||
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
|
||||
HANDLE h;
|
||||
#if 0 /* This doesn't work correctly at all! See:
|
||||
<https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
|
||||
*/
|
||||
int nFull = pVfs->mxPathname+1;
|
||||
char *zFull = sqlite3MallocZero( nFull );
|
||||
void *zConverted = 0;
|
||||
if( zFull==0 ){
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
}
|
||||
if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
|
||||
sqlite3_free(zFull);
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
}
|
||||
zConverted = winConvertFromUtf8Filename(zFull);
|
||||
sqlite3_free(zFull);
|
||||
#else
|
||||
void *zConverted = winConvertFromUtf8Filename(zFilename);
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
#endif
|
||||
if( zConverted==0 ){
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
|
||||
@@ -700,6 +700,9 @@ struct Pager {
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -7581,6 +7584,11 @@ static int pagerOpenWal(Pager *pPager){
|
||||
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);
|
||||
|
||||
@@ -7700,6 +7708,7 @@ int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
|
||||
** blocking locks are required.
|
||||
*/
|
||||
void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
|
||||
pPager->dbWal = db;
|
||||
if( pagerUseWal(pPager) ){
|
||||
sqlite3WalDb(pPager->pWal, db);
|
||||
}
|
||||
|
||||
@@ -416,6 +416,14 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
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);
|
||||
|
||||
+17
-5
@@ -596,7 +596,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
|
||||
}
|
||||
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
|
||||
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
|
||||
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
|
||||
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.
|
||||
@@ -612,6 +612,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
|
||||
*/
|
||||
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
|
||||
@@ -628,7 +630,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
|
||||
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);
|
||||
@@ -2105,6 +2113,10 @@ static void generateColumnTypes(
|
||||
#endif
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER(pParse);
|
||||
UNUSED_PARAMETER(pTabList);
|
||||
UNUSED_PARAMETER(pEList);
|
||||
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
|
||||
}
|
||||
|
||||
@@ -4236,9 +4248,9 @@ static int compoundHasDifferentAffinities(Select *p){
|
||||
** from 2015-02-09.)
|
||||
**
|
||||
** (3) If the subquery is the right operand of a LEFT JOIN then
|
||||
** (3a) the subquery may not be a join and
|
||||
** (3b) the FROM clause of the subquery may not contain a virtual
|
||||
** table and
|
||||
** (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.
|
||||
@@ -4454,7 +4466,7 @@ static int flattenSubquery(
|
||||
*/
|
||||
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
|
||||
if( pSubSrc->nSrc>1 /* (3a) */
|
||||
|| IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */
|
||||
/**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|
||||
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|
||||
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
|
||||
){
|
||||
|
||||
+56
-8
@@ -887,12 +887,21 @@ static int strlen30(const char *z){
|
||||
|
||||
/*
|
||||
** Return the length of a string in characters. Multibyte UTF8 characters
|
||||
** count as a single character.
|
||||
** 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( (0xc0&*(z++))!=0x80 ) n++;
|
||||
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;
|
||||
}
|
||||
@@ -1325,11 +1334,7 @@ static void shellAddSchemaName(
|
||||
#define SQLITE_EXTENSION_INIT1
|
||||
#define SQLITE_EXTENSION_INIT2(X) (void)(X)
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
INCLUDE test_windirent.h
|
||||
INCLUDE test_windirent.c
|
||||
#define dirent DIRENT
|
||||
#endif
|
||||
INCLUDE ../ext/misc/windirent.h
|
||||
INCLUDE ../ext/misc/memtrace.c
|
||||
INCLUDE ../ext/misc/pcachetrace.c
|
||||
INCLUDE ../ext/misc/shathree.c
|
||||
@@ -11585,7 +11590,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{"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, "" },*/
|
||||
{"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..." },
|
||||
@@ -11923,6 +11928,49 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -366,6 +366,8 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.44.0 and later */
|
||||
void *(*get_clientdata)(sqlite3*,const char*);
|
||||
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
|
||||
/* Version 3.50.0 and later */
|
||||
int (*setlk_timeout)(sqlite3*,int,int);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -699,6 +701,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.44.0 and later */
|
||||
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
|
||||
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
|
||||
/* Version 3.50.0 and later */
|
||||
#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+29
-11
@@ -765,7 +765,7 @@
|
||||
** ourselves.
|
||||
*/
|
||||
#ifndef offsetof
|
||||
#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1153,6 +1153,7 @@ extern u32 sqlite3TreeTrace;
|
||||
** 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
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1197,6 +1198,7 @@ extern u32 sqlite3WhereTrace;
|
||||
** 0x00020000 Show WHERE terms returned from whereScanNext()
|
||||
** 0x00040000 Solver overview messages
|
||||
** 0x00080000 Star-query heuristic
|
||||
** 0x00100000 Pointers are all shown as zero
|
||||
*/
|
||||
|
||||
|
||||
@@ -2329,6 +2331,7 @@ struct CollSeq {
|
||||
#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)
|
||||
|
||||
@@ -2644,9 +2647,15 @@ struct FKey {
|
||||
** argument to sqlite3VdbeKeyCompare and is used to control the
|
||||
** comparison of the two index keys.
|
||||
**
|
||||
** Note that aSortOrder[] and aColl[] have nField+1 slots. There
|
||||
** are nField slots for the columns of an index then one extra slot
|
||||
** for the rowid at the end.
|
||||
** 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 */
|
||||
@@ -2658,9 +2667,18 @@ struct KeyInfo {
|
||||
CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
|
||||
};
|
||||
|
||||
/* The size (in bytes) of a KeyInfo object with up to N fields */
|
||||
/* 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.
|
||||
*/
|
||||
@@ -2679,9 +2697,8 @@ struct KeyInfo {
|
||||
**
|
||||
** An instance of this object serves as a "key" for doing a search on
|
||||
** an index b+tree. The goal of the search is to find the entry that
|
||||
** is closed to the key described by this object. This object might hold
|
||||
** just a prefix of the key. The number of fields is given by
|
||||
** pKeyInfo->nField.
|
||||
** 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
|
||||
@@ -2691,7 +2708,7 @@ struct KeyInfo {
|
||||
** The key comparison functions actually return default_rc when they find
|
||||
** an equals comparison. default_rc can be -1, 0, or +1. If there are
|
||||
** multiple entries in the b-tree with the same key (when only looking
|
||||
** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
|
||||
** 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.
|
||||
**
|
||||
@@ -2703,8 +2720,8 @@ struct KeyInfo {
|
||||
** b-tree.
|
||||
*/
|
||||
struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
Mem *aMem; /* Values */
|
||||
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() */
|
||||
@@ -4879,6 +4896,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
void sqlite3ShowWindow(const Window*);
|
||||
void sqlite3ShowWinFunc(const Window*);
|
||||
#endif
|
||||
void sqlite3ShowBitvec(Bitvec*);
|
||||
#endif
|
||||
|
||||
void sqlite3SetString(char **, sqlite3*, const char*);
|
||||
|
||||
+99
-43
@@ -49,6 +49,10 @@
|
||||
# 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 ****/
|
||||
|
||||
@@ -1084,7 +1088,9 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
Tcl_DecrRefCount(pCmd);
|
||||
}
|
||||
|
||||
if( rc && rc!=TCL_RETURN ){
|
||||
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);
|
||||
@@ -1102,7 +1108,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
}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)
|
||||
|| (c=='i' && strcmp(zType,"int")==0)
|
||||
){
|
||||
eType = SQLITE_INTEGER;
|
||||
}else if( c=='d' && strcmp(zType,"double")==0 ){
|
||||
@@ -1616,11 +1622,12 @@ struct DbEvalContext {
|
||||
SqlPreparedStmt *pPreStmt; /* Current statement */
|
||||
int nCol; /* Number of columns returned by pStmt */
|
||||
int evalFlags; /* Flags used */
|
||||
Tcl_Obj *pArray; /* Name of array variable */
|
||||
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
|
||||
@@ -1641,20 +1648,20 @@ static void dbReleaseColumnNames(DbEvalContext *p){
|
||||
/*
|
||||
** Initialize a DbEvalContext structure.
|
||||
**
|
||||
** If pArray is not NULL, then it contains the name of a Tcl array
|
||||
** 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 ${pArray}(*) {a b c}
|
||||
** 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 *pArray, /* Name of Tcl array to set (*) element of */
|
||||
Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */
|
||||
int evalFlags /* Flags controlling evaluation */
|
||||
){
|
||||
memset(p, 0, sizeof(DbEvalContext));
|
||||
@@ -1662,9 +1669,9 @@ static void dbEvalInit(
|
||||
p->zSql = Tcl_GetString(pSql);
|
||||
p->pSql = pSql;
|
||||
Tcl_IncrRefCount(pSql);
|
||||
if( pArray ){
|
||||
p->pArray = pArray;
|
||||
Tcl_IncrRefCount(pArray);
|
||||
if( pVarName ){
|
||||
p->pVarName = pVarName;
|
||||
Tcl_IncrRefCount(pVarName);
|
||||
}
|
||||
p->evalFlags = evalFlags;
|
||||
addDatabaseRef(p->pDb);
|
||||
@@ -1687,7 +1694,7 @@ static void dbEvalRowInfo(
|
||||
Tcl_Obj **apColName = 0; /* Array of column names */
|
||||
|
||||
p->nCol = nCol = sqlite3_column_count(pStmt);
|
||||
if( nCol>0 && (papColName || p->pArray) ){
|
||||
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);
|
||||
@@ -1696,20 +1703,35 @@ static void dbEvalRowInfo(
|
||||
p->apColName = apColName;
|
||||
}
|
||||
|
||||
/* If results are being stored in an array variable, then create
|
||||
** the array(*) entry for that array
|
||||
/* If results are being stored in a variable then create the
|
||||
** array(*) or dict(*) entry for that variable.
|
||||
*/
|
||||
if( p->pArray ){
|
||||
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]);
|
||||
}
|
||||
Tcl_IncrRefCount(pStar);
|
||||
Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1751,7 +1773,7 @@ static int dbEvalStep(DbEvalContext *p){
|
||||
if( rcs==SQLITE_ROW ){
|
||||
return TCL_OK;
|
||||
}
|
||||
if( p->pArray ){
|
||||
if( p->pVarName ){
|
||||
dbEvalRowInfo(p, 0, 0);
|
||||
}
|
||||
rcs = sqlite3_reset(pStmt);
|
||||
@@ -1802,9 +1824,9 @@ static void dbEvalFinalize(DbEvalContext *p){
|
||||
dbReleaseStmt(p->pDb, p->pPreStmt, 0);
|
||||
p->pPreStmt = 0;
|
||||
}
|
||||
if( p->pArray ){
|
||||
Tcl_DecrRefCount(p->pArray);
|
||||
p->pArray = 0;
|
||||
if( p->pVarName ){
|
||||
Tcl_DecrRefCount(p->pVarName);
|
||||
p->pVarName = 0;
|
||||
}
|
||||
Tcl_DecrRefCount(p->pSql);
|
||||
dbReleaseColumnNames(p);
|
||||
@@ -1879,7 +1901,7 @@ static int DbUseNre(void){
|
||||
/*
|
||||
** This function is part of the implementation of the command:
|
||||
**
|
||||
** $db eval SQL ?ARRAYNAME? SCRIPT
|
||||
** $db eval SQL ?TGT-NAME? SCRIPT
|
||||
*/
|
||||
static int SQLITE_TCLAPI DbEvalNextCmd(
|
||||
ClientData data[], /* data[0] is the (DbEvalContext*) */
|
||||
@@ -1893,8 +1915,8 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
|
||||
** 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 *pScript = (Tcl_Obj *)data[1];
|
||||
Tcl_Obj *pArray = p->pArray;
|
||||
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;
|
||||
@@ -1902,15 +1924,46 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
|
||||
Tcl_Obj **apColName;
|
||||
dbEvalRowInfo(p, &nCol, &apColName);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( pArray==0 ){
|
||||
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
|
||||
&& sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
|
||||
){
|
||||
Tcl_UnsetVar2(interp, Tcl_GetString(pArray),
|
||||
Tcl_GetString(apColName[i]), 0);
|
||||
/* 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{
|
||||
Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2019,7 +2072,7 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
"timeout", "total_changes", "trace",
|
||||
"trace_v2", "transaction", "unlock_notify",
|
||||
"update_hook", "version", "wal_hook",
|
||||
0
|
||||
0
|
||||
};
|
||||
enum DB_enum {
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
|
||||
@@ -2853,13 +2906,15 @@ deserialize_error:
|
||||
}
|
||||
|
||||
/*
|
||||
** $db eval ?options? $sql ?array? ?{ ...code... }?
|
||||
** $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 named "array" and ...code... is executed.
|
||||
** If "array" and "code" are omitted, then no callback is every invoked.
|
||||
** If "array" is an empty string, then the values are placed in variables
|
||||
** that have the same name as the fields extracted by the query.
|
||||
** 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;
|
||||
@@ -2867,8 +2922,9 @@ deserialize_error:
|
||||
while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
|
||||
if( strcmp(zOpt, "-withoutnulls")==0 ){
|
||||
evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
|
||||
}
|
||||
else{
|
||||
}else if( strcmp(zOpt, "-asdict")==0 ){
|
||||
evalFlags |= SQLITE_EVAL_ASDICT;
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -2876,8 +2932,8 @@ deserialize_error:
|
||||
objv++;
|
||||
}
|
||||
if( objc<3 || objc>5 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv,
|
||||
"?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?");
|
||||
Tcl_WrongNumArgs(interp, 2, objv,
|
||||
"?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -2903,17 +2959,17 @@ deserialize_error:
|
||||
}else{
|
||||
ClientData cd2[2];
|
||||
DbEvalContext *p;
|
||||
Tcl_Obj *pArray = 0;
|
||||
Tcl_Obj *pVarName = 0;
|
||||
Tcl_Obj *pScript;
|
||||
|
||||
if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
|
||||
pArray = objv[3];
|
||||
pVarName = objv[3];
|
||||
}
|
||||
pScript = objv[objc-1];
|
||||
Tcl_IncrRefCount(pScript);
|
||||
|
||||
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
|
||||
dbEvalInit(p, pDb, objv[2], pArray, evalFlags);
|
||||
dbEvalInit(p, pDb, objv[2], pVarName, evalFlags);
|
||||
|
||||
cd2[0] = (void *)p;
|
||||
cd2[1] = (void *)pScript;
|
||||
@@ -4044,8 +4100,8 @@ EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
|
||||
#if defined(TCLSH)
|
||||
|
||||
/* This is the main routine for an ordinary TCL shell. If there are
|
||||
** are arguments, run the first argument as a script. Otherwise,
|
||||
** read TCL commands from standard input
|
||||
** arguments, run the first argument as a script. Otherwise, read TCL
|
||||
** commands from standard input
|
||||
*/
|
||||
static const char *tclsh_main_loop(void){
|
||||
static const char zMainloop[] =
|
||||
|
||||
@@ -8458,7 +8458,12 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
|
||||
{ "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;
|
||||
|
||||
+4
-8
@@ -72,12 +72,8 @@
|
||||
#if !defined(_WIN32) || defined(__MSVCRT__)
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# ifndef DIRENT
|
||||
# define DIRENT dirent
|
||||
# endif
|
||||
#else
|
||||
# include <io.h>
|
||||
# include "test_windirent.h"
|
||||
# include "windirent.h"
|
||||
# ifndef S_ISREG
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
# endif
|
||||
@@ -121,7 +117,7 @@ struct FsdirCsr {
|
||||
char *zDir; /* Buffer containing directory scanned */
|
||||
DIR *pDir; /* Open directory */
|
||||
sqlite3_int64 iRowid;
|
||||
struct DIRENT *pEntry;
|
||||
struct dirent *pEntry;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -483,9 +479,9 @@ static int fstreeFilter(
|
||||
char aWild[2] = { '\0', '\0' };
|
||||
|
||||
#ifdef _WIN32
|
||||
const char *zDrive = windirent_getenv("fstreeDrive");
|
||||
const char *zDrive = getenv("fstreeDrive");
|
||||
if( zDrive==0 ){
|
||||
zDrive = windirent_getenv("SystemDrive");
|
||||
zDrive = getenv("SystemDrive");
|
||||
}
|
||||
zRoot = sqlite3_mprintf("%s%c", zDrive, '/');
|
||||
nRoot = sqlite3Strlen30(zRoot);
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
** 2015 November 30
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains code to implement most of the opendir() family of
|
||||
** POSIX functions on Win32 using the MSVCRT.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
#include "test_windirent.h"
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX getenv() function using the Win32 API.
|
||||
** This function is not thread-safe.
|
||||
*/
|
||||
const char *windirent_getenv(
|
||||
const char *name
|
||||
){
|
||||
static char value[32768]; /* Maximum length, per MSDN */
|
||||
DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
|
||||
DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
|
||||
|
||||
memset(value, 0, sizeof(value));
|
||||
dwRet = GetEnvironmentVariableA(name, value, dwSize);
|
||||
if( dwRet==0 || dwRet>dwSize ){
|
||||
/*
|
||||
** The function call to GetEnvironmentVariableA() failed -OR-
|
||||
** the buffer is not large enough. Either way, return NULL.
|
||||
*/
|
||||
return 0;
|
||||
}else{
|
||||
/*
|
||||
** The function call to GetEnvironmentVariableA() succeeded
|
||||
** -AND- the buffer contains the entire value.
|
||||
*/
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX opendir() function using the MSVCRT.
|
||||
*/
|
||||
LPDIR opendir(
|
||||
const char *dirname /* Directory name, UTF8 encoding */
|
||||
){
|
||||
struct _wfinddata_t data;
|
||||
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
|
||||
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
|
||||
wchar_t *b1;
|
||||
sqlite3_int64 sz;
|
||||
|
||||
if( dirp==NULL ) return NULL;
|
||||
memset(dirp, 0, sizeof(DIR));
|
||||
|
||||
/* TODO: Remove this if Unix-style root paths are not used. */
|
||||
if( sqlite3_stricmp(dirname, "/")==0 ){
|
||||
dirname = windirent_getenv("SystemDrive");
|
||||
}
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
sz = strlen(dirname);
|
||||
b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
|
||||
if( b1==0 ){
|
||||
closedir(dirp);
|
||||
return NULL;
|
||||
}
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
|
||||
b1[sz++] = '\\';
|
||||
b1[sz++] = '*';
|
||||
b1[sz] = 0;
|
||||
if( sz+1>(sqlite3_int64)namesize ){
|
||||
closedir(dirp);
|
||||
sqlite3_free(b1);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
|
||||
sqlite3_free(b1);
|
||||
dirp->d_handle = _wfindfirst(data.name, &data);
|
||||
|
||||
if( dirp->d_handle==BAD_INTPTR_T ){
|
||||
closedir(dirp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: Remove this block to allow hidden and/or system files. */
|
||||
if( is_filtered(data) ){
|
||||
next:
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
if( _wfindnext(dirp->d_handle, &data)==-1 ){
|
||||
closedir(dirp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: Remove this block to allow hidden and/or system files. */
|
||||
if( is_filtered(data) ) goto next;
|
||||
}
|
||||
|
||||
dirp->d_first.d_attributes = data.attrib;
|
||||
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
||||
dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX readdir() function using the MSVCRT.
|
||||
*/
|
||||
LPDIRENT readdir(
|
||||
LPDIR dirp
|
||||
){
|
||||
struct _wfinddata_t data;
|
||||
|
||||
if( dirp==NULL ) return NULL;
|
||||
|
||||
if( dirp->d_first.d_ino==0 ){
|
||||
dirp->d_first.d_ino++;
|
||||
dirp->d_next.d_ino++;
|
||||
|
||||
return &dirp->d_first;
|
||||
}
|
||||
|
||||
next:
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
|
||||
|
||||
/* TODO: Remove this block to allow hidden and/or system files. */
|
||||
if( is_filtered(data) ) goto next;
|
||||
|
||||
dirp->d_next.d_ino++;
|
||||
dirp->d_next.d_attributes = data.attrib;
|
||||
WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
|
||||
dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
|
||||
return &dirp->d_next;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX closedir() function using the MSVCRT.
|
||||
*/
|
||||
INT closedir(
|
||||
LPDIR dirp
|
||||
){
|
||||
INT result = 0;
|
||||
|
||||
if( dirp==NULL ) return EINVAL;
|
||||
|
||||
if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
|
||||
result = _findclose(dirp->d_handle);
|
||||
}
|
||||
|
||||
sqlite3_free(dirp);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
** 2015 November 30
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains declarations for most of the opendir() family of
|
||||
** POSIX functions on Win32 using the MSVCRT.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
|
||||
#define SQLITE_WINDIRENT_H
|
||||
|
||||
/*
|
||||
** We need several data types from the Windows SDK header.
|
||||
*/
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
/*
|
||||
** We need several support functions from the SQLite core.
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** We need several things from the ANSI and MSVCRT headers.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
** We may need several defines that should have been in "sys/stat.h".
|
||||
*/
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define S_ISLNK(mode) (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We may need to provide the "mode_t" type.
|
||||
*/
|
||||
|
||||
#ifndef MODE_T_DEFINED
|
||||
#define MODE_T_DEFINED
|
||||
typedef unsigned short mode_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We may need to provide the "ino_t" type.
|
||||
*/
|
||||
|
||||
#ifndef INO_T_DEFINED
|
||||
#define INO_T_DEFINED
|
||||
typedef unsigned short ino_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to define "NAME_MAX" if it was not present in "limits.h".
|
||||
*/
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# ifdef FILENAME_MAX
|
||||
# define NAME_MAX (FILENAME_MAX)
|
||||
# else
|
||||
# define NAME_MAX (260)
|
||||
# endif
|
||||
# define DIRENT_NAME_MAX (NAME_MAX)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
|
||||
*/
|
||||
|
||||
#ifndef NULL_INTPTR_T
|
||||
# define NULL_INTPTR_T ((intptr_t)(0))
|
||||
#endif
|
||||
|
||||
#ifndef BAD_INTPTR_T
|
||||
# define BAD_INTPTR_T ((intptr_t)(-1))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to provide the necessary structures and related types.
|
||||
*/
|
||||
|
||||
#ifndef DIRENT_DEFINED
|
||||
#define DIRENT_DEFINED
|
||||
typedef struct DIRENT DIRENT;
|
||||
typedef DIRENT *LPDIRENT;
|
||||
struct DIRENT {
|
||||
ino_t d_ino; /* Sequence number, do not use. */
|
||||
unsigned d_attributes; /* Win32 file attributes. */
|
||||
char d_name[NAME_MAX + 1]; /* Name within the directory. */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DIR_DEFINED
|
||||
#define DIR_DEFINED
|
||||
typedef struct DIR DIR;
|
||||
typedef DIR *LPDIR;
|
||||
struct DIR {
|
||||
intptr_t d_handle; /* Value returned by "_findfirst". */
|
||||
DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
|
||||
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Provide a macro, for use by the implementation, to determine if a
|
||||
** particular directory entry should be skipped over when searching for
|
||||
** the next directory entry that should be returned by the readdir().
|
||||
*/
|
||||
|
||||
#ifndef is_filtered
|
||||
# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Provide the function prototype for the POSIX compatible getenv()
|
||||
** function. This function is not thread-safe.
|
||||
*/
|
||||
|
||||
extern const char *windirent_getenv(const char *name);
|
||||
|
||||
/*
|
||||
** Finally, we can provide the function prototypes for the opendir(),
|
||||
** readdir(), and closedir() POSIX functions.
|
||||
*/
|
||||
|
||||
extern LPDIR opendir(const char *dirname);
|
||||
extern LPDIRENT readdir(LPDIR dirp);
|
||||
extern INT closedir(LPDIR dirp);
|
||||
|
||||
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
||||
@@ -108,7 +108,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|
||||
/*
|
||||
** Write a single UTF8 character whose value is v into the
|
||||
** buffer starting at zOut. zOut must be sized to hold at
|
||||
** least for bytes. Return the number of bytes needed
|
||||
** least four bytes. Return the number of bytes needed
|
||||
** to encode the new character.
|
||||
*/
|
||||
int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
|
||||
|
||||
+2
-1
@@ -195,7 +195,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
saved_nChange = db->nChange;
|
||||
saved_nTotalChange = db->nTotalChange;
|
||||
saved_mTrace = db->mTrace;
|
||||
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
|
||||
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);
|
||||
|
||||
+2
-1
@@ -2476,6 +2476,7 @@ case OP_Compare: {
|
||||
pKeyInfo = pOp->p4.pKeyInfo;
|
||||
assert( n>0 );
|
||||
assert( pKeyInfo!=0 );
|
||||
assert( pKeyInfo->aSortFlags!=0 );
|
||||
p1 = pOp->p1;
|
||||
p2 = pOp->p2;
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -5349,7 +5350,7 @@ case OP_Found: { /* jump, in3, ncycle */
|
||||
if( rc ) goto no_mem;
|
||||
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
|
||||
if( pIdxKey==0 ) goto no_mem;
|
||||
sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
|
||||
sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
|
||||
pIdxKey->default_rc = 0;
|
||||
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
|
||||
sqlite3DbFreeNN(db, pIdxKey);
|
||||
|
||||
+1
-1
@@ -301,7 +301,7 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
|
||||
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
||||
int sqlite3BlobCompare(const Mem*, const Mem*);
|
||||
|
||||
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
||||
void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
|
||||
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
|
||||
|
||||
+1
-1
@@ -557,7 +557,7 @@ struct PreUpdate {
|
||||
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 */
|
||||
u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -2163,7 +2163,7 @@ static UnpackedRecord *vdbeUnpackRecord(
|
||||
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
|
||||
if( pRet ){
|
||||
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
|
||||
sqlite3VdbeRecordUnpack(nKey, pKey, pRet);
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
+10
-16
@@ -4202,30 +4202,22 @@ void sqlite3VdbeSerialGet(
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** This routine is used to allocate sufficient space for an UnpackedRecord
|
||||
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
|
||||
** the first argument is a pointer to KeyInfo structure pKeyInfo.
|
||||
** Allocate sufficient space for an UnpackedRecord structure large enough
|
||||
** to hold a decoded index record for pKeyInfo.
|
||||
**
|
||||
** The space is either allocated using sqlite3DbMallocRaw() or from within
|
||||
** the unaligned buffer passed via the second and third arguments (presumably
|
||||
** stack space). If the former, then *ppFree is set to a pointer that should
|
||||
** be eventually freed by the caller using sqlite3DbFree(). Or, if the
|
||||
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
|
||||
** before returning.
|
||||
**
|
||||
** If an OOM error occurs, NULL is returned.
|
||||
** 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 */
|
||||
int nByte; /* Number of bytes required for *p */
|
||||
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))];
|
||||
assert( pKeyInfo->aSortFlags!=0 );
|
||||
p->pKeyInfo = pKeyInfo;
|
||||
p->nField = pKeyInfo->nKeyField + 1;
|
||||
return p;
|
||||
@@ -4237,7 +4229,6 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
|
||||
** contents of the decoded record.
|
||||
*/
|
||||
void sqlite3VdbeRecordUnpack(
|
||||
KeyInfo *pKeyInfo, /* Information about the record format */
|
||||
int nKey, /* Size of the binary record */
|
||||
const void *pKey, /* The binary record */
|
||||
UnpackedRecord *p /* Populate this structure before returning. */
|
||||
@@ -4248,6 +4239,7 @@ void sqlite3VdbeRecordUnpack(
|
||||
u16 u; /* Unsigned loop counter */
|
||||
u32 szHdr;
|
||||
Mem *pMem = p->aMem;
|
||||
KeyInfo *pKeyInfo = p->pKeyInfo;
|
||||
|
||||
p->default_rc = 0;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
||||
@@ -4275,6 +4267,8 @@ void sqlite3VdbeRecordUnpack(
|
||||
** warnings from MSAN. */
|
||||
sqlite3VdbeMemSetNull(pMem-1);
|
||||
}
|
||||
testcase( u == pKeyInfo->nKeyField + 1 );
|
||||
testcase( u < pKeyInfo->nKeyField + 1 );
|
||||
assert( u<=pKeyInfo->nKeyField + 1 );
|
||||
p->nField = u;
|
||||
}
|
||||
@@ -5134,6 +5128,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
|
||||
** 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] ){
|
||||
@@ -5492,7 +5487,6 @@ void sqlite3VdbePreUpdateHook(
|
||||
i64 iKey2;
|
||||
PreUpdate preupdate;
|
||||
const char *zTbl = pTab->zName;
|
||||
static const u8 fakeSortOrder = 0;
|
||||
#ifdef SQLITE_DEBUG
|
||||
int nRealCol;
|
||||
if( pTab->tabFlags & TF_WithoutRowid ){
|
||||
@@ -5531,7 +5525,7 @@ void sqlite3VdbePreUpdateHook(
|
||||
preupdate.pKeyinfo->db = db;
|
||||
preupdate.pKeyinfo->enc = ENC(db);
|
||||
preupdate.pKeyinfo->nKeyField = pTab->nCol;
|
||||
preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
|
||||
preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
|
||||
preupdate.iKey1 = iKey1;
|
||||
preupdate.iKey2 = iKey2;
|
||||
preupdate.pTab = pTab;
|
||||
|
||||
+12
-4
@@ -766,7 +766,7 @@ static int vdbeSorterCompareTail(
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( *pbKey2Cached==0 ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
|
||||
@@ -793,7 +793,7 @@ static int vdbeSorterCompare(
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( !*pbKey2Cached ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
||||
@@ -833,6 +833,7 @@ static int vdbeSorterCompareText(
|
||||
);
|
||||
}
|
||||
}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;
|
||||
@@ -896,6 +897,7 @@ static int vdbeSorterCompareInt(
|
||||
}
|
||||
}
|
||||
|
||||
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
|
||||
if( res==0 ){
|
||||
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
|
||||
res = vdbeSorterCompareTail(
|
||||
@@ -969,7 +971,8 @@ int sqlite3VdbeSorterInit(
|
||||
assert( pCsr->eCurType==CURTYPE_SORTER );
|
||||
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
|
||||
< 0x7fffffff );
|
||||
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
|
||||
assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
|
||||
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
|
||||
sz = SZ_VDBESORTER(nWorker+1);
|
||||
|
||||
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
|
||||
@@ -983,7 +986,12 @@ int sqlite3VdbeSorterInit(
|
||||
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);
|
||||
@@ -2763,7 +2771,7 @@ int sqlite3VdbeSorterCompare(
|
||||
assert( r2->nField==nKeyCol );
|
||||
|
||||
pKey = vdbeSorterRowkey(pSorter, &nKey);
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
|
||||
sqlite3VdbeRecordUnpack(nKey, pKey, r2);
|
||||
for(i=0; i<nKeyCol; i++){
|
||||
if( r2->aMem[i].flags & MEM_Null ){
|
||||
*pRes = -1;
|
||||
|
||||
@@ -3062,7 +3062,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
|
||||
rc = walIndexReadHdr(pWal, pChanged);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
walDisableBlocking(pWal);
|
||||
if( rc==SQLITE_BUSY_TIMEOUT ){
|
||||
rc = SQLITE_BUSY;
|
||||
*pCnt |= WAL_RETRY_BLOCKED_MASK;
|
||||
@@ -3077,6 +3076,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
|
||||
** 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
|
||||
@@ -3093,6 +3093,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
|
||||
rc = SQLITE_BUSY_RECOVERY;
|
||||
}
|
||||
}
|
||||
walDisableBlocking(pWal);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
+6
-4
@@ -426,11 +426,11 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
pScan->pWC = pWC;
|
||||
pScan->k = k+1;
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace & 0x20000 ){
|
||||
if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){
|
||||
int ii;
|
||||
sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
|
||||
pTerm, pScan->nEquiv);
|
||||
for(ii=0; ii<pScan->nEquiv; 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]);
|
||||
}
|
||||
@@ -2385,6 +2385,7 @@ void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
|
||||
}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);
|
||||
@@ -3602,6 +3603,7 @@ static int whereUsablePartialIndex(
|
||||
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
|
||||
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
|
||||
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
|
||||
&& !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
|
||||
&& (pTerm->wtFlags & TERM_VNULL)==0
|
||||
){
|
||||
return 1;
|
||||
|
||||
@@ -280,6 +280,9 @@ struct WhereTerm {
|
||||
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>" */
|
||||
|
||||
+43
-42
@@ -110,7 +110,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
|
||||
}
|
||||
|
||||
/*
|
||||
** This function sets the P4 value of an existing OP_Explain opcode to
|
||||
** 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.
|
||||
*/
|
||||
@@ -600,7 +600,7 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
iField = pLoop->aLTerm[i]->u.x.iField - 1;
|
||||
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
|
||||
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
|
||||
pOrigRhs->a[iField].pExpr = 0;
|
||||
pOrigRhs->a[iField].pExpr = 0;
|
||||
if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
|
||||
if( pOrigLhs ){
|
||||
assert( pOrigLhs->a[iField].pExpr!=0 );
|
||||
@@ -948,7 +948,7 @@ static int codeAllEqualityTerms(
|
||||
testcase( pIdx->aiColumn[j]==XN_EXPR );
|
||||
VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Evaluate the equality constraints
|
||||
*/
|
||||
@@ -1289,7 +1289,7 @@ static void codeDeferredSeek(
|
||||
|
||||
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))
|
||||
@@ -1443,14 +1443,14 @@ static SQLITE_NOINLINE void filterPullDown(
|
||||
}
|
||||
|
||||
/*
|
||||
** 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
|
||||
** 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
|
||||
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++){
|
||||
@@ -1831,37 +1831,37 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
||||
}
|
||||
}else if( pLoop->wsFlags & WHERE_INDEXED ){
|
||||
/* Case 4: A scan using an index.
|
||||
/* Case 4: Search using an index.
|
||||
**
|
||||
** The WHERE clause may contain zero or more equality
|
||||
** terms ("==" or "IN" operators) that refer to the N
|
||||
** left-most columns of the index. It may also contain
|
||||
** inequality constraints (>, <, >= or <=) on the indexed
|
||||
** column that immediately follows the N equalities. Only
|
||||
** the right-most column can be an inequality - the rest must
|
||||
** use the "==" and "IN" operators. For example, if the
|
||||
** index is on (x,y,z), then the following clauses are all
|
||||
** optimized:
|
||||
** 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
|
||||
** 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:
|
||||
** The z<10 term of the following cannot be used, only
|
||||
** the x=5 term:
|
||||
**
|
||||
** x=5 AND z<10
|
||||
** 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.
|
||||
** 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.
|
||||
*/
|
||||
** 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,
|
||||
@@ -2015,7 +2015,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
if( zStartAff ){
|
||||
updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
|
||||
}
|
||||
}
|
||||
nConstraint += nBtm;
|
||||
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
|
||||
if( sqlite3ExprIsVector(pRight)==0 ){
|
||||
@@ -2201,12 +2201,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
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.
|
||||
** the partial index. This optimization does not work on an outer join,
|
||||
** as shown by:
|
||||
**
|
||||
** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
|
||||
** for a LEFT JOIN.
|
||||
** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
|
||||
** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
|
||||
*/
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
|
||||
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
|
||||
}
|
||||
}else{
|
||||
@@ -2216,7 +2217,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** 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))
|
||||
@@ -2605,7 +2606,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
**
|
||||
** iLoop==1: Code only expressions that are entirely covered by pIdx.
|
||||
** iLoop==2: Code remaining expressions that do not contain correlated
|
||||
** sub-queries.
|
||||
** sub-queries.
|
||||
** iLoop==3: Code all remaining expressions.
|
||||
**
|
||||
** An effort is made to skip unnecessary iterations of the loop.
|
||||
@@ -2876,7 +2877,7 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
|
||||
pSubq = pRight->u4.pSubq;
|
||||
assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
|
||||
sqlite3VdbeAddOp3(
|
||||
v, OP_Null, 0, pSubq->regResult,
|
||||
v, OP_Null, 0, pSubq->regResult,
|
||||
pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
|
||||
);
|
||||
}
|
||||
|
||||
+23
-12
@@ -931,30 +931,38 @@ static void exprAnalyzeOrTerm(
|
||||
** 1. The SQLITE_Transitive optimization must be enabled
|
||||
** 2. Must be either an == or an IS operator
|
||||
** 3. Not originating in the ON clause of an OUTER JOIN
|
||||
** 4. The affinities of A and B must be compatible
|
||||
** 5a. Both operands use the same collating sequence OR
|
||||
** 5b. The overall collating sequence is BINARY
|
||||
** 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){
|
||||
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
char aff1, aff2;
|
||||
CollSeq *pColl;
|
||||
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
|
||||
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
|
||||
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
|
||||
if( !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) */
|
||||
if( pExpr->op==TK_IS && (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;
|
||||
return 0; /* (5) */
|
||||
}
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
|
||||
if( sqlite3IsBinary(pColl) ) return 1;
|
||||
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
|
||||
if( !sqlite3IsBinary(pColl)
|
||||
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
|
||||
){
|
||||
return 0; /* (6) */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1112,6 +1120,9 @@ static void exprAnalyze(
|
||||
}
|
||||
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 */
|
||||
@@ -1219,8 +1230,8 @@ static void exprAnalyze(
|
||||
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
|
||||
if( termIsEquivalence(pParse, pDup) ){
|
||||
assert( pWInfo->pTabList!=0 );
|
||||
if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){
|
||||
pTerm->eOperator |= WO_EQUIV;
|
||||
eExtraOp = WO_EQUIV;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,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;
|
||||
+1
-4
@@ -97,11 +97,8 @@ do_eqp_test 4.2 {
|
||||
WHERE t4.y = ?;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE rr
|
||||
| `--SCAN ft4 VIRTUAL TABLE INDEX 3:
|
||||
|--SCAN t4
|
||||
|--BLOOM FILTER ON rr (docid=?)
|
||||
`--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?) LEFT-JOIN
|
||||
`--SCAN ft4 VIRTUAL TABLE INDEX 3: LEFT-JOIN
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -26,6 +26,9 @@ do_catchsql_test func9-120 {
|
||||
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);
|
||||
} {{}}
|
||||
|
||||
@@ -1002,6 +1002,21 @@ do_execsql_test join-20.2 {
|
||||
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.
|
||||
@@ -1289,4 +1304,69 @@ do_execsql_test join-30.3 {
|
||||
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
|
||||
|
||||
@@ -341,4 +341,74 @@ do_execsql_test 13.4 {
|
||||
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
|
||||
|
||||
+1
-1
@@ -1113,7 +1113,7 @@ do_execsql_test json101-21.26 {
|
||||
do_execsql_test json101-21.27 {
|
||||
WITH c(x,y) AS (VALUES('a',1),('b',2.0),('c',NULL),(NULL,'three'),('e','four'))
|
||||
SELECT json_group_object(x,y) FROM c;
|
||||
} {{{"a":1,"b":2.0,"c":null,:"three","e":"four"}}}
|
||||
} {{{"a":1,"b":2.0,"c":null,"e":"four"}}}
|
||||
|
||||
# 2023-10-09 https://sqlite.org/forum/forumpost/b25edc1d46
|
||||
# UAF due to JSON cache overflow
|
||||
|
||||
@@ -96,6 +96,9 @@ do_test 1.8 {
|
||||
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 {
|
||||
|
||||
+12
-3
@@ -25,6 +25,7 @@ Other options include:
|
||||
--help Show this help screen.
|
||||
--lean "Lean" mode.
|
||||
--lookaside N SZ Lookahead uses N slots of SZ bytes each.
|
||||
--osmalloc Use the OS native malloc() instead of MEMSYS5
|
||||
--pagesize N Use N as the page size.
|
||||
--quiet | -q "Quite". Put results in file but don't pop up editor
|
||||
--size N Change the test size. 100 means 100%. Default: 5.
|
||||
@@ -40,7 +41,8 @@ set cc gcc
|
||||
set testset mix1
|
||||
set dryrun 0
|
||||
set quiet 0
|
||||
set speedtestflags {--shrink-memory --reprepare --stats --heap 40000000 64}
|
||||
set osmalloc 0
|
||||
set speedtestflags {--shrink-memory --reprepare --stats}
|
||||
lappend speedtestflags --journal wal --size 5
|
||||
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
@@ -92,6 +94,10 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
--dryrun {
|
||||
set dryrun 1
|
||||
}
|
||||
-osmalloc -
|
||||
--osmalloc {
|
||||
set osmalloc 1
|
||||
}
|
||||
-? -
|
||||
-help -
|
||||
--help {
|
||||
@@ -139,10 +145,13 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
if {[lsearch -glob $cflags -O*]<0} {
|
||||
lappend cflags -Os
|
||||
}
|
||||
if {[lsearch -glob $cflags -DSQLITE_ENABLE_MEMSYS*]<0} {
|
||||
if {!$osmalloc} {
|
||||
append speedtestflags { --heap 40000000 64}
|
||||
}
|
||||
if {!$osmalloc && [lsearch -glob $cflags {-DSQLITE_ENABLE_MEMSYS*}]<0} {
|
||||
lappend cflags -DSQLITE_ENABLE_MEMSYS5
|
||||
}
|
||||
if {[lsearch -glob $cflags -DSQLITE_ENABLE_RTREE*]<0} {
|
||||
if {[lsearch -glob $cflags {-DSQLITE_ENABLE_RTREE*}]<0} {
|
||||
lappend cflags -DSQLITE_ENABLE_RTREE
|
||||
}
|
||||
if {$srcfile==""} {
|
||||
|
||||
+108
-45
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for TCL interface to the
|
||||
# SQLite library.
|
||||
# SQLite library.
|
||||
#
|
||||
# Actually, all tests are based on the TCL interface, so the main
|
||||
# interface is pretty well tested. This file contains some addition
|
||||
@@ -121,7 +121,7 @@ ifcapable {complete} {
|
||||
do_test tcl-1.14 {
|
||||
set v [catch {db eval} msg]
|
||||
lappend v $msg
|
||||
} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"}}
|
||||
} {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
|
||||
@@ -359,6 +359,19 @@ do_test tcl-9.3 {
|
||||
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 {
|
||||
@@ -465,7 +478,7 @@ 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
|
||||
# Now test that [db transaction] commands may be nested with
|
||||
# the expected results.
|
||||
#
|
||||
do_test tcl-10.14 {
|
||||
@@ -475,7 +488,7 @@ do_test tcl-10.14 {
|
||||
INSERT INTO t4 VALUES('one');
|
||||
}
|
||||
|
||||
catch {
|
||||
catch {
|
||||
db transaction {
|
||||
db eval { INSERT INTO t4 VALUES('two') }
|
||||
db transaction {
|
||||
@@ -674,11 +687,11 @@ do_test tcl-15.5 {
|
||||
} {0}
|
||||
|
||||
|
||||
# 2017-06-26: The --withoutnulls flag to "db eval".
|
||||
# 2017-06-26: The -withoutnulls flag to "db eval".
|
||||
#
|
||||
# In the "db eval --withoutnulls SQL ARRAY" form, NULL results cause the
|
||||
# corresponding array entry to be unset. The default behavior (without
|
||||
# the -withoutnulls flags) is for the corresponding array value to get
|
||||
# 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}
|
||||
@@ -720,64 +733,64 @@ 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_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 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_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
|
||||
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) );
|
||||
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) );
|
||||
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) );
|
||||
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') );
|
||||
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') );
|
||||
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') );
|
||||
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 {
|
||||
@@ -848,21 +861,70 @@ do_catchsql_test 19.911 {
|
||||
} {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 20.1 {
|
||||
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
|
||||
@@ -874,7 +936,7 @@ sqlite3 db test.db
|
||||
db func closedb closedb
|
||||
db func func1 func1
|
||||
|
||||
do_test 20.2 {
|
||||
do_test 21.2 {
|
||||
set rc [catch {
|
||||
db eval {
|
||||
SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
|
||||
@@ -884,9 +946,10 @@ do_test 20.2 {
|
||||
} {0 {10 1 20 30 30 40}}
|
||||
|
||||
sqlite3 db :memory:
|
||||
do_test 21.1 {
|
||||
do_test 22.1 {
|
||||
catch {db eval {SELECT 1 2 3;}} msg
|
||||
db erroroffset
|
||||
} {9}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -458,16 +458,17 @@ proc trd_fuzztest_data {buildname} {
|
||||
|
||||
if {$::tcl_platform(platform) eq "windows"} {
|
||||
return [list fuzzcheck.exe $lFuzzDb]
|
||||
} elseif {[lsearch $sanBuilds $buildname]>=0} {
|
||||
return [list [trd_get_bin_name fuzzcheck] $lFuzzDb \
|
||||
[trd_get_bin_name fuzzcheck-asan] $lFuzzDb \
|
||||
[trd_get_bin_name fuzzcheck-ubsan] $lFuzzDb \
|
||||
{sessionfuzz run} $lSessionDb]
|
||||
} else {
|
||||
return [list [trd_get_bin_name fuzzcheck] $lFuzzDb \
|
||||
{sessionfuzz run} $lSessionDb]
|
||||
set lRet [list [trd_get_bin_name fuzzcheck] $lFuzzDb]
|
||||
if {[lsearch $sanBuilds $buildname]>=0} {
|
||||
lappend lRet [trd_get_bin_name fuzzcheck-asan] $lFuzzDb
|
||||
if {$::tcl_platform(os) ne "OpenBSD"} {
|
||||
lappend lRet [trd_get_bin_name fuzzcheck-ubsan] $lFuzzDb
|
||||
}
|
||||
}
|
||||
lappend lRet {sessionfuzz run} $lSessionDb
|
||||
return $lRet
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -401,4 +401,25 @@ do_test vacuum-10.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
|
||||
|
||||
@@ -90,6 +90,8 @@ tvfs delete
|
||||
# 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);
|
||||
|
||||
@@ -0,0 +1,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
|
||||
|
||||
@@ -0,0 +1,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
|
||||
|
||||
+5
-5
@@ -2023,10 +2023,10 @@ static char *msort(
|
||||
list = NEXT(list);
|
||||
NEXT(ep) = 0;
|
||||
for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
|
||||
ep = merge(ep,set[i],cmp,offset);
|
||||
ep = merge(set[i],ep,cmp,offset);
|
||||
set[i] = 0;
|
||||
}
|
||||
set[i] = ep;
|
||||
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);
|
||||
@@ -4035,10 +4035,10 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
|
||||
}
|
||||
}
|
||||
if( lhsdirect ){
|
||||
sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
|
||||
lemon_sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
|
||||
}else{
|
||||
rc = 1;
|
||||
sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
|
||||
lemon_sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
|
||||
}
|
||||
|
||||
append_str(0,0,0,0);
|
||||
@@ -5925,7 +5925,7 @@ struct state **State_arrayof(void)
|
||||
PRIVATE unsigned confighash(struct config *a)
|
||||
{
|
||||
unsigned h=0;
|
||||
h = h*571 + a->rp->index*37 + a->dot;
|
||||
h = a->rp->index*37 + a->dot;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ while {1} {
|
||||
if {[regexp {^# *include "sqlite} $lx]} {
|
||||
set lx "/* $lx */"
|
||||
}
|
||||
if {[regexp {^# *include "test_windirent.h"} $lx]} {
|
||||
if {[regexp {^# *include "windirent.h"} $lx]} {
|
||||
set lx "/* $lx */"
|
||||
}
|
||||
set lx [string map [list __declspec(dllexport) {}] $lx]
|
||||
|
||||
@@ -56,7 +56,7 @@ proc write_one_file {content} {
|
||||
set label $filecnt
|
||||
}
|
||||
set out [open sqlite3-$label.c w]
|
||||
fconfigure $out -translation lf
|
||||
fconfigure $out -translation text
|
||||
puts -nonewline $out $content
|
||||
close $out
|
||||
puts $::out1 "#include \"sqlite3-$filecnt.c\""
|
||||
|
||||
@@ -1538,7 +1538,7 @@ static void originSide(SQLiteRsync *p){
|
||||
sqlite3_finalize(pInsHash);
|
||||
pCkHash = 0;
|
||||
pInsHash = 0;
|
||||
if( mxHash<p->nPage ){
|
||||
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",
|
||||
@@ -1797,6 +1797,7 @@ static void replicaSide(SQLiteRsync *p){
|
||||
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;
|
||||
|
||||
+1
-1
@@ -752,7 +752,7 @@ void sha1sum_file(const char *zFilename, char *zCksum){
|
||||
SHA1Final(zResult, &ctx);
|
||||
DigestToBase16(zResult, zCksum, 20);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Decode a fossilized string in-place.
|
||||
*/
|
||||
|
||||
+9
-9
@@ -10,7 +10,7 @@ if uname | grep -i openbsd ; then
|
||||
WARNING_ANDROID_OPTS=-Wall
|
||||
else
|
||||
# Use these for testing on Linux and Mac OSX:
|
||||
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
|
||||
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -Wno-array-bounds"
|
||||
gccvers=`gcc -v 2>&1 | grep '^gcc version'`
|
||||
if test "$gccvers" '<' 'gcc version 6'
|
||||
then
|
||||
@@ -22,15 +22,15 @@ fi
|
||||
|
||||
rm -f sqlite3.c
|
||||
make sqlite3.c
|
||||
echo '********** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
echo '**** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
|
||||
echo '****' $WARNING_OPTS
|
||||
gcc -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
|
||||
-DSQLITE_ENABLE_FTS5 \
|
||||
sqlite3.c
|
||||
if test x`uname` = 'xLinux'; then
|
||||
echo '********** Android configuration ******************************'
|
||||
echo '********** ' Options: $WARNING_ANDROID_OPTS
|
||||
echo '**** Android configuration ******************************'
|
||||
echo '****' $WARNING_ANDROID_OPTS
|
||||
gcc -c \
|
||||
-DSQLITE_HAVE_ISNAN \
|
||||
-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
|
||||
@@ -52,13 +52,13 @@ gcc -c \
|
||||
$WARNING_ANDROID_OPTS \
|
||||
-Os sqlite3.c shell.c
|
||||
fi
|
||||
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
echo '**** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
|
||||
echo '****' $WARNING_OPTS
|
||||
gcc -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
|
||||
sqlite3.c
|
||||
echo '********** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******'
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
echo '**** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******'
|
||||
echo '****' $WARNING_OPTS
|
||||
gcc -O3 -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
|
||||
-DSQLITE_ENABLE_FTS5 \
|
||||
|
||||
Reference in New Issue
Block a user