Compare commits

...

51 Commits

Author SHA1 Message Date
drh 280559b446 For all binary operators, try to avoid computing subquery operands if the
other operand is NULL.

FossilOrigin-Name: d86eb16283c4b573c506d4faa422d5d9aeb6abc279d8e6a8e2104737162d417f
2025-06-30 12:14:47 +00:00
drh e2e81e6983 Slightly smaller and faster version of the previous check-in.
FossilOrigin-Name: f6e6fd02f4ad49c390a2d3c9626d57f9b2fff1f67eb361b30074cc1f5121810e
2025-06-30 11:04:55 +00:00
drh e24f20a4f5 Factor out the code that tries to avoid evaluating subquery operands if the
other operand is NULL into a subroutine, so that it can be more easily reused
by other parts of the code generator.

FossilOrigin-Name: 3c6c71bcea16443b82234414137dfa1b59e2ee8fe5097906c738fc1228fec4e6
2025-06-30 10:30:47 +00:00
drh 311d73efc2 Improve the bytecode generated for comparisons so that if one operand is
a subquery and the other operand evaluates to NULL, the subquery operand
is not even computed.  This fixes 5 of the 12 slow queries described
in [forum:/forumpost/52651713ac|forum post 52651713ac].

FossilOrigin-Name: f147bc04776ac0056412f69dfc518016c0d5b4e9d964664e3d88f595fb29dbe0
2025-06-28 17:59:15 +00:00
drh c52e9d97d4 Raise an error right away if the number of aggregate terms in a query
exceeds the maximum number of columns.

FossilOrigin-Name: 5508b56fd24016c13981ec280ecdd833007c9d8dd595edb295b984c2b487b5c8
2025-06-27 19:02:21 +00:00
stephan fbf1c0526e API doc typo fixes and closing DD element tags from brickviking.
FossilOrigin-Name: c9ddd15b0197e6e5c5a74581d94cf986523514ffdb28c66ba18de9a22aec97e9
2025-06-27 12:46:50 +00:00
drh e77e589a35 Work around an apparent GCC UBSAN bug. See
[forum:/forumpost/1d7c25d4a2d6f5e2|forum thread 1d7c25d4a2d] for details.

FossilOrigin-Name: 23056532e51abcff486e38a3319545e6663b4a855abe1bc443e2cd7e0473748c
2025-06-26 18:57:20 +00:00
stephan 981022b7ff Minor API doc fixes sent off-list from brickviking.
FossilOrigin-Name: cb4d05633a0c9cdf146f3108e1b4b10754cd79d72a425d8cc9cd21836037a01b
2025-06-25 20:42:40 +00:00
drh a67c71224f Similar fix to the previous check-in, but this time for
sqlite3_preupdate_new().

FossilOrigin-Name: 9aaff764d508cbd9823f23cdf0c510255721bc5c09be481ebc60bd8902ceb8c5
2025-06-24 18:27:59 +00:00
drh 66cd200ede Range check the column index on the sqlite3_preupdate_old() interface
and return SQLITE_MISUSE if too large.
[forum:/forumpost/b617e497287235d0|Forum post b617e49728].

FossilOrigin-Name: 6a5701e6c7be25cba93e55438f950966e1dacb32eb2b23a8acc8ac53da6f0a85
2025-06-24 15:58:32 +00:00
stephan 513fff88c4 API doc typo fixes and one rephrasing improvement from brickviking.
FossilOrigin-Name: 85e8060c4701a601d4bc8a639acd268ee4f2736193820d55ecd9b8abf864132f
2025-06-24 07:38:52 +00:00
dan fe182f74b2 Improve some of the error messages emitted by fts5 when it encounters corruption.
FossilOrigin-Name: 48044a6b57c0a16cb75139c103ad88ca4ab64d74f70a3dee0d8b817fbfbec3c6
2025-06-23 19:38:22 +00:00
drh b1560be826 Fix an SQL typo introduced by the previous check-in.
FossilOrigin-Name: 72a81d247bc74a21d077d311969ac585d0f26bffbd210ec60f03c38bf138790e
2025-06-23 19:00:30 +00:00
drh 28789029ee Escape the "_" character in LIKE patterns in the CLI.
[forum:/forumpost/6a89702f5d|Forum post 6a89702f5d].

FossilOrigin-Name: cf61cd359e666c66b6bba4407a653c799f7f07e1f5ee6b837ad467029c461a6a
2025-06-23 16:51:33 +00:00
drh f453e8d84e Fix a harmless compiler warning injected by [c978aed3b6f82b3d].
FossilOrigin-Name: f46500247b3a2f8b4a2f0f032cc4066af9cb3918e38a09c59db0a1da5747a25c
2025-06-23 13:42:59 +00:00
drh 4c1c400d64 Improved "statement aborts at ..." log-file messages that identify the
trigger that caused the abort.

FossilOrigin-Name: 7691264fe37300c880d612c91cf093327841fbe85fb7ec67e777e911d2cfc9ee
2025-06-23 13:28:13 +00:00
stephan 87c807c6dd Add the --disable-rpath configure script flag to address [forum:13cac3b56516f849 | forum post 13cac3b56516f849].
FossilOrigin-Name: a59d9bb25e518f5d79f654615b92f6c50cfb704b5abee0f820912644b89366c5
2025-06-22 22:48:11 +00:00
stephan b5aa9593ac API doc typo fixes from brickviking.
FossilOrigin-Name: 18e07f8f53693d0dace3c4025a572c1a10582290a338aa7f0913c83842a69b05
2025-06-22 12:04:47 +00:00
stephan 5806a922ba Minor JS test cleanups prompted by a linter.
FossilOrigin-Name: 764235a3d15fda55af85ebe3b5885fa27336cc0e979f1be2f6770b66a84bbe87
2025-06-21 16:33:05 +00:00
stephan 427d2cd57d Remove some duplicated JS tests.
FossilOrigin-Name: d1cb9ed79d806f667c22f5ba9861451d4d0765aa3072e085831045cf3a39f8b4
2025-06-21 16:18:23 +00:00
stephan db37e6097c Reduce the maximum --size flag for JS kvvfs speedtest1 from 4 to 2, as --size 3 and 4 are overflowing the kvvfs storage limits.
FossilOrigin-Name: b77b3adc828ce543e880e230701edd5e0ccb681e4c3c724ea8ad5ecbd69c73a6
2025-06-21 16:02:20 +00:00
stephan 6fcb7f22a1 Give oo1.Stmt.get() similar treatment to [8c187140a60b]. This is an internal change only - the API is unaffected.
FossilOrigin-Name: f5a7abc0a447273de40dacc463d267d26d4b62be56ee15baf05825791c2a7a6e
2025-06-21 15:58:20 +00:00
stephan 2f7f948fa7 Extend the SEE-via-kvvfs tests to include all three key types.
FossilOrigin-Name: fc001aa5ee978795c2ff670bea64db0b69b6bde98653769d9cede8825a28e698
2025-06-21 15:38:59 +00:00
stephan 0cdde5b44f Rework how JS's oo1.DB.exec() flags its Stmt objects to make certain Stmt APIs illegal (i.e. throwing) if called while that Stmt is being step()ped by DB.exec() (which can happen via client-provided per-result-row callbacks). This is an internal change only - the API is unaffected. Remove some unrelated dead code.
FossilOrigin-Name: 8c187140a60b62dc3b6066b8615766d52b7a29a5de992cbb6d312dbb225a980b
2025-06-21 14:38:53 +00:00
stephan a0c6de56ba Numerous small doc typo from BrickViking.
FossilOrigin-Name: 3aab4415de615c178205936372c625bb571bad1016c3d2e7bb2a45932356f3d6
2025-06-21 06:07:13 +00:00
drh b68d63158a Enhance sqlite3BtreeSetPageSize() so that it detects early if no changes
are needed and exists with SQLITE_OK.

FossilOrigin-Name: c978aed3b6f82b3d9d2e0ca0283c611351bca5e5496e86a9d5d0731ebcd27c84
2025-06-20 13:12:55 +00:00
drh 59de42763f Fix an out-of-order local variable declaration in ext/misc/fileio.c.
FossilOrigin-Name: a88bb75288a06492a04ab1278e8a2101a74f4ba712d328b4c73e86ac01cb946d
2025-06-19 20:19:12 +00:00
drh 37794b4ad0 Improve the accuracy of sqlite3BtreeRowCountEst().
FossilOrigin-Name: e553fb538ec1527457e2927edf9127dccf268a8a3b5918d4fb0d066ad9676094
2025-06-19 20:00:37 +00:00
drh 397b82cf0f Generalize the indexCellCompare() so that works on any index page, not just
the current page that a cursor is pointing to.

FossilOrigin-Name: b305a7f5db183d8e0e5d62ca3c9c6260ad94bb954f7342bd3caabcd8308a21f5
2025-06-19 19:33:06 +00:00
stephan 92d1bec584 A slight doc rephrasing for clarity, suggested in the forum.
FossilOrigin-Name: 0d6084a398edb013fcfb613eff8d75e2f86cbb5e3c8049328ede89e75db93cb3
2025-06-19 12:35:30 +00:00
stephan a5c484b432 Doc typo fixes from [forum:0bce273669 | forum post 0bce273669].
FossilOrigin-Name: 8f97e3f00d24b26fe87a9d3396ad855277a1a369f6f89e9c77dc9af4d203bdf1
2025-06-19 10:46:39 +00:00
stephan 64159096b8 Expose the column metadata APIs to WASM (which does not require a non-default sqlite3.c build, contrary to my prior mistaken claims). This adds only 424 bytes to sqlite3.wasm and 660 bytes to sqlite3.js.
FossilOrigin-Name: 3cf983816ccd167d93cb39c7a16b6db4b4f7ef2a64f4181d3bc4530cd0bd3b67
2025-06-19 10:25:50 +00:00
drh ab9c91ae82 Extend the pedantic enforcement of type to VIRTUAL columns.
FossilOrigin-Name: b734c74e55acb26eb61b60937bef870f4b55b2e2e7560a22362f5f31ba2fcd03
2025-06-18 19:04:28 +00:00
drh bcf25e7129 Enforce judgmental typing on STORED generated columns for STRICT
tables.  [forum:/forumpost/6caf195248a849e4|Forum post 6caf195248].

FossilOrigin-Name: 5e9279bff0482806f86657ae05ca3e916708d138bc3c3ceb3fbf454818649d44
2025-06-18 16:17:00 +00:00
stephan 2be0a700ff Export the column-metadata APIs to WASM. Doing so requires a non-default build of sqlite3.c, so this is a proof-of-concept branch saved just in case SQLITE_ENABLE_COLUMN_METADATA ever becomes the default for sqlite3.c.
FossilOrigin-Name: 59db3f639d1073678805dea26a4686eddfb238f055aa90bd429fc7fd33241502
2025-06-18 15:37:04 +00:00
stephan 3a26f72e20 Add the --enable-column-metadata flag to the configure script (off by default). It's only available in the canonical build, not the autoconf build, because it changes how sqlite3.c gets generated.
FossilOrigin-Name: 986b601db11a041d280eb61004723604bf4b6fd573b9832c97e3a9da9ea16e9a
2025-06-18 15:22:50 +00:00
stephan d961d49971 Eliminate configure/build discrepancies in how 'make tclextension-...' works vs other makefile-side handling of the extension, conforming to the former.
FossilOrigin-Name: 7ca545fd3b460fcf92e117baef42655eb6e78ebb5bdc6302f8f1b5b8446c0a06
2025-06-18 14:17:18 +00:00
drh 9a9140ba59 Change the definition of SQLITE_DYNAMIC to a function that has exactly
the same type as sqlite3_destructor_type, in an effort to work around
possible legacy compiler bugs.

FossilOrigin-Name: 83553edf78c35d171a0ddf1a51306e963d715e56d95b8159b561b729cfb27843
2025-06-18 14:14:46 +00:00
stephan 12bd8ea09a Add the --tclConfig.sh FILE flag to buildtclext.tcl to eliminate the discrepancy between the configure-time-detected tclConfig.sh and the one auto-detected by the tclextension family of makefile targets. Add the tclextension-all target to run all of the various tclextension-... targets in their natural order to facilitate testing changes like this one. Update the --help text to note that --with-tclsh should only be used if there's a specific need, and that --with-tcl is generall preferred. This is in response to [https://github.com/termux/termux-packages/issues/23268 | Termux ticket 23268].
FossilOrigin-Name: 928976abcb11f9d5abe1f7631002592c4af7bf83ecadba5b0763866d039c2270
2025-06-18 11:11:30 +00:00
stephan 1e9baaf743 tea: remove the vsatisfies 8.6- enforcement from the extension because at least one platform with tcl 8.6 is inexplicably failing it. [forum:fde857fb8101a4be | Forum post fde857fb8101a4be]
FossilOrigin-Name: 7331e32a76a8a41cc1bd1c84069219c9929e0e0f941c1d9e308cbbb7959373c5
2025-06-17 20:50:51 +00:00
drh df8aa3745a Avoid writing frames with no checksums into the wal file if a
savepoint is rolled back after dirty pages have already been
spilled into the wal file.

FossilOrigin-Name: 5973f9b9aa828ec9274b02a124b95f452c58235eaafffbdda1c32b4ae2d5616d
2025-06-17 19:10:33 +00:00
drh 110055cd6c Fix a corner-case for [9441fff52cc4e19c].
FossilOrigin-Name: 336a59eb3afd80ce048de472368df6dfc32934ee783859d37663ed8f5cf169a5
2025-06-17 18:57:07 +00:00
dan 79a746b1f2 Update walcksum.test so that it works with SQLITE_DEFAULT_AUTOVACUUM=1 builds.
FossilOrigin-Name: 0da16f6c625bff9f2ca5624afa6dce6b5a157f44c1d56b25b92946c13217ab02
2025-06-17 18:17:09 +00:00
stephan 9ebf9d358b Extend [b5c6cb13cff5] to use a wildcard on darwin* because some OSes report a version number in the suffix. [forum:0c4bbc2962dfb06e | Forum post 0c4bbc2962dfb06e].
FossilOrigin-Name: d960bd6f9256410ebc98125b0567380457e39bc8fe768fcd9ea05c6de1994df6
2025-06-17 17:15:12 +00:00
stephan e68aa0e44b Minor proj.tcl portability fixes and cleanups suggested in [forum:7b218c3c9f|forum post 7b218c3c9f]. Tested on Linux, Msys, Cygwin, and Haiku.
FossilOrigin-Name: b5c6cb13cff53f4ba1e0e6a0d61389252bd004d9099727e7a9304217e3f81d80
2025-06-17 14:56:30 +00:00
stephan 6e1c2f0483 proj.tcl portability fixes and cleanups suggested in [forum:7b218c3c9f|forum post 7b218c3c9f]. Branching so that it can be tested on msys/cygwin/haiku before committing to it.
FossilOrigin-Name: 89552e9137b7ebba9600443720e936e8dc4f7ab021d2ac3f0bb01b74071e130c
2025-06-17 14:37:31 +00:00
dan 1ea6a53762 Avoid writing frames with no checksums into the wal file if a savepoint is rolled back after dirty pages have already been spilled into the wal file. Possible fix for [forum:/forumpost/b490f726db | forum post b490f726db].
FossilOrigin-Name: 3a3269fe8e925a522d5df9f011220a842fb15a9f56e785884e32d2e15abda5bb
2025-06-17 11:36:39 +00:00
drh 86d9c2d9f3 Fix an issue going back to version 3.39.0 with transitive IS constraints
in queries that make use of RIGHT JOIN.  Problem reported by
[forum:/forumpost/68f29a2005|forum post 68f29a2005].

FossilOrigin-Name: 9441fff52cc4e19c44df1a77ffe474f409d519b270c7166ce17f99e6ea48fc1e
2025-06-16 17:36:11 +00:00
drh d3a13f7d25 Improved debugging output for the transitive constraint optimization.
FossilOrigin-Name: 94b53c20e9bc8687c44272419aa7a93076eebdeae9a4f50b95b96a49993f9c0d
2025-06-16 16:07:14 +00:00
drh 6ed5aa4b9b Make the show-%p-az-zero hack of the previous check-in configurable at
run-time using the 0x100000 bit of either .treetrace or .wheretrace.
As before, this is all a no-op except for debugging builds.

FossilOrigin-Name: a29627d7e7f8344d9a099cc133bda85250b02dc5ee5f358ba59691e0816b5b2d
2025-06-16 15:34:26 +00:00
drh 67f708298f Add an "#if 0" that can be changed to "1" to cause all %p output to render
as 0, thus making comparisons of .treetrace and .wheretrace output easier.

FossilOrigin-Name: 65e2704c0bc329f3dd248548a2d4edb7d3ace8ceaf0b82b8618b9b1b764884cd
2025-06-16 13:51:09 +00:00
44 changed files with 1281 additions and 517 deletions
+7
View File
@@ -213,6 +213,13 @@ TCL_CONFIG_SH = @TCL_CONFIG_SH@
#TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
#TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
#TCL_VERSION = @TCL_VERSION@
TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@
# ^^^ main.mk optionally uses this for determining the Tcl extension's
# DLL name.
TCL_EXT_DLL_BASENAME = @TCL_EXT_DLL_BASENAME@
# ^^^ base name of the Tcl extension DLL. It varies by platform and
# Tcl version.
#
# $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it
# is calculated at make-time by the targets which need it but we
+6 -1
View File
@@ -64,13 +64,18 @@ apply {{dir} {
-name.pkg sqlite3
-version $version
-name.dist $distname
-vsatisfies 8.6-
-libDir sqlite$version
-pragmas $pragmas
-src generic/tclsqlite3.c
}
# We should also have:
# -vsatisfies 8.6-
# But at least one platform is failing this vsatisfies check
# for no apparent reason:
# https://sqlite.org/forum/forumpost/fde857fb8101a4be
}} [teaish-get -dir]
#
# Must return either an empty string or a list in the form accepted by
# autosetup's [options] function.
+30 -37
View File
@@ -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]
@@ -2189,11 +2187,7 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
upvar $argvName argv
upvar $tgtArrayName outFlags
array set flags {}; # staging area
array set scripts {}; # map of -flag=>script
array set consuming {}; # map of -flag=>1 for arg-consuming flags
array set multi {}; # map of -flag=>1 for multi-time flags
array set seen {}; # map of -flag=>number of times seen
array set call {}; # map of -flag=>1 for -call entries
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]
@@ -2201,8 +2195,8 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
#puts "**** checkProtoFlag #$i of $n k=$k fv=$fv"
switch -exact -- $fv {
-literal {
proj-assert {![info exists consuming($k)]}
set scripts($k) [list expr [lindex $prototype [incr i]]]
proj-assert {![info exists blob(${k}.consumes)]}
set blob(${k}.script) [list expr [lindex $prototype [incr i]]]
}
-apply {
set fv [lindex $prototype [incr i]]
@@ -2210,16 +2204,16 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
# Treat this as a lambda literal
set fv [list $fv]
}
lappend call($k) "apply $fv"
lappend blob(${k}.call) "apply $fv"
}
-call {
# arg is either a proc name or {apply $aLambda}
set fv [lindex $prototype [incr i]]
lappend call($k) $fv
lappend blob(${k}.call) $fv
}
default {
proj-assert {![info exists consuming($k)]}
set scripts($k) $fv
proj-assert {![info exists blob(${k}.consumes)]}
set blob(${k}.script) $fv
}
}
if {$i >= $n} {
@@ -2244,7 +2238,7 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
if {[string match {*\*} $k]} {
# Re-map -foo* to -foo and flag -foo as a repeatable flag
set k [string map {* ""} $k]
incr multi($k)
incr blob(${k}.multi)
}
if {[info exists flags($k)]} {
@@ -2258,7 +2252,7 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
if {$i >= $n} {
proj-error -up "[proj-scope]: Missing argument for $k => flag"
}
incr consuming($k)
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"
@@ -2281,10 +2275,9 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
set flags($k) $vi
}
#puts "-- flags"; parray flags
#puts "-- scripts"; parray scripts
#puts "-- calls"; parray call
#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...
@@ -2295,36 +2288,36 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
lappend rv $arg
} elseif {"--" eq $arg} {
# "--" is the conventional way to end processing of args
if {[incr seen(--)] > 1} {
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 multi($arg)]
incr seen($arg)
if {1 < $seen($arg) && !$isMulti} {
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 consuming($arg)]
set isConsuming [info exists blob(${arg}.consumes)]
if {$isConsuming} {
incr i
if {$i >= $n} {
proj-error -up [proj-scope] "is missing argument for $arg flag"
}
set vv [lindex $argv $i]
} elseif {[info exists scripts($arg)]} {
} elseif {[info exists blob(${arg}.script)]} {
set vMode 1
set vv $scripts($arg)
set vv $blob(${arg}.script)
} else {
set vv $flags($arg)
}
if {[info exists call($arg)]} {
if {[info exists blob(${arg}.call)]} {
set vMode 2
set vv [concat {*}$call($arg) $arg $vv]
set vv [concat {*}$blob(${arg}.call) $arg $vv]
} elseif {$isConsuming} {
proj-assert {!$vMode}
# fall through
@@ -2351,7 +2344,7 @@ proc proj-parse-flags {argvName tgtArrayName prototype} {
}
}
if {$isConsuming && $isMulti} {
if {1 == $seen($arg)} {
if {1 == $blob(${arg}.seen)} {
# On the first hit, overwrite the default with a new list.
set flags($arg) [list $vv]
} else {
+40 -19
View File
@@ -217,6 +217,11 @@ proc sqlite-configure {buildMode configScript} {
=> {This legacy flag has no effect on the library but may influence
the generated sqlite_cfg.h by adding #define HAVE_LFS}
}
{canonical} {
column-metadata => {Enable the column metadata APIs}
# ^^^ Affects how sqlite3.c is generated, so is not available in
# the autoconf build.
}
}
# Options for TCL support
@@ -227,8 +232,6 @@ proc sqlite-configure {buildMode configScript} {
This tree requires TCL for code generation but can use the in-tree
copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the
test code require a canonical tclsh.}
}
{canonical} {
with-tcl:DIR
=> {Directory containing tclConfig.sh or a directory one level up from
that, from which we can derive a directory containing tclConfig.sh.
@@ -236,11 +239,10 @@ proc sqlite-configure {buildMode configScript} {
the --prefix flag.}
with-tclsh:PATH
=> {Full pathname of tclsh to use. It is used for (A) trying to find
tclConfig.sh and (B) all TCL-based code generation. Warning: if
its containing dir has multiple tclsh versions, it may select the
tclConfig.sh and (B) all TCL-based code generation. Use --with-tcl
unless you have a specific need for this flag. Warning: if its
containing dir has multiple tclsh versions, it may select the
wrong tclConfig.sh!}
}
{canonical} {
static-tclsqlite3=0
=> {Statically-link tclsqlite3. This only works if TCL support is
enabled and all requisite libraries are available in
@@ -334,8 +336,8 @@ proc sqlite-configure {buildMode configScript} {
=> {Link the sqlite3 shell app against the DLL instead of embedding sqlite3.c}
}
{canonical autoconf} {
# A potential TODO without a current use case:
#rpath=1 => {Disable use of the rpath linker flag}
rpath=1 => {Disable use of the rpath linker flag}
# soname: https://sqlite.org/src/forumpost/5a3b44f510df8ded
soname:=legacy
=> {SONAME for libsqlite3.so. "none", or not using this flag, sets no
@@ -772,7 +774,8 @@ proc sqlite-handle-common-feature-flags {} {
sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3
}
}
scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
column-metadata -DSQLITE_ENABLE_COLUMN_METADATA {}
}] {
if {$boolFlag ni $::autosetup(options)} {
# Skip flags which are in the canonical build but not
@@ -1969,13 +1972,14 @@ proc sqlite-check-tcl {} {
# TCLLIBDIR from here, which will cause the canonical makefile to
# use this one rather than to re-calculate it at make-time.
set tcllibdir [get-env TCLLIBDIR ""]
set sq3Ver [get-define PACKAGE_VERSION]
if {"" eq $tcllibdir} {
# Attempt to extract TCLLIBDIR from TCL's $auto_path
if {"" ne $with_tclsh &&
[catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
foreach i $result {
if {[file isdir $i]} {
set tcllibdir $i/sqlite3
set tcllibdir $i/sqlite${sq3Ver}
break
}
}
@@ -2111,15 +2115,31 @@ proc sqlite-determine-codegen-tcl {} {
# sqlite-determine-codegen-tcl.
proc sqlite-handle-tcl {} {
sqlite-check-tcl
if {"canonical" eq $::sqliteConfig(build-mode)} {
msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
if {"canonical" ne $::sqliteConfig(build-mode)} return
msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
# Determine the base name of the Tcl extension's DLL
#
if {[get-define HAVE_TCL]} {
if {[string match *-cygwin [get-define host]]} {
set libname cyg
} else {
set libname lib
}
if {[get-define TCL_MAJOR_VERSION] > 8} {
append libname tcl9
}
append libname sqlite
} else {
set libname ""
}
define TCL_EXT_DLL_BASENAME $libname
# The extension is added in the makefile
}
########################################################################
# Handle the --enable/disable-rpath flag.
proc sqlite-handle-rpath {} {
proj-check-rpath
# autosetup/cc-shared.tcl sets the rpath flag definition in
# [get-define SH_LINKRPATH], but it does so on a per-platform basis
# rather than as a compiler check. Though we should do a proper
@@ -2128,12 +2148,13 @@ proc sqlite-handle-rpath {} {
# for which sqlite-env-is-unix-on-windows returns a non-empty
# string.
# if {[proj-opt-truthy rpath]} {
# proj-check-rpath
# } else {
# msg-result "Disabling use of rpath."
# define LDFLAGS_RPATH ""
# }
# https://sqlite.org/forum/forumpost/13cac3b56516f849
if {[proj-opt-truthy rpath]} {
proj-check-rpath
} else {
msg-result "Disabling use of rpath."
define LDFLAGS_RPATH ""
}
}
########################################################################
+82 -38
View File
@@ -554,6 +554,36 @@ struct Fts5SegIter {
u8 bDel; /* True if the delete flag is set */
};
static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){
pIdx->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
"fts5: corruption found reading blob %lld from table \"%s\"",
iRowid, pIdx->pConfig->zName
);
return SQLITE_CORRUPT_VTAB;
}
#define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid)
static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){
pIdx->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
"fts5: corruption on page %d, segment %d, table \"%s\"",
pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName
);
return SQLITE_CORRUPT_VTAB;
}
#define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter)
static int fts5IndexCorruptIdx(Fts5Index *pIdx){
pIdx->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
"fts5: corruption in table \"%s\"", pIdx->pConfig->zName
);
return SQLITE_CORRUPT_VTAB;
}
#define FTS5_CORRUPT_IDX(pIdx) fts5IndexCorruptIdx(pIdx)
/*
** Array of tombstone pages. Reference counted.
*/
@@ -843,7 +873,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
** All the reasons those functions might return SQLITE_ERROR - missing
** table, missing row, non-blob/text in block column - indicate
** backing store corruption. */
if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;
if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT_ROWID(p, iRowid);
if( rc==SQLITE_OK ){
u8 *aOut = 0; /* Read blob data into this buffer */
@@ -893,7 +923,7 @@ static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
Fts5Data *pRet = fts5DataRead(p, iRowid);
if( pRet ){
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
fts5DataRelease(pRet);
pRet = 0;
}
@@ -1252,8 +1282,14 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){
/* TODO: Do we need this if the leaf-index is appended? Probably... */
memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
if( p->rc==SQLITE_OK ){
if( (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
}
}else if( p->rc==SQLITE_CORRUPT_VTAB ){
sqlite3Fts5ConfigErrmsg(p->pConfig,
"fts5: corrupt structure record for table \"%s\"", p->pConfig->zName
);
}
fts5DataRelease(pData);
if( p->rc!=SQLITE_OK ){
@@ -1876,7 +1912,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
while( iOff>=pIter->pLeaf->szLeaf ){
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf==0 ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
if( p->rc==SQLITE_OK ) FTS5_CORRUPT_ITER(p, pIter);
return;
}
iOff = 4;
@@ -1908,7 +1944,7 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
iOff += fts5GetVarint32(&a[iOff], nNew);
if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
pIter->term.n = nKeep;
@@ -2103,7 +2139,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
iRowidOff = fts5LeafFirstRowidOff(pNew);
if( iRowidOff ){
if( iRowidOff>=pNew->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
}else{
pIter->pLeaf = pNew;
pIter->iLeafOffset = iRowidOff;
@@ -2337,7 +2373,7 @@ static void fts5SegIterNext(
}
assert_nc( iOff<pLeaf->szLeaf );
if( iOff>pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
}
@@ -2447,7 +2483,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
pIter->iLeafPgno = pgnoLast;
iOff = fts5LeafFirstRowidOff(pLast);
if( iOff>pLast->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
@@ -2526,7 +2562,7 @@ static void fts5LeafSeek(
iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
iOff = iTermOff;
if( iOff>n ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
@@ -2569,7 +2605,7 @@ static void fts5LeafSeek(
iOff = iTermOff;
if( iOff>=n ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
@@ -2591,7 +2627,7 @@ static void fts5LeafSeek(
iPgidx = (u32)pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}else{
nKeep = 0;
@@ -2606,7 +2642,7 @@ static void fts5LeafSeek(
search_success:
if( (i64)iOff+nNew>n || nNew<1 ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ITER(p, pIter);
return;
}
pIter->iLeafOffset = iOff + nNew;
@@ -3071,7 +3107,7 @@ static void fts5SegIterGotoPage(
assert( iLeafPgno>pIter->iLeafPgno );
if( iLeafPgno>pIter->pSeg->pgnoLast ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
}else{
fts5DataRelease(pIter->pNextLeaf);
pIter->pNextLeaf = 0;
@@ -3086,7 +3122,7 @@ static void fts5SegIterGotoPage(
u8 *a = pIter->pLeaf->p;
int n = pIter->pLeaf->szLeaf;
if( iOff<4 || iOff>=n ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
}else{
iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
pIter->iLeafOffset = iOff;
@@ -3565,7 +3601,7 @@ static void fts5ChunkIterate(
if( nRem<=0 ){
break;
}else if( pSeg->pSeg==0 ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
return;
}else{
pgno++;
@@ -4668,7 +4704,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
** a single page has been assigned to more than one segment. In
** this case a prior iteration of this loop may have corrupted the
** segment currently being trimmed. */
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iLeafRowid);
}else{
fts5BufferZero(&buf);
fts5BufferGrow(&p->rc, &buf, pData->nn);
@@ -5135,7 +5171,7 @@ static void fts5SecureDeleteOverflow(
}else if( bDetailNone ){
break;
}else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
break;
}else{
int nShift = iNext - 4;
@@ -5155,7 +5191,7 @@ static void fts5SecureDeleteOverflow(
i1 += fts5GetVarint32(&aPg[i1], iFirst);
if( iFirst<iNext ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
break;
}
aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2);
@@ -5378,14 +5414,14 @@ static void fts5DoSecureDelete(
nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
}else{
if( iKey!=1 ){
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
}
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
if( nPrefix2>pSeg->term.n ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
}else if( nPrefix2>nPrefix ){
memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
iOff += (nPrefix2-nPrefix);
@@ -6178,7 +6214,7 @@ static void fts5MergePrefixLists(
}
if( pHead==0 || pHead->pNext==0 ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_IDX(p);
break;
}
@@ -6215,7 +6251,7 @@ static void fts5MergePrefixLists(
assert_nc( tmp.n+nTail<=nTmp );
assert( tmp.n+nTail<=nTmp+nMerge*10 );
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
if( p->rc==SQLITE_OK ) FTS5_CORRUPT_IDX(p);
break;
}
fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
@@ -8344,14 +8380,17 @@ static void fts5IndexIntegrityCheckEmpty(
for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
if( pLeaf ){
if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT;
if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT;
if( !fts5LeafIsTermless(pLeaf)
|| (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf))
){
FTS5_CORRUPT_ROWID(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
}
}
fts5DataRelease(pLeaf);
}
}
static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){
i64 iTermOff = 0;
int ii;
@@ -8369,12 +8408,12 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
iOff = iTermOff;
if( iOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
}else if( iTermOff==nIncr ){
int nByte;
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
if( (iOff+nByte)>pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
}else{
fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
}
@@ -8383,7 +8422,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep);
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRowid);
}else{
buf1.n = nKeep;
fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
@@ -8391,7 +8430,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
if( p->rc==SQLITE_OK ){
res = fts5BufferCompare(&buf1, &buf2);
if( res<=0 ) p->rc = FTS5_CORRUPT;
if( res<=0 ) FTS5_CORRUPT_ROWID(p, iRowid);
}
}
fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p);
@@ -8452,7 +8491,7 @@ static void fts5IndexIntegrityCheckSegment(
** entry even if all the terms are removed from it by secure-delete
** operations. */
}else{
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRow);
}
}else{
@@ -8464,15 +8503,15 @@ static void fts5IndexIntegrityCheckSegment(
iOff = fts5LeafFirstTermOff(pLeaf);
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iRow);
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
if( res==0 ) res = nTerm - nIdxTerm;
if( res<0 ) p->rc = FTS5_CORRUPT;
if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
}
fts5IntegrityCheckPgidx(p, pLeaf);
fts5IntegrityCheckPgidx(p, iRow, pLeaf);
}
fts5DataRelease(pLeaf);
if( p->rc ) break;
@@ -8502,7 +8541,7 @@ static void fts5IndexIntegrityCheckSegment(
iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
pLeaf = fts5DataRead(p, iKey);
if( pLeaf ){
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT;
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey);
fts5DataRelease(pLeaf);
}
}
@@ -8517,12 +8556,12 @@ static void fts5IndexIntegrityCheckSegment(
int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
ASSERT_SZLEAF_OK(pLeaf);
if( iRowidOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iKey);
}else if( bSecureDelete==0 || iRowidOff>0 ){
i64 iDlRowid = fts5DlidxIterRowid(pDlidx);
fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){
p->rc = FTS5_CORRUPT;
FTS5_CORRUPT_ROWID(p, iKey);
}
}
fts5DataRelease(pLeaf);
@@ -8637,7 +8676,12 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
fts5MultiIterFree(pIter);
if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){
p->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(p->pConfig,
"fts5: checksum mismatch for table \"%s\"", p->pConfig->zName
);
}
fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
+2 -1
View File
@@ -3701,8 +3701,9 @@ static int fts5IntegrityMethod(
" FTS5 table %s.%s: %s",
zSchema, zTabname, sqlite3_errstr(rc));
}
}else if( (rc&0xff)==SQLITE_CORRUPT ){
rc = SQLITE_OK;
}
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
pTab->p.pConfig->pzErrmsg = 0;
+1 -1
View File
@@ -428,7 +428,7 @@ do_execsql_test 15.1 {
}
do_catchsql_test 15.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
} {1 {fts5: checksum mismatch for table "t1"}}
#-------------------------------------------------------------------------
#
+3 -4
View File
@@ -47,11 +47,10 @@ do_test 1.3 {
DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4);
}
catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
} {1 {database disk image is malformed}}
} {1 {fts5: corruption found reading blob 137438953476 from table "t1"}}
do_execsql_test 1.3b {
PRAGMA integrity_check(t1);
} {{malformed inverted index for FTS5 table main.t1}}
} {{fts5: corruption found reading blob 137438953476 from table "t1"}}
do_test 1.4 {
db_restore_and_reopen
@@ -61,7 +60,7 @@ do_test 1.4 {
rowid = fts5_rowid('segment', $segid, 4);
}
catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
} {1 {database disk image is malformed}}
} {1 {fts5: corruption found reading blob 137438953476 from table "t1"}}
db_restore_and_reopen
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
+6 -6
View File
@@ -109,12 +109,12 @@ for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
do_catchsql_test 2.$i.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
} {/1.*fts5: corruption.*/}
do_test 2.$i.3 {
set res [catchsql {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'}]
expr {
$res=="1 {database disk image is malformed}"
[string match {*fts5: corruption*} $res]
|| $res=="0 {$all}"
}
} 1
@@ -160,17 +160,17 @@ foreach {tn hdr} {
close $fd
set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}]
if {$res == "1 {database disk image is malformed}"} {incr nCorrupt}
if {[string match {*fts5: corruption*} $res]} {incr nCorrupt}
set {} 1
} {1}
if {($tn2 % 10)==0 && $existing != $hdr} {
do_test 3.$tn.$tn2.2 {
catchsql { INSERT INTO x3(x3) VALUES('integrity-check') }
} {1 {database disk image is malformed}}
} {/.*fts5: corruption.*/}
do_execsql_test 3.$tn.$tn2.3 {
PRAGMA integrity_check(x3);
} {{malformed inverted index for FTS5 table main.x3}}
} {/.*fts5: corruption.*/}
}
execsql ROLLBACK
@@ -209,7 +209,7 @@ foreach {tn nCut} {
set res [catchsql {
SELECT rowid FROM x4 WHERE x4 MATCH 'a' ORDER BY 1 DESC
}]
if {$res == "1 {database disk image is malformed}"} {incr nCorrupt}
if {[string match {*fts5: corruption*} $res]} {incr nCorrupt}
set {} 1
} {1}
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -237,7 +237,7 @@ do_test 1.0 {
do_catchsql_test 1.1 {
SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
#-------------------------------------------------------------------------
#
@@ -450,7 +450,7 @@ do_test 2.0 {
do_catchsql_test 2.1 {
SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
#-------------------------------------------------------------------------
reset_db
@@ -569,7 +569,7 @@ do_test 3.0 {
do_catchsql_test 3.1 {
UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T';
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
#-------------------------------------------------------------------------
reset_db
@@ -878,7 +878,7 @@ do_execsql_test 5.1 {
}
do_catchsql_test 5.4 {
UPDATE t1 SET content=randomblob(500);
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
#-------------------------------------------------------------------------
reset_db
+1 -1
View File
@@ -123,6 +123,6 @@ do_execsql_test 2.2 {
do_catchsql_test 2.3 {
DELETE FROM t1 WHERE rowid = 1
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
finish_test
+1 -1
View File
@@ -32,7 +32,7 @@ sqlite3 db test.db
do_catchsql_test 1.2 {
SELECT * FROM t1
} {1 {database disk image is malformed}}
} {1 {fts5: corrupt structure record for table "t1"}}
do_catchsql_test 1.3 {
DROP TABLE t1
} {0 {}}
+1 -1
View File
@@ -46,7 +46,7 @@ do_execsql_test 1.5 {
do_catchsql_test 1.6 {
INSERT INTO f1(f1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
} {/.*fts5: corrupt.*/}
do_execsql_test 1.7 {
INSERT INTO f1(f1) VALUES('rebuild');
+1 -1
View File
@@ -899,9 +899,9 @@ static int fsdirFilter(
){
const char *zDir = 0;
fsdir_cursor *pCur = (fsdir_cursor*)cur;
int i;
(void)idxStr;
fsdirResetCursor(pCur);
int i;
if( idxNum==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
+2 -1
View File
@@ -260,7 +260,8 @@ SQLITE_OPT.full-featured := \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_SESSION \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
-DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
-DSQLITE_ENABLE_COLUMN_METADATA
ifeq (0,$(wasm-bare-bones))
# The so-called canonical build is full-featured:
+17 -14
View File
@@ -1,12 +1,27 @@
_sqlite3_column_database_name
_sqlite3_column_origin_name
_sqlite3_column_table_name
_sqlite3_create_module
_sqlite3_create_module_v2
_sqlite3_create_window_function
_sqlite3_progress_handler
_sqlite3_set_authorizer
_sqlite3_declare_vtab
_sqlite3_drop_modules
_sqlite3_preupdate_blobwrite
_sqlite3_preupdate_count
_sqlite3_preupdate_depth
_sqlite3_preupdate_hook
_sqlite3_preupdate_new
_sqlite3_preupdate_old
_sqlite3_progress_handler
_sqlite3_set_authorizer
_sqlite3_vtab_collation
_sqlite3_vtab_distinct
_sqlite3_vtab_in
_sqlite3_vtab_in_first
_sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
_sqlite3changegroup_add
_sqlite3changegroup_add_strm
_sqlite3changegroup_delete
@@ -49,15 +64,3 @@ _sqlite3session_object_config
_sqlite3session_patchset
_sqlite3session_patchset_strm
_sqlite3session_table_filter
_sqlite3_create_module
_sqlite3_create_module_v2
_sqlite3_declare_vtab
_sqlite3_drop_modules
_sqlite3_vtab_collation
_sqlite3_vtab_distinct
_sqlite3_vtab_in
_sqlite3_vtab_in_first
_sqlite3_vtab_in_next
_sqlite3_vtab_nochange
_sqlite3_vtab_on_conflict
_sqlite3_vtab_rhs_value
+8 -1
View File
@@ -20,7 +20,6 @@
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'use strict';
const toss = (...args)=>{throw new Error(args.join(' '))};
const toss3 = sqlite3.SQLite3Error.toss;
const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
globalThis.WhWasmUtilInstaller(wasm);
delete globalThis.WhWasmUtilInstaller;
@@ -368,6 +367,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
);
}/* sqlite3_set_authorizer() */
if( !!wasm.exports.sqlite3_column_origin_name ){
wasm.bindingSignatures.push(
["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"],
["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"],
["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"]
);
}
if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
/* ^^^ "the problem" is that this is an optional feature and the
build-time function-export list does not currently take
+48 -23
View File
@@ -16,7 +16,6 @@
and it installs its deliverable as globalThis.sqlite3.oo1.
*/
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const toss = (...args)=>{throw new Error(args.join(' '))};
const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)};
const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
@@ -1061,18 +1060,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const cbArgCache = Object.create(null)
/* 2nd arg for arg.cbArg, used by (at least) row-to-object
converter */;
for(; stmt.step(); stmt._lockedByExec = false){
for( ; stmt.step(); __execLock.delete(stmt) ){
if(0===gotColNames++){
stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || []));
}
stmt._lockedByExec = true;
__execLock.add(stmt);
const row = arg.cbArg(stmt,cbArgCache);
if(resultRows) resultRows.push(row);
if(callback && false === callback.call(opt, row, stmt)){
break;
}
}
stmt._lockedByExec = false;
__execLock.delete(stmt);
}
if(0===gotColNames){
/* opt.columnNames was provided but we visited no result rows */
@@ -1094,7 +1093,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}*/finally{
wasm.scopedAllocPop(stack);
if(stmt){
delete stmt._lockedByExec;
__execLock.delete(stmt);
stmt.finalize();
}
}
@@ -1388,7 +1387,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/**
Starts a transaction, calls the given callback, and then either
rolls back or commits the savepoint, depending on whether the
rolls back or commits the transaction, depending on whether the
callback throws. The callback is passed this db object as its
only argument. On success, returns the result of the
callback. Throws on error.
@@ -1511,7 +1510,30 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
};
/**
If stmt._lockedByExec is truthy, this throws an exception
Each Stmt object which is "locked" by DB.exec() gets an entry
here to note that "lock".
The reason this is in place is because exec({callback:...})'s
callback gets access to the Stmt objects created internally by
exec() but it must not use certain Stmt APIs.
*/
const __execLock = new Set();
/**
This is a Stmt.get() counterpart of __execLock. Each time
Stmt.step() returns true, the statement is added to this set,
indicating that Stmt.get() is legal. Stmt APIs which invalidate
that status remove the Stmt object from this set, which will
cause Stmt.get() to throw with a descriptive error message
instead of a more generic "API misuse" if we were to allow that
call to reach the C API.
*/
const __stmtMayGet = new Set();
/**
Stmt APIs which are prohibited on locked objects must call
affirmNotLockedByExec() before doing any work.
If __execLock.has(stmt) is truthy, this throws an exception
complaining that the 2nd argument (an operation name,
e.g. "bind()") is not legal while the statement is "locked".
Locking happens before an exec()-like callback is passed a
@@ -1519,7 +1541,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
finalize the statement. If it does not throw, it returns stmt.
*/
const affirmNotLockedByExec = function(stmt,currentOpName){
if(stmt._lockedByExec){
if(__execLock.has(stmt)){
toss3("Operation is illegal when statement is locked:",currentOpName);
}
return stmt;
@@ -1604,7 +1626,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
toss3("Unsupported bind() argument type: "+(typeof val));
}
if(rc) DB.checkRc(stmt.db.pointer, rc);
stmt._mayGet = false;
return stmt;
};
@@ -1627,9 +1648,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const rc = capi.sqlite3_finalize(this.pointer);
delete __stmtMap.get(this.db)[this.pointer];
__ptrMap.delete(this);
delete this._mayGet;
__execLock.delete(this);
__stmtMayGet.delete(this);
delete this.parameterCount;
delete this._lockedByExec;
delete this.db;
return rc;
}
@@ -1643,7 +1664,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
clearBindings: function(){
affirmNotLockedByExec(affirmStmtOpen(this), 'clearBindings()')
capi.sqlite3_clear_bindings(this.pointer);
this._mayGet = false;
__stmtMayGet.delete(this);
return this;
},
/**
@@ -1669,7 +1690,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
affirmNotLockedByExec(this,'reset()');
if(alsoClearBinds) this.clearBindings();
const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer);
this._mayGet = false;
__stmtMayGet.delete(this);
checkSqlite3Rc(this.db, rc);
return this;
},
@@ -1756,7 +1777,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}else if(!this.parameterCount){
toss3("This statement has no bindable parameters.");
}
this._mayGet = false;
__stmtMayGet.delete(this);
if(null===arg){
/* bind NULL */
return bindOne(this, ndx, BindTypes.null, arg);
@@ -1821,14 +1842,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
affirmNotLockedByExec(this, 'step()');
const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer);
switch(rc){
case capi.SQLITE_DONE: return this._mayGet = false;
case capi.SQLITE_ROW: return this._mayGet = true;
default:
this._mayGet = false;
sqlite3.config.warn("sqlite3_step() rc=",rc,
capi.sqlite3_js_rc_str(rc),
"SQL =", capi.sqlite3_sql(this.pointer));
DB.checkRc(this.db.pointer, rc);
case capi.SQLITE_DONE:
__stmtMayGet.delete(this);
return false;
case capi.SQLITE_ROW:
__stmtMayGet.add(this);
return true;
default:
__stmtMayGet.delete(this);
sqlite3.config.warn("sqlite3_step() rc=",rc,
capi.sqlite3_js_rc_str(rc),
"SQL =", capi.sqlite3_sql(this.pointer));
DB.checkRc(this.db.pointer, rc);
}
},
/**
@@ -1913,7 +1938,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
getJSON() can be used for that.
*/
get: function(ndx,asType){
if(!affirmStmtOpen(this)._mayGet){
if(!__stmtMayGet.has(affirmStmtOpen(this))){
toss3("Stmt.step() has not (recently) returned true.");
}
if(Array.isArray(ndx)){
+4 -1
View File
@@ -135,9 +135,12 @@
/*
** If SQLITE_WASM_BARE_BONES is defined, undefine most of the ENABLE
** macros.
** macros. This will, when using the canonical makefile, also elide
** any C functions from the WASM exports which are listed in
** ./EXPORT_FUNCTIONS.sqlite3-extras.
*/
#ifdef SQLITE_WASM_BARE_BONES
# undef SQLITE_ENABLE_COLUMN_METADATA
# undef SQLITE_ENABLE_DBPAGE_VTAB
# undef SQLITE_ENABLE_DBSTAT_VTAB
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
+1 -1
View File
@@ -279,7 +279,7 @@
opt.innerHTML = lbl;
opt.value = f;
if(preselectedFlags.indexOf(f) >= 0) opt.selected = true;
});
});
const cbReverseLog = E('#cb-reverse-log-order');
const lblReverseLog = E('#lbl-reverse-log-order');
if(cbReverseLog.checked){
+1 -1
View File
@@ -118,7 +118,7 @@
argv.push("--vfs", vfs);
log2('',"Using VFS:",vfs);
if('kvvfs' === vfs){
forceSize = 4 /* 5 uses approx. 4.96mb */;
forceSize = 2 /* 5 uses approx. 4.96mb */;
dbFile = 'session';
log2('warning',"kvvfs VFS: forcing --size",forceSize,
"and filename '"+dbFile+"'.");
+124 -58
View File
@@ -1263,7 +1263,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
capi.sqlite3_stmt_status(
st, capi.SQLITE_STMTSTATUS_RUN, 0
) === 0)
.assert(!st._mayGet)
.assert('a' === st.getColumnName(0))
.mustThrowMatching(()=>st.columnCount=2,
/columnCount property is read-only/)
@@ -1287,9 +1286,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(1===st.get(0,capi.SQLITE_BLOB).length)
.assert(st.getBlob(0) instanceof Uint8Array)
.assert('3'.charCodeAt(0) === st.getBlob(0)[0])
.assert(st._mayGet)
.assert(false===st.step())
.assert(!st._mayGet)
.mustThrowMatching(()=>st.get(0),
"Stmt.step() has not (recently) returned true.")
.assert(
capi.sqlite3_stmt_status(
st, capi.SQLITE_STMTSTATUS_RUN, 0
@@ -1297,11 +1296,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(this.progressHandlerCount>0
|| wasm.compileOptionUsed('OMIT_PROGRESS_CALLBACK'),
"Expecting progress callback.").
assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")).
assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")).
assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)).
assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0));
"Expecting progress callback.");
}finally{
rc = st.finalize();
}
@@ -1350,7 +1345,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(pVfsDb > 0)
.assert(pVfsMem !== pVfsDflt
/* memdb lives on top of the default vfs */)
.assert(pVfsDb === pVfsDflt || pVfsdb === pVfsMem)
.assert(pVfsDb === pVfsDflt || pVfsDb === pVfsMem)
;
/*const vMem = new capi.sqlite3_vfs(pVfsMem),
vDflt = new capi.sqlite3_vfs(pVfsDflt),
@@ -2193,7 +2188,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
"back into JS because of the lack of 64-bit integer support.");
}
}finally{
const x = w.scopedAlloc(1), y = w.scopedAlloc(1), z = w.scopedAlloc(1);
//const x = w.scopedAlloc(1), y = w.scopedAlloc(1), z = w.scopedAlloc(1);
//log("x=",x,"y=",y,"z=",z); // just looking at the alignment
w.scopedAllocPop(stack);
}
@@ -2673,50 +2668,70 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|| "Only available in main thread."),
test: function(sqlite3){
this.kvvfsUnlink();
let db;
const encOpt1 = 1
? {textkey: 'foo'}
: {key: 'foo'};
const encOpt2 = encOpt1.textkey
? encOpt1
: {hexkey: new Uint8Array([0x66,0x6f,0x6f]/*==>"foo"*/)}
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
...encOpt1
});
db.exec([
"create table t(a,b);",
"insert into t(a,b) values(1,2),(3,4)"
]);
db.close();
let err;
try{
db = new this.JDb({
filename: this.kvvfsDbFile,
flags: 'ct'
let initDb = true;
const tryKey = function(keyKey, key, expectCount){
let db;
//console.debug('tryKey()',arguments);
const ctoropt = {
filename: this.kvvfsDbFile
//vfs: 'kvvfs'
//,flags: 'ct'
};
try {
if (initDb) {
initDb = false;
db = new this.JDb({
...ctoropt,
[keyKey]: key
});
db.exec([
"drop table if exists t;",
"create table t(a);"
]);
db.close();
// Ensure that it's actually encrypted...
let err;
try {
db = new this.JDb(ctoropt);
T.assert(db, 'db opened') /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("(should not be reached) sessionStorage =", sessionStorage);
} catch (e) {
err = e;
} finally {
db.close()
}
T.assert(err, "Expecting an exception")
.assert(sqlite3.capi.SQLITE_NOTADB == err.resultCode,
"Expecting NOTADB");
}/*initDb*/
//console.debug('tryKey()',arguments);
db = new sqlite3.oo1.DB({
...ctoropt,
vfs: 'kvvfs',
[keyKey]: key
});
T.assert(db) /* opening is fine, but... */;
db.exec("select 1 from sqlite_schema");
console.warn("sessionStorage =",sessionStorage);
}catch(e){
err = e;
}finally{
db.close();
db.exec("insert into t(a) values (1),(2)");
T.assert(expectCount === db.selectValue('select sum(a) from t'));
} finally {
if (db) db.close();
}
T.assert(err,"Expecting an exception")
.assert(sqlite3.capi.SQLITE_NOTADB==err.resultCode,
"Expecting NOTADB");
db = new sqlite3.oo1.DB({
filename: this.kvvfsDbFile,
vfs: 'kvvfs',
...encOpt2
});
T.assert( 4===db.selectValue('select sum(a) from t') );
}finally{
if( db ) db.close();
this.kvvfsUnlink();
}
}.bind(this);
const hexFoo = new Uint8Array([0x66,0x6f,0x6f]/*=="foo"*/);
tryKey('textkey', 'foo', 3);
T.assert( !initDb );
tryKey('textkey', 'foo', 6);
this.kvvfsUnlink();
initDb = true;
tryKey('key', 'foo', 3);
T.assert( !initDb );
tryKey('key', hexFoo, 6);
this.kvvfsUnlink();
initDb = true;
tryKey('hexkey', hexFoo, 3);
T.assert( !initDb );
tryKey('hexkey', hexFoo, 6);
this.kvvfsUnlink();
}
})/*kvvfs with SEE*/
//#endif enable-see
@@ -2836,6 +2851,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
},
9
);
T.assert( 0==rc );
db.transaction((d)=>{
d.exec([
"create table t(a);",
@@ -2849,8 +2865,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(2 === countHook[capi.SQLITE_UPDATE])
.assert(1 === countHook[capi.SQLITE_DELETE]);
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
db.close();
T.assert( !!capi.sqlite3_preupdate_hook(db, 0, 0) );
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
T.assert( !capi.sqlite3_preupdate_hook(db, 0, 0) );
db.close();
}
})/*pre-update hooks*/
;/*end hook API tests*/
@@ -3051,7 +3069,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert(6 === db.selectValue('select count(*) from p')).
assert( this.opfsImportSize == exp.byteLength );
db.close();
const unlink = this.opfsUnlink =
this.opfsUnlink =
(fn=filename)=>sqlite3.util.sqlite3__wasm_vfs_unlink("opfs",fn);
this.opfsUnlink(filename);
T.assert(!(await sqlite3.opfs.entryExists(filename)));
@@ -3302,7 +3320,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(true === await u3.removeVfs())
.assert(false === await P3b.removeVfs());
}
}/*OPFS SAH Pool sanity checks*/)
}/*OPFS SAH Pool sanity checks*/);
////////////////////////////////////////////////////////////////////////
T.g('Misc. APIs')
@@ -3323,6 +3341,44 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
db.close();
})
/**
Ensure that certain Stmt members throw when called
via DB.exec().
*/
.t('locked-by-exec() APIs', function(sqlite3){
const db = new sqlite3.oo1.DB();
db.exec("create table t(a);insert into t(a) values(1);");
let checkCount = 0;
const checkOp = function(op){
++checkCount;
T.mustThrowMatching(() => {
db.exec({
sql: "select ?1",
bind: op,
callback: (row, stmt) => {
switch (row[0]) {
case 'bind': stmt.bind(1); break;
case 'finalize':
case 'clearBindings':
case 'reset':
case 'step': stmt[op](); break;
}
}
});
}, /^Operation is illegal when statement is locked.*/)
};
try{
checkOp('bind');
checkOp('finalize');
checkOp('clearBindings');
checkOp('reset');
checkOp('step');
T.assert(5===checkCount);
}finally{
db.close();
}
})
////////////////////////////////////////////////////////////////////
.t("Misc. stmt_...", function(sqlite3){
const db = new sqlite3.oo1.DB();
@@ -3353,6 +3409,16 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
T.assert( 1===n )
.assert( 0===capi.sqlite3_stmt_busy(stmt) )
.assert( !stmt.isBusy() );
if( wasm.exports.sqlite3_column_origin_name ){
log("Column metadata APIs enabled");
T.assert( "t" === capi.sqlite3_column_table_name(stmt, 0))
.assert("a" === capi.sqlite3_column_origin_name(stmt, 0))
.assert("main" === capi.sqlite3_column_database_name(stmt, 0))
}else{
log("Column metadata APIs not enabled");
} // column metadata APIs
stmt.finalize();
db.close();
})
@@ -3364,7 +3430,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
capi.sqlite3_interrupt(db);
T.assert( 0!==capi.sqlite3_is_interrupted(db) );
db.close();
})
});
////////////////////////////////////////////////////////////////////////
T.g('Bug Reports')
@@ -3384,10 +3450,10 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
sql: "SELECT * FROM f order by path",
rowMode: 'array'
});
const dump = function(lbl){
/*const dump = function(lbl){
let rc = fetchEm();
log((lbl ? (lbl+' results') : ''),rc);
};
};*/
//dump('Full fts table');
let rc = fetchEm();
T.assert(3===rc.length);
+41 -10
View File
@@ -1047,13 +1047,17 @@ $(T.tcl.env.sh): $(TCLSH_CMD) $(TCL_CONFIG_SH) $(MAKEFILE_LIST)
@if [ x = "x$(TCL_CONFIG_SH)" ]; then \
echo 'TCL_CONFIG_SH must be set to point to a "tclConfig.sh"' 1>&2; exit 1; \
fi; \
if [ x != "x$(TCLLIBDIR)" ]; then echo TCLLIBDIR="$(TCLLIBDIR)"; else \
if [ x != "x$(TCLLIBDIR)" ]; then \
echo "# generated by main.mk"; \
echo TCLLIBDIR="$(TCLLIBDIR)"; \
else \
ld= ; \
for d in `echo "puts stdout \\$$auto_path" | $(TCLSH_CMD)`; do \
if [ -d "$$d" ]; then ld=$$d; break; fi; \
done; \
if [ x = "x$$ld" ]; then echo "Cannot determine TCLLIBDIR" 1>&2; exit 1; fi; \
echo "TCLLIBDIR=$$ld/sqlite3"; \
echo "# generated by main.mk"; \
echo "TCLLIBDIR=$$ld/sqlite3$(PACKAGE_VERSION)"; \
fi > $@; \
echo ". \"$(TCL_CONFIG_SH)\" || exit \$$?" >> $@; \
echo "Created $@"
@@ -1622,15 +1626,29 @@ install-headers: sqlite3.h $(install-dir.include)
$(INSTALL.noexec) sqlite3.h "$(TOP)/src/sqlite3ext.h" "$(install-dir.include)"
install: install-headers
#
# If TCL_EXT_DLL_BASENAME is not set then guess the Tcl extension's
# DLL name depending on the Tcl version. This does not account for
# Cygwin's naming - the canonical build will usually set it, but
# static makefiles importing this one will need to account for that on
# their own. They can do that by setting libtclsqlite3.basename-[89]
# to appropriate names (cygsqlite resp. cygtcl9sqlite).
#
TCL_MAJOR_VERSION ?= 0
libtclsqlite3.basename-8 ?= libsqlite
libtclsqlite3.basename-9 ?= libtcl9sqlite
TCL_EXT_DLL_BASENAME ?= $(libtclsqlite3.basename-$(TCL_MAJOR_VERSION))
libtclsqlite3.DLL ?= $(TCL_EXT_DLL_BASENAME)$(PACKAGE_VERSION)$(T.dll)
#
# libtclsqlite3...
#
pkgIndex.tcl:
echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] Sqlite3]' > $@
pkgIndex.tcl: $(TOP)/main.mk
echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir $(libtclsqlite3.DLL)] Sqlite3]' > $@
pkgIndex.tcl-1: pkgIndex.tcl
pkgIndex.tcl-0 pkgIndex.tcl-:
tcl: pkgIndex.tcl-$(HAVE_TCL)
libtclsqlite3.DLL = libtclsqlite3$(T.dll)
$(libtclsqlite3.DLL): $(T.tcl.env.sh) tclsqlite.o $(LIBOBJ)
$(T.tcl.env.source); \
$(T.link.shared) -o $@ tclsqlite.o \
@@ -1671,34 +1689,47 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
# by --with-tclsh=
#
tclextension: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only --cc "$(T.cc)" $(CFLAGS.tclextension)
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
#
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
# to find it.
#
tclextension-install: tclsqlite3.c
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" --cc "$(T.cc)" $(CFLAGS.tclextension)
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
#
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
#
tclextension-uninstall:
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall \
--tclConfig.sh $(TCL_CONFIG_SH)
#
# List all installed the SQLite TCL extensions that is are accessible
# by $TCLSH_CMD, including prior versions.
#
tclextension-list:
@ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
@ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info \
--tclConfig.sh $(TCL_CONFIG_SH)
# Verify that the SQLite TCL extension that is loaded by default
# in $(TCLSH_CMD) is the same as the version of SQLite for the
# current source tree
#
tclextension-verify: sqlite3.h
@ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --version-check
@ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --version-check \
--tclConfig.sh $(TCL_CONFIG_SH)
# Run all of the tclextension targets in order, ending with uninstall.
tclextension-all:
$(MAKE) tclextension
$(MAKE) tclextension-install
$(MAKE) tclextension-list
$(MAKE) tclextension-verify
$(MAKE) tclextension-uninstall
#
# FTS5 things
+48 -48
View File
@@ -1,10 +1,10 @@
C Have\ssqlite3_setlk_timeout()\stake\sthe\sdatabase\shandle\smutex.\sThis\sfixes\san\sassert()\sfailure\sthat\scould\soccur\sif\ssqlite3_setlk_timeout()\swere\scalled\son\sa\sthreadsafe\shandle.
D 2025-06-12T07:35:38.259
C For\sall\sbinary\soperators,\stry\sto\savoid\scomputing\ssubquery\soperands\sif\sthe\nother\soperand\sis\sNULL.
D 2025-06-30T12:14:47.305
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.in d8bc4aee9fb645c9f2ff0e3a30585d17a0df076bb6a33f0f20bab4999abb45a0
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc ec2011bbdfc917d6a1c7c173dabb29c14ead0dd8e2e0b67278a00ae4ba576a77
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
@@ -29,7 +29,7 @@ F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079
F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
F autoconf/tea/teaish.tcl a2224762a039ed30c45cc1ce4b2fde5667fb0aa2569bb56590f5cb5d45d7410b
F autoconf/tea/teaish.tcl 81feb417e718ed75cdd7e2fdf6771f3da80dae97377a90c4d5b62b3754abbf1d
F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e
@@ -46,8 +46,8 @@ 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 a4d7eb8d7e05328ac6202abe813da300db2fa89f1936a69f3f9d75300b4ff244
F autosetup/sqlite-config.tcl ccda82e43e377b832aae72a1678b1dc17dcaff36ed0ebbd8f0cfc88612ae8de3
F autosetup/proj.tcl 6aac1eb3059fc511c8e1659f33b96eb2a216a371ed9b28be6661374061be9b15
F autosetup/sqlite-config.tcl 3177dedd7bd49465fa06677fd743c4966eee5702a9ddf4914c2c1af5e5972a52
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl aee092fc71986d1272b835ea7492bb55ffc213a289502e4f14da80cf67b7e3c3
@@ -113,8 +113,8 @@ F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
F ext/fts5/fts5_expr.c be9e5f7f11d87e7bd3680832c93c13050fe351994b5052b0215c2ef40312c23a
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_index.c 1906bb292b65121aa7d88cabb2a486bea58de75c600271e5011fb86ccc2e427a
F ext/fts5/fts5_main.c e558225168845dc708abeb2ad10415696e5a3249bcba1810ba3c7ef80764962e
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
@@ -126,7 +126,7 @@ F ext/fts5/fts5_vocab.c ff0441c4ea165081e8152dec6d29056faa0cdc281a9f218a00e3d7aa
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl c5aa7cf7148b6dcffb5b61520ae18212baf169936af734ab265143f59db328fe
F ext/fts5/test/fts5aa.test 015c81b84d53bfcedd77d624202c8b02e9f0cbbb4b51688e3a9c9f90bccbb4ac
F ext/fts5/test/fts5aa.test cf4ff6180873bbc131666ba846ddd90148fcb61c20aad089711d3511cce24300
F ext/fts5/test/fts5ab.test 4bdb619fee409e11417e8827e320b857e42e926a01a0408fc9f143ec870a6ced
F ext/fts5/test/fts5ac.test 4a73626de86f3d17c95738034880c4f0de8d54741fb943d819b528373657e59b
F ext/fts5/test/fts5ad.test 058e616612964e61d19f70295f0e6eaedceb4b29b1fbf4f859615ef7e779dc22
@@ -160,14 +160,14 @@ F ext/fts5/test/fts5contentless2.test 70ffe6c611d8f278240da56734df8a77948f04e273
F ext/fts5/test/fts5contentless3.test 75eaae5ad6b284ee447788943974d323228f27cc35a1681da997135cff95bc6a
F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b05ea89964c863833b6eff8
F ext/fts5/test/fts5contentless5.test 38cd0392c730dc7090c550321ce3c24ba4c392bc97308b51a4180e9959dca7b5
F ext/fts5/test/fts5corrupt.test 6485f721b88ba355ca5d701e7ee87a4efa3ea578d8e6adb26f51ef956c8328bd
F ext/fts5/test/fts5corrupt2.test 335911e3f68b9625d850325f9e29a128db3f4276a8c9d4e32134580da8f924c4
F ext/fts5/test/fts5corrupt3.test 3420ad30bf9e9bbdbd43b3224c582431744899530a65b11b60ddacdf14200e19
F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14cccbda3cfe13833193
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
F ext/fts5/test/fts5corrupt3.test e4852b2472dd25556431fd48fe88e4d0c8cf3e18e010c5ea308345e1cdf97bd5
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
F ext/fts5/test/fts5corrupt5.test bcf0801b0c991eadae3cb8e978e82b4bf01412cb4df41874a90d5aa279c7cc96
F ext/fts5/test/fts5corrupt5.test 73985d4fe6d8f0d5d5c7bcf79ae7c6522c376cd6ad710a0ff2f26e0c2e222abe
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
F ext/fts5/test/fts5corrupt7.test 4e830875c33b9ea3c4cf1ba71e692b63893cbb4faae8c69b1071889dc26e211c
F ext/fts5/test/fts5corrupt8.test b81d802e41631e98100f49a1aadeeffef860e30a62d6ed7d743c2797c477239e
F ext/fts5/test/fts5corrupt7.test 814aab492d7a09abb5bfdd81cc66fc206d7f3868f9a3bae91876e02efc466fb3
F ext/fts5/test/fts5corrupt8.test 7618b102b9b3a5a3494271f4975ab5837e2fb3f61f5adfcdeeb31772c859e6df
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -229,7 +229,7 @@ F ext/fts5/test/fts5prefix.test c0b7842f1a2d830c0b146cd438a95ea4c5a25635719ed0d9
F ext/fts5/test/fts5prefix2.test a5bb43b8a2687efafa7ac4e5ccff6812015cf8cf18e3086bb0eb3126f30fbbf6
F ext/fts5/test/fts5query.test 0320a7a4b58a6e3e50ec8910b301649da90ace675001f9e0bf6392750ad4591d
F ext/fts5/test/fts5rank.test 47c1e8e5d84754ff18e012fdd629776088b5a15de41bdd24957581cf084d8a00
F ext/fts5/test/fts5rebuild.test 83e72d77636378833233fadc7cb7517a2fa446ea7d1f94dd526ba3e7e104b9f5
F ext/fts5/test/fts5rebuild.test dc09779fbbe151ab68206a0931c10a611912a7a12c7a85d71c5e48453f2375a5
F ext/fts5/test/fts5restart.test 9af2084b8e065130037b95f05f3f220bb7973903a7701e2c5fb916dff7cf80c5
F ext/fts5/test/fts5rowid.test 8632829fec04996832a4cfb4f0bd89721ba65b7e398c1731741bdb63f070e1a3
F ext/fts5/test/fts5savepoint.test 1447758d7900afe903cef08b4524c5331fb60c1126ae6fba7f4d8704268013c5
@@ -417,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 5e1aff478ea12455a76be25dff321e1e9517b189fffb1d547a019625c49c1880
F ext/misc/fileio.c 88cb2e5744296de6638af02ef6349fd468c2eb5e5f41ba405f88d9b4ad500f8e
F ext/misc/fossildelta.c 0aeb099e9627eea693cf21ae47826ecd1e0319b93143bed23090838b2ef0c162
F ext/misc/fuzzer.c 6b231352815304ba60d8e9ec2ee73d4918e74d9b76bda8940ba2b64e8777515e
F ext/misc/ieee754.c c9dd9d77c8e8e18e0a5706f8ffcccf4ccb6562073709f7453d4d73f5122f4362
@@ -621,7 +621,7 @@ F ext/session/sqlite3session.c 6b0877fe1ab832aa4b85eaca72606dfd1630a1363a1be7af1
F ext/session/sqlite3session.h 9bb1a6687b467764b35178dc29bbd2c57ab8cd3acdc8a62f088c34ad17e4fe2b
F ext/session/test_session.c 2ddff73ea368d827028c32851b291416e1008845832feb27b751d15e57e13cc3
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile e315b903c33b28ca074367041849de9dd2681c96d1437c11a5e9596abc265012
F ext/wasm/GNUmakefile a05bb1766f97c88cb42fbfe9e349c799c691f8ae0dc959e9d9469f0bcee89350
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -630,7 +630,7 @@ F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 2bcbbfe3b95c043ed6037e2708a2ee078d212dd1612c364f93588d8dc97300fe
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras cb4fa8842c875b6ee99381523792975c5ebb7371bd27fbd1bd863a43c7f3505a
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md c64ec8e84449c069e0217706d9d7d31b3bd53627228b2ba0c3cddbdc2350ca66
@@ -640,8 +640,8 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
F ext/wasm/api/sqlite3-api-glue.c-pp.js bd8ae059bb3ea489666b2f167025833e55dc5941be99c129a56fc25e541d37ce
F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
F ext/wasm/api/sqlite3-api-glue.c-pp.js 0b76510f3650053bac67ca8947cb6ab9d050ad2218118a2e7796dd37be832ffa
F ext/wasm/api/sqlite3-api-oo1.c-pp.js c68d6da0088c2527156fca9163a721abe08e7bd077b15404fd8d292f4612adc1
F ext/wasm/api/sqlite3-api-prologue.js 8708570165f5b4bce9a78ccd91bc9ddf8735970ac1c4d659e36c9a7d9a644bb4
F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
@@ -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 7ea3d4a286a2241f6fcc65c9ff10fc04ee5590f80f40763a57001dd5e93aa4c4
F ext/wasm/api/sqlite3-wasm.c d2672a83b99a89db6bab31eccf9f93fca15a01838d8b0224967db6d4c4bff560
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
@@ -688,9 +688,9 @@ F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
F ext/wasm/speedtest1-wasmfs.mjs c77c7231338ed5c0e1ce16aa29106df8e5b5cf11a48319c49433490a8d3ded30
F ext/wasm/speedtest1-worker.html 864b65ed78ce24847a348c180e7f267621a02ca027068a1863ec1c90187c1852
F ext/wasm/speedtest1-worker.html d24d1e06caf3dcd83430c8c3d87761ff7555fd06eaeaf2fc02ce49cf45f0d032
F ext/wasm/speedtest1-worker.js 95e549e13a4d35863a9a7fc66122b5f546c0130d3be7b06dfcc556eb66d24bde
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/speedtest1.html 217bf15d43065634a27a06dbd5c9a320f6da9932dbcdfc963d482bc2f99dbea9
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
@@ -698,7 +698,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js 419717b16e12703487a7ccf3ea4e63d693bdfbf7657e55a7e6c559bbccf027d3
F ext/wasm/tester1.c-pp.js 766a2ba51a2619d41a49be7c6a1ad014c1d23fc97b67496e4f103038203eb17d
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -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 17744293e7af7c39936c3f220ebb8eaff4f0ad1be1e186efb584dbc34bbea2c1
F main.mk 3ced12d068b22957f4e82a0b94a2c1d83b37dcf39c087263691267f7bfb39a84
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -726,7 +726,7 @@ F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 53a9c7b243e94c992853d90f1dac0959028433b4b0d27e04409cee04e001b508
F src/btree.c 81fb44041929a605e293185bd4091cb24c468a108afe8ba1d93a81a8823de47f
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
@@ -736,7 +736,7 @@ F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c b3e218f8ed74fcbb7fa805df8ca669a3718d397617b3d8a8aac3307dc315c4d6
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
F src/expr.c f16fa5cbd849991462edf1d31bb7def5b970bb9611afcb4ea21c77e88e52a220
F src/expr.c d726acf67585c14473e354c3d1123a4290e357bdfd389056a05df15b70f66d49
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c de47a8295503aa130baae5e6d9868ecf4f7c4dbffa65d83ad1f70bdbac0ee2d6
@@ -745,7 +745,7 @@ 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/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c cb87977b1ee25ee7d27505d65a9261b687395bf895342c8ba566b7c01aee2047
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c d7edd8e671237539d795d30daaf888908a2c82e99bade4c78f3be021e8b7d655
@@ -781,16 +781,16 @@ 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 882d739e0d5e6c7a8b46a3cca3ada37fe1a56301f1360d6b141312c666bbe482
F src/shell.c.in 4ae9ff8e8b23d9a309e50d5b5ef2768b9bb18f748ece2acc2641a3c23b71e2b9
F src/sqlite.h.in 22882ddd3a70751aa8864c81993ee4562ed54c2c508b6270f75e223ffee38e1b
F src/shell.c.in 4f14a1f5196b6006abc8e73cc8fd6c1a62cf940396f8ba909d6711f35f074bb6
F src/sqlite.h.in ab255d9c4944db23ac5a2f3f6ff691b24a9a15b40ac06cef7725639373821df5
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
F src/sqliteInt.h 5f190640c1939960f993c07d0e626fb2acc40d42ac12b21811dd6c069fb71db4
F src/sqliteInt.h 005542f8760edf9b62f014abccb876cf64533b64475a40a89402054d62535288
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -852,10 +852,10 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
F src/vdbe.c 714fab7aa7c516edbcf5e4f653ae8f548a3e24c0ed19086d7383bb5851983992
F src/vdbe.c 7e29623ca387880b8893e69135a0ff240c3dcaf0710f7a46a5f95b062cf93883
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
F src/vdbeapi.c 613a6f29efacd6ed83e886b6e52db0fe52ba80a596b0a137608db1948bad90a9
F src/vdbeapi.c f9a4881a9674fec3fa13da35044a1484d3c4b95f9ec891cc8ffb02ef2b7a41df
F src/vdbeaux.c fd2c6b19a8892c31a2adc719f156f313560f9cc490cdbd04ff08fdae5d7aedb7
F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
@@ -864,13 +864,13 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c b0f848cfba8dd057f77073493cdd542f9125b4cf87941f53e9d0db21604155c8
F src/wal.c 20be6f0a25a80b7897cf2a5369bfd37ef198e6f0b6cdef16d83eee856056b159
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 45a3b496248a0b36d91ce34da3278d54f8fa20e9d3fbd36d45a42051d1118137
F src/whereInt.h ecdbfb5551cf394f04ec7f0bc7ad963146d80eee3071405ac29aa84950128b8e
F src/where.c a99fa3061a0155d2cb0e2c91df76dbf834750272a8d79ec5e2dce3ed4e6abad6
F src/whereInt.h 02b646ea41a8342815b3628f8064c32618ea2e0f20b83216ea08cad11f0ac5aa
F src/wherecode.c 9710e62379c000189476404f923d4d1b192d0def222fdd287b820cc085a0d555
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
F src/whereexpr.c 566ca4382e07a4ba1fd86c97ae0781cdf84004c7d9c59466bf5db75733548807
F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
@@ -1300,7 +1300,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 3481a68009fe143e3363fca922f6fc7a1e1f3776c51e42777f1a01b26ad2a9c8
F test/hook.test 2d89bf9480646feb8093be3a58ea502d6521906779ed960de31dd9c4502c0541
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 8da7d52cd9722c82f33b0466ed915460cb03c23a38f18a9a2d3ff97da9a4a8c0
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
@@ -1360,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 255c1f42b7fe027b518cadb2bf40f41a793a95e7f8db2bceb54faaf59ff19c6c
F test/join.test 2fcfd84640cfd9ff48f31b4b0d370c4d5498c355ae4384544668ca54d37ae186
F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1701,7 +1701,7 @@ F test/statfault.test 064f43379e4992b5221b7d9ac887c313b3191f85cce605d78e416fc404
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
F test/stmtrand.test 340e2ea4841c5cdc02d36e33739769c5d907ab529b12bb535407def0e413ca17
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
F test/strict1.test a7f9091603fe71cdc62baab0766684cba12a97ec69bfbb70be965532669cd77a
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e17a84
@@ -2014,7 +2014,7 @@ F test/wal_common.tcl 204d1721ac13c5e0c7fae6380315b5ab7f4e8423f580d826c5e9df1995
F test/walbak.test 018d4e5a3d45c6298d11b99f09a8ef6876527946
F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434
F test/walblock.test 6bb472e82730e7e4e81395e907a01d8cfc2bd9e1f01f8a9184ca572e2955a4bf
F test/walcksum.test ba02b4fe6d22cb42e57a323003cbae62f77a740983e1355b2b520e019ae261c7
F test/walcksum.test 50e204500eed9c691b6045e467bb2923f49aa93d8adf315e2be135fdb202c1c2
F test/walcrash.test 21038858cc552077b0522f50b0fa87e38139306a
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
@@ -2124,7 +2124,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/build-all-msvc.bat 1960a7a3e5d8176c4329e31476f6e3dfa9543675355fa9020a569f4452628458 x
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
F tool/buildtclext.tcl 85d1bcd5410d0a4c739e2d013106f03674d082cc4d573bcc57a68546b6db67cd
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
@@ -2208,8 +2208,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P badf3014bd1620fd3d4b8013f641fd820b249649fb93cc75b7b8df9dfd6f32a6
R 7fdf393495e0e2303824909fb18b2ec1
U dan
Z 94b5809cfbb11f003ae05c3735568843
P f6e6fd02f4ad49c390a2d3c9626d57f9b2fff1f67eb361b30074cc1f5121810e
R 886172909745da80cda276284a701cfd
U drh
Z 78219ecf578f4ce2acfc88c5fa4f82e5
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
a95d126e1330e1b83f42b51f97c4c216622cf38062f3b5d72ccb76313187e850
d86eb16283c4b573c506d4faa422d5d9aeb6abc279d8e6a8e2104737162d417f
+16 -8
View File
@@ -3074,6 +3074,10 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
sqlite3BtreeEnter(p);
pBt->nReserveWanted = (u8)nReserve;
x = pBt->pageSize - pBt->usableSize;
if( x==nReserve && (pageSize==0 || (u32)pageSize==pBt->pageSize) ){
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
if( nReserve<x ) nReserve = x;
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
@@ -5882,8 +5886,8 @@ moveto_table_finish:
}
/*
** Compare the "idx"-th cell on the page the cursor pCur is currently
** pointing to to pIdxKey using xRecordCompare. Return negative or
** Compare the "idx"-th cell on the page pPage against the key
** pointing to by pIdxKey using xRecordCompare. Return negative or
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
@@ -5898,12 +5902,11 @@ moveto_table_finish:
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
BtCursor *pCur,
MemPage *pPage,
int idx,
UnpackedRecord *pIdxKey,
RecordCompare xRecordCompare
){
MemPage *pPage = pCur->pPage;
int c;
int nCell; /* Size of the pCell cell in bytes */
u8 *pCell = findCellPastPtr(pPage, idx);
@@ -6012,14 +6015,14 @@ int sqlite3BtreeIndexMoveto(
){
int c;
if( pCur->ix==pCur->pPage->nCell-1
&& (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
&& (c = indexCellCompare(pCur->pPage,pCur->ix,pIdxKey,xRecordCompare))<=0
&& pIdxKey->errCode==SQLITE_OK
){
*pRes = c;
return SQLITE_OK; /* Cursor already pointing at the correct spot */
}
if( pCur->iPage>0
&& indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
&& indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
@@ -6236,7 +6239,7 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
n = pCur->pPage->nCell;
for(i=0; i<pCur->iPage; i++){
n *= pCur->apPage[i]->nCell;
n *= pCur->apPage[i]->nCell+1;
}
return n;
}
@@ -8693,7 +8696,12 @@ static int balance_nonroot(
** of the right-most new sibling page is set to the value that was
** originally in the same field of the right-most old sibling page. */
if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
MemPage *pOld;
if( nNew>nOld ){
pOld = apNew[nOld-1];
}else{
pOld = apOld[nOld-1];
}
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
}
+196 -32
View File
@@ -2373,6 +2373,81 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
return pExpr;
}
/*
** Return true if it might be advantageous to compute the right operand
** of expression pExpr first, before the left operand.
**
** Normally the left operand is computed before the right operand. But if
** the left operand contains a subquery and the right does not, then it
** might be more efficient to compute the right operand first.
*/
static int exprEvalRhsFirst(Expr *pExpr){
if( ExprHasProperty(pExpr->pLeft, EP_Subquery)
&& !ExprHasProperty(pExpr->pRight, EP_Subquery)
){
return 1;
}else{
return 0;
}
}
/*
** Compute the two operands of a binary operator.
**
** If either operand contains a subquery, then the code strives to
** compute the operand containing the subquery second. If the other
** operand evalutes to NULL, then a jump is made. The address of the
** IsNull operand that does this jump is returned. The caller can use
** this to optimize the computation so as to avoid doing the potentially
** expensive subquery.
**
** If no optimization opportunities exist, return 0.
*/
static int exprComputeOperands(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The comparison expression */
int *pR1, /* OUT: Register holding the left operand */
int *pR2, /* OUT: Register holding the right operand */
int *pFree1, /* OUT: Temp register to free if not zero */
int *pFree2 /* OUT: Another temp register to free if not zero */
){
int addrIsNull;
int r1, r2;
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
/*
** If the left operand contains a (possibly expensive) subquery and the
** right operand does not and the right operation might be NULL,
** then compute the right operand first and do an IsNull jump if the
** right operand evalutes to NULL.
*/
if( exprEvalRhsFirst(pExpr) && sqlite3ExprCanBeNull(pExpr->pRight) ){
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2);
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
}else{
addrIsNull = 0;
}
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1);
if( addrIsNull==0 ){
/*
** If the right operand contains a subquery and the left operand does not
** and the left operand might be NULL, then check the left operand do
** an IsNull check on the left operand before computing the right
** operand.
*/
if( ExprHasProperty(pExpr->pRight, EP_Subquery)
&& sqlite3ExprCanBeNull(pExpr->pLeft)
){
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1); VdbeCoverage(v);
}
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2);
}
*pR1 = r1;
*pR2 = r2;
return addrIsNull;
}
/*
** pExpr is a TK_FUNCTION node. Try to determine whether or not the
** function is a constant function. A function is constant if all of
@@ -4269,7 +4344,12 @@ void sqlite3ExprCodeGeneratedColumn(
iAddr = 0;
}
sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
if( pCol->affinity>=SQLITE_AFF_TEXT ){
if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0
&& (pTab->tabFlags & TF_Strict)!=0
){
int p3 = 2+(int)(pCol - pTab->aCol);
sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE);
}else if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
@@ -4956,11 +5036,17 @@ expr_code_doover:
case TK_NE:
case TK_EQ: {
Expr *pLeft = pExpr->pLeft;
int addrIsNull = 0;
if( sqlite3ExprIsVector(pLeft) ){
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
if( ExprHasProperty(pExpr, EP_Subquery) && p5!=SQLITE_NULLEQ ){
addrIsNull = exprComputeOperands(pParse, pExpr,
&r1, &r2, &regFree1, &regFree2);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
}
sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
sqlite3VdbeCurrentAddr(v)+2, p5,
@@ -4975,9 +5061,15 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
}else{
sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
if( addrIsNull ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeJumpHere(v, addrIsNull);
sqlite3VdbeAddOp2(v, OP_Null, 0, inReg);
}
}
testcase( regFree1==0 );
testcase( regFree2==0 );
}
break;
}
@@ -4993,6 +5085,7 @@ expr_code_doover:
case TK_LSHIFT:
case TK_RSHIFT:
case TK_CONCAT: {
int addrIsNull;
assert( TK_AND==OP_And ); testcase( op==TK_AND );
assert( TK_OR==OP_Or ); testcase( op==TK_OR );
assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
@@ -5004,11 +5097,22 @@ expr_code_doover:
assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
if( ExprHasProperty(pExpr, EP_Subquery) ){
addrIsNull = exprComputeOperands(pParse, pExpr,
&r1, &r2, &regFree1, &regFree2);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
addrIsNull = 0;
}
sqlite3VdbeAddOp3(v, op, r2, r1, target);
testcase( regFree1==0 );
testcase( regFree2==0 );
if( addrIsNull ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeJumpHere(v, addrIsNull);
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
break;
}
case TK_UMINUS: {
@@ -5857,17 +5961,27 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
if( pAlt!=pExpr ){
sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull);
}else if( op==TK_AND ){
int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,
jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
}else{
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
Expr *pFirst, *pSecond;
if( exprEvalRhsFirst(pExpr) ){
pFirst = pExpr->pRight;
pSecond = pExpr->pLeft;
}else{
pFirst = pExpr->pLeft;
pSecond = pExpr->pRight;
}
if( op==TK_AND ){
int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pFirst, d2,
jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
}else{
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pFirst, dest, jumpIfNull);
sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull);
}
}
break;
}
@@ -5906,10 +6020,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_GE:
case TK_NE:
case TK_EQ: {
int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
addrIsNull = exprComputeOperands(pParse, pExpr,
&r1, &r2, &regFree1, &regFree2);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
addrIsNull = 0;
}
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
@@ -5924,6 +6044,13 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
testcase( regFree1==0 );
testcase( regFree2==0 );
if( addrIsNull ){
if( jumpIfNull ){
sqlite3VdbeChangeP2(v, addrIsNull, dest);
}else{
sqlite3VdbeJumpHere(v, addrIsNull);
}
}
break;
}
case TK_ISNULL:
@@ -6031,17 +6158,27 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
if( pAlt!=pExpr ){
sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull);
}else if( pExpr->op==TK_AND ){
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
}else{
int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2,
jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
Expr *pFirst, *pSecond;
if( exprEvalRhsFirst(pExpr) ){
pFirst = pExpr->pRight;
pSecond = pExpr->pLeft;
}else{
pFirst = pExpr->pLeft;
pSecond = pExpr->pRight;
}
if( pExpr->op==TK_AND ){
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pFirst, dest, jumpIfNull);
sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull);
}else{
int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pFirst, d2,
jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
}
}
break;
}
@@ -6083,10 +6220,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_GE:
case TK_NE:
case TK_EQ: {
int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
addrIsNull = exprComputeOperands(pParse, pExpr,
&r1, &r2, &regFree1, &regFree2);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
addrIsNull = 0;
}
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
@@ -6101,6 +6244,13 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
testcase( regFree1==0 );
testcase( regFree2==0 );
if( addrIsNull ){
if( jumpIfNull ){
sqlite3VdbeChangeP2(v, addrIsNull, dest);
}else{
sqlite3VdbeJumpHere(v, addrIsNull);
}
}
break;
}
case TK_ISNULL:
@@ -7010,7 +7160,9 @@ static void findOrCreateAggInfoColumn(
){
struct AggInfo_col *pCol;
int k;
int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
assert( mxTerm <= SMXV(i16) );
assert( pAggInfo->iFirstReg==0 );
pCol = pAggInfo->aCol;
for(k=0; k<pAggInfo->nColumn; k++, pCol++){
@@ -7028,6 +7180,10 @@ static void findOrCreateAggInfoColumn(
assert( pParse->db->mallocFailed );
return;
}
if( k>mxTerm ){
sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
k = mxTerm;
}
pCol = &pAggInfo->aCol[k];
assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
@@ -7061,6 +7217,7 @@ fix_up_expr:
if( pExpr->op==TK_COLUMN ){
pExpr->op = TK_AGG_COLUMN;
}
assert( k <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)k;
}
@@ -7145,13 +7302,19 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
assert( mxTerm <= SMXV(i16) );
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
if( i>=pAggInfo->nFunc ){
if( i>mxTerm ){
sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
i = mxTerm;
assert( i<pAggInfo->nFunc );
}else if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
@@ -7205,6 +7368,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pExpr, EP_NoReduce);
assert( i <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
+4 -1
View File
@@ -185,12 +185,15 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
** by one slot and insert a new OP_TypeCheck where the current
** OP_MakeRecord is found */
VdbeOp *pPrev;
int p3;
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
pPrev = sqlite3VdbeGetLastOp(v);
assert( pPrev!=0 );
assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
pPrev->opcode = OP_TypeCheck;
sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
p3 = pPrev->p3;
pPrev->p3 = 0;
sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3);
}else{
/* Insert an isolated OP_Typecheck */
sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
+8
View File
@@ -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);
+6 -5
View File
@@ -9328,7 +9328,8 @@ static int do_meta_command(char *zLine, ShellState *p){
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
" FROM sqlite_schema UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"WHERE type!='meta' AND sql NOTNULL"
" AND name NOT LIKE 'sqlite__%' ESCAPE '_' "
"ORDER BY x",
callback, &data, 0
);
@@ -10804,7 +10805,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zQarg);
}
if( bNoSystemTabs ){
appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0);
}
appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
@@ -11235,7 +11236,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
zSql = "SELECT lower(name) as tname FROM sqlite_schema"
" WHERE type='table' AND coalesce(rootpage,0)>1"
" AND name NOT LIKE 'sqlite_%'"
" AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
" ORDER BY 1 collate nocase";
}
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -11300,7 +11301,7 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zRevText = /* Query for reversible to-blob-to-text check */
"SELECT lower(name) as tname FROM sqlite_schema\n"
"WHERE type='table' AND coalesce(rootpage,0)>1\n"
"AND name NOT LIKE 'sqlite_%%'%s\n"
"AND name NOT LIKE 'sqlite__%%' ESCAPE '_'%s\n"
"ORDER BY 1 collate nocase";
zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
zRevText = sqlite3_mprintf(
@@ -11496,7 +11497,7 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&s, ".sqlite_schema ", 0);
if( c=='t' ){
appendText(&s," WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%'"
" AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
" AND name LIKE ?1", 0);
}else{
appendText(&s," WHERE type='index'"
+96 -94
View File
@@ -168,9 +168,9 @@ extern "C" {
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
** </pre></blockquote>)^
**
** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
** macro. ^The sqlite3_libversion() function returns a pointer to the
** to the sqlite3_version[] string constant. The sqlite3_libversion()
** ^The sqlite3_version[] string constant contains the text of the
** [SQLITE_VERSION] macro. ^The sqlite3_libversion() function returns a
** pointer to the sqlite3_version[] string constant. The sqlite3_libversion()
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
@@ -370,7 +370,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** without having to use a lot of C code.
**
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separate SQL statements passed into its 2nd argument,
** semicolon-separated SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument. ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
@@ -403,7 +403,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** result row is NULL then the corresponding string pointer for the
** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
** sqlite3_exec() callback is an array of pointers to strings where each
** entry represents the name of corresponding result column as obtained
** entry represents the name of a corresponding result column as obtained
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
@@ -589,7 +589,7 @@ int sqlite3_exec(
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
** [sqlite3_open_v2()] does *not* cause the underlying database file
** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
** [sqlite3_open_v2()] has historically be a no-op and might become an
** [sqlite3_open_v2()] has historically been a no-op and might become an
** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
@@ -683,7 +683,7 @@ int sqlite3_exec(
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
** of an [sqlite3_io_methods] object. These values are ordered from
** lest restrictive to most restrictive.
** least restrictive to most restrictive.
**
** The argument to xLock() is always SHARED or higher. The argument to
** xUnlock is either SHARED or NONE.
@@ -999,7 +999,7 @@ struct sqlite3_io_methods {
**
** <li>[[SQLITE_FCNTL_VFSNAME]]
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
** all [VFSes] in the VFS stack. The names of all VFS shims and the
** final bottom-level VFS are written into memory obtained from
** [sqlite3_malloc()] and the result is stored in the char* variable
** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -1013,7 +1013,7 @@ struct sqlite3_io_methods {
** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
** [VFSes] currently in use. ^(The argument X in
** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
** of type "[sqlite3_vfs] **". This opcodes will set *X
** of type "[sqlite3_vfs] **". This opcode will set *X
** to a pointer to the top-level VFS.)^
** ^When there are multiple VFS shims in the stack, this opcode finds the
** upper-most shim only.
@@ -1203,7 +1203,7 @@ struct sqlite3_io_methods {
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
** whether or not there is a database client in another process with a wal-mode
** transaction open on the database or not. It is only available on unix.The
** transaction open on the database or not. It is only available on unix. The
** (void*) argument passed with this file-control should be a pointer to a
** value of type (int). The integer value is set to 1 if the database is a wal
** mode database and there exists at least one client in another process that
@@ -1628,7 +1628,7 @@ struct sqlite3_vfs {
** SQLite interfaces so that an application usually does not need to
** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
** calls sqlite3_initialize() so the SQLite library will be automatically
** initialized when [sqlite3_open()] is called if it has not be initialized
** initialized when [sqlite3_open()] is called if it has not been initialized
** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
** compile-time option, then the automatic calls to sqlite3_initialize()
** are omitted and the application must call sqlite3_initialize() directly
@@ -1885,21 +1885,21 @@ struct sqlite3_mem_methods {
** The [sqlite3_mem_methods]
** structure is filled with the currently defined memory allocation routines.)^
** This option can be used to overload the default memory allocation
** routines with a wrapper that simulations memory allocation failure or
** routines with a wrapper that simulates memory allocation failure or
** tracks memory usage, for example. </dd>
**
** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes a single argument of
** type int, interpreted as a boolean, which if true provides a hint to
** SQLite that it should avoid large memory allocations if possible.
** SQLite will run faster if it is free to make large memory allocations,
** but some application might prefer to run slower in exchange for
** but some applications might prefer to run slower in exchange for
** guarantees about memory fragmentation that are possible if large
** allocations are avoided. This hint is normally off.
** </dd>
**
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes a single argument of type int,
** interpreted as a boolean, which enables or disables the collection of
** memory allocation statistics. ^(When memory allocation statistics are
** disabled, the following SQLite interfaces become non-operational:
@@ -1944,7 +1944,7 @@ struct sqlite3_mem_methods {
** ^If pMem is NULL and N is non-zero, then each database connection
** does an initial bulk allocation for page cache memory
** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
** of -1024*N bytes if N is negative, . ^If additional
** of -1024*N bytes if N is negative. ^If additional
** page cache memory is needed beyond what is provided by the initial
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
** additional cache line. </dd>
@@ -1973,7 +1973,7 @@ struct sqlite3_mem_methods {
** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a
** pointer to an instance of the [sqlite3_mutex_methods] structure.
** The argument specifies alternative low-level mutex routines to be used
** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of
** in place of the mutex routines built into SQLite.)^ ^SQLite makes a copy of
** the content of the [sqlite3_mutex_methods] structure before the call to
** [sqlite3_config()] returns. ^If SQLite is compiled with
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -2015,7 +2015,7 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of
** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off
** the current page cache implementation into that object.)^ </dd>
**
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
@@ -2032,7 +2032,7 @@ struct sqlite3_mem_methods {
** the logger function is a copy of the first parameter to the corresponding
** [sqlite3_log()] call and is intended to be a [result code] or an
** [extended result code]. ^The third parameter passed to the logger is
** log message after formatting via [sqlite3_snprintf()].
** a log message after formatting via [sqlite3_snprintf()].
** The SQLite logging interface is not reentrant; the logger function
** supplied by the application must not invoke any SQLite interface.
** In a multi-threaded application, the application-defined logger
@@ -2223,7 +2223,7 @@ struct sqlite3_mem_methods {
** These constants are the available integer configuration options that
** can be passed as the second parameter to the [sqlite3_db_config()] interface.
**
** The [sqlite3_db_config()] interface is a var-args functions. It takes a
** The [sqlite3_db_config()] interface is a var-args function. It takes a
** variable number of parameters, though always at least two. The number of
** parameters passed into sqlite3_db_config() depends on which of these
** constants is given as the second parameter. This documentation page
@@ -2357,8 +2357,8 @@ struct sqlite3_mem_methods {
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argument to
** this interface is 0, then both the C-API and the SQL function are disabled.
** If the first argument is -1, then no changes are made to state of either the
** C-API or the SQL function.
** If the first argument is -1, then no changes are made to the state of either
** the C-API or the SQL function.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
** is disabled or enabled following this call. The second parameter may
@@ -2476,7 +2476,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]]
** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt>
** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates
** the legacy behavior of the [ALTER TABLE RENAME] command such it
** the legacy behavior of the [ALTER TABLE RENAME] command such that it
** behaves as it did prior to [version 3.24.0] (2018-06-04). See the
** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for
** additional information. This feature can also be turned on and off
@@ -2525,7 +2525,7 @@ struct sqlite3_mem_methods {
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt>
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
** the legacy file format flag. When activated, this flag causes all newly
** created database file to have a schema format version number (the 4-byte
** created database files to have a schema format version number (the 4-byte
** integer found at offset 44 into the database header) of 1. This in turn
** means that the resulting database file will be readable and writable by
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
@@ -2552,7 +2552,7 @@ struct sqlite3_mem_methods {
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
** by default. <p>This option takes two arguments: an integer and a pointer to
** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
** an integer. The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option. If the second argument
** is not NULL, then the value of the statement scanstatus setting after
** processing the first argument is written into the integer that the second
@@ -2595,8 +2595,8 @@ struct sqlite3_mem_methods {
** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the
** ability of the [ATTACH DATABASE] SQL command to open a database for writing.
** This capability is enabled by default. Applications can disable or
** reenable this capability using the current DBCONFIG option. If the
** the this capability is disabled, the [ATTACH] command will still work,
** reenable this capability using the current DBCONFIG option. If
** this capability is disabled, the [ATTACH] command will still work,
** but the database will be opened read-only. If this option is disabled,
** then the ability to create a new database using [ATTACH] is also disabled,
** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]
@@ -2630,7 +2630,7 @@ struct sqlite3_mem_methods {
**
** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the
** overall call to [sqlite3_db_config()] has a total of four parameters.
** The first argument (the third parameter to sqlite3_db_config()) is a integer.
** The first argument (the third parameter to sqlite3_db_config()) is an integer.
** The second argument is a pointer to an integer. If the first argument is 1,
** then the option becomes enabled. If the first integer argument is 0, then the
** option is disabled. If the first argument is -1, then the option setting
@@ -2920,7 +2920,7 @@ int sqlite3_is_interrupted(sqlite3*);
** ^These routines return 0 if the statement is incomplete. ^If a
** memory allocation fails, then SQLITE_NOMEM is returned.
**
** ^These routines do not parse the SQL statements thus
** ^These routines do not parse the SQL statements and thus
** will not detect syntactically incorrect SQL.
**
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
@@ -3037,7 +3037,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms);
** indefinitely if possible. The results of passing any other negative value
** are undefined.
**
** Internally, each SQLite database handle store two timeout values - the
** Internally, each SQLite database handle stores two timeout values - the
** busy-timeout (used for rollback mode databases, or if the VFS does not
** support blocking locks) and the setlk-timeout (used for blocking locks
** on wal-mode databases). The sqlite3_busy_timeout() method sets both
@@ -3067,7 +3067,7 @@ int sqlite3_setlk_timeout(sqlite3*, int ms, int flags);
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
**
** Definition: A <b>result table</b> is memory data structure created by the
** Definition: A <b>result table</b> is a memory data structure created by the
** [sqlite3_get_table()] interface. A result table records the
** complete query results from one or more queries.
**
@@ -3210,7 +3210,7 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** ^Calling sqlite3_free() with a pointer previously returned
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
** that it might be reused. ^The sqlite3_free() routine is
** a no-op if is called with a NULL pointer. Passing a NULL pointer
** a no-op if it is called with a NULL pointer. Passing a NULL pointer
** to sqlite3_free() is harmless. After being freed, memory
** should neither be read nor written. Even reading previously freed
** memory might result in a segmentation fault or other severe error.
@@ -3228,13 +3228,13 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** sqlite3_free(X).
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
** of at least N bytes in size or NULL if insufficient memory is available.
** ^If M is the size of the prior allocation, then min(N,M) bytes
** of the prior allocation are copied into the beginning of buffer returned
** ^If M is the size of the prior allocation, then min(N,M) bytes of the
** prior allocation are copied into the beginning of the buffer returned
** by sqlite3_realloc(X,N) and the prior allocation is freed.
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
** prior allocation is not freed.
**
** ^The sqlite3_realloc64(X,N) interfaces works the same as
** ^The sqlite3_realloc64(X,N) interface works the same as
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
** of a 32-bit signed integer.
**
@@ -3284,7 +3284,7 @@ sqlite3_uint64 sqlite3_msize(void*);
** was last reset. ^The values returned by [sqlite3_memory_used()] and
** [sqlite3_memory_highwater()] include any overhead
** added by SQLite in its implementation of [sqlite3_malloc()],
** but not overhead added by the any underlying system library
** but not overhead added by any underlying system library
** routines that [sqlite3_malloc()] may call.
**
** ^The memory high-water mark is reset to the current value of
@@ -3736,7 +3736,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** there is no harm in trying.)
**
** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
** <dd>The database is opened [shared cache] enabled, overriding
** <dd>The database is opened with [shared cache] enabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
** The [use of shared cache mode is discouraged] and hence shared cache
@@ -3744,7 +3744,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** this option is a no-op.
**
** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
** <dd>The database is opened [shared cache] disabled, overriding
** <dd>The database is opened with [shared cache] disabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
**
@@ -4079,7 +4079,7 @@ sqlite3_file *sqlite3_database_file_object(const char*);
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
** with N URI parameters key/values pairs in the array P. The result from
** an array P of N URI Key/Value pairs. The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
** <ul>
@@ -4162,7 +4162,7 @@ void sqlite3_free_filename(sqlite3_filename);
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr(E) interface returns the English-language text
** that describes the [result code] E, as UTF-8, or NULL if E is not an
** that describes the [result code] E, as UTF-8, or NULL if E is not a
** result code for which a text error message is available.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
@@ -4170,7 +4170,7 @@ void sqlite3_free_filename(sqlite3_filename);
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token. ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.
** sqlite3_error_offset() assumes that the input SQL is UTF-8.
** ^If the most recent error does not reference a specific token in the input
** SQL, then the sqlite3_error_offset() function returns -1.
**
@@ -4269,8 +4269,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
**
** These constants define various performance limits
** that can be lowered at run-time using [sqlite3_limit()].
** The synopsis of the meanings of the various limits is shown below.
** Additional information is available at [limits | Limits in SQLite].
** A concise description of these limits follows, and additional information
** is available at [limits | Limits in SQLite].
**
** <dl>
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
@@ -4335,7 +4335,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Prepare Flags
**
** These constants define various flags that can be passed into
** These constants define various flags that can be passed into the
** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
** [sqlite3_prepare16_v3()] interfaces.
**
@@ -4422,7 +4422,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string <i>including</i>
** the nul-terminator.
** Note that nByte measure the length of the input in bytes, not
** Note that nByte measures the length of the input in bytes, not
** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
@@ -4556,7 +4556,7 @@ int sqlite3_prepare16_v3(
**
** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory
** is available to hold the result, or if the result would exceed the
** the maximum string length determined by the [SQLITE_LIMIT_LENGTH].
** maximum string length determined by the [SQLITE_LIMIT_LENGTH].
**
** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
@@ -4744,7 +4744,7 @@ typedef struct sqlite3_value sqlite3_value;
**
** The context in which an SQL function executes is stored in an
** sqlite3_context object. ^A pointer to an sqlite3_context object
** is always first parameter to [application-defined SQL functions].
** is always the first parameter to [application-defined SQL functions].
** The application-defined SQL function implementation will pass this
** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
** [sqlite3_aggregate_context()], [sqlite3_user_data()],
@@ -4760,7 +4760,7 @@ typedef struct sqlite3_context sqlite3_context;
** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
** literals may be replaced by a [parameter] that matches one of following
** literals may be replaced by a [parameter] that matches one of the following
** templates:
**
** <ul>
@@ -4805,7 +4805,7 @@ typedef struct sqlite3_context sqlite3_context;
**
** [[byte-order determination rules]] ^The byte-order of
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
** found in first character, which is removed, or in the absence of a BOM
** found in the first character, which is removed, or in the absence of a BOM
** the byte order is the native byte order of the host
** machine for sqlite3_bind_text16() or the byte order specified in
** the 6th parameter for sqlite3_bind_text64().)^
@@ -4825,7 +4825,7 @@ typedef struct sqlite3_context sqlite3_context;
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated. If any NUL characters occurs at byte offsets less than
** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
@@ -5037,7 +5037,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
** table column that is the origin of a particular result column in
** table column that is the origin of a particular result column in a
** [SELECT] statement.
** ^The name of the database or table or column can be returned as
** either a UTF-8 or UTF-16 string. ^The _database_ routines return
@@ -5481,7 +5481,7 @@ int sqlite3_column_type(sqlite3_stmt*, int iCol);
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite3_finalize() returns
** or if the statement has never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
** [extended error code].
@@ -5606,8 +5606,8 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of
** the database schema. This flags is especially recommended for SQL
** used inside of triggers, views, CHECK constraints, or other elements of
** the database schema. This flag is especially recommended for SQL
** functions that have side effects or reveal internal application state.
** Without this flag, an attacker might be able to modify the schema of
** a database file to include invocations of the function with parameters
@@ -5638,7 +5638,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** [user-defined window functions|available here].
**
** ^(If the final parameter to sqlite3_create_function_v2() or
** sqlite3_create_window_function() is not NULL, then it is destructor for
** sqlite3_create_window_function() is not NULL, then it is the destructor for
** the application data pointer. The destructor is invoked when the function
** is deleted, either by being overloaded or when the database connection
** closes.)^ ^The destructor is also invoked if the call to
@@ -5713,7 +5713,7 @@ int sqlite3_create_window_function(
/*
** CAPI3REF: Text Encodings
**
** These constant define integer codes that represent the various
** These constants define integer codes that represent the various
** text encodings supported by SQLite.
*/
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
@@ -5805,7 +5805,7 @@ int sqlite3_create_window_function(
** result.
** Every function that invokes [sqlite3_result_subtype()] should have this
** property. If it does not, then the call to [sqlite3_result_subtype()]
** might become a no-op if the function is used as term in an
** might become a no-op if the function is used as a term in an
** [expression index]. On the other hand, SQL functions that never invoke
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
@@ -5932,7 +5932,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
** that the xUpdate method call was invoked to implement and if
** and the prior [xColumn] method call that was invoked to extracted
** the prior [xColumn] method call that was invoked to extract
** the value for that column returned without setting a result (probably
** because it queried [sqlite3_vtab_nochange()] and found that the column
** was unchanging). ^Within an [xUpdate] method, any value for which
@@ -6038,7 +6038,7 @@ unsigned int sqlite3_value_subtype(sqlite3_value*);
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
** object V and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails. ^If V is a [pointer value], then the result
@@ -6076,7 +6076,7 @@ void sqlite3_value_free(sqlite3_value*);
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call. Changing the
** determined by the N parameter on the first successful call. Changing the
** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
@@ -6238,7 +6238,7 @@ void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
**
** Security Warning: These interfaces should not be exposed in scripting
** languages or in other circumstances where it might be possible for an
** an attacker to invoke them. Any agent that can invoke these interfaces
** attacker to invoke them. Any agent that can invoke these interfaces
** can probably also take control of the process.
**
** Database connection client data is only available for SQLite
@@ -6352,7 +6352,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** pointed to by the 2nd parameter are taken as the application-defined
** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
** appear if the string where NUL terminated. If any NUL characters occur
** appear if the string were NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
@@ -6410,7 +6410,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** string and preferably a string literal. The sqlite3_result_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
** If these routines are called from within the different thread
** If these routines are called from within a different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
@@ -6816,7 +6816,7 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
** for the N-th database on database connection D, or a NULL pointer of N is
** for the N-th database on database connection D, or a NULL pointer if N is
** out of range. An N value of 0 means the main database file. An N of 1 is
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
** databases.
@@ -6911,7 +6911,7 @@ int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_READ state means that the database is currently
** in a read transaction. Content has been read from the database file
** but nothing in the database file has changed. The transaction state
** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are
** no other conflicting concurrent write transactions. The transaction
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
** [COMMIT].</dd>
@@ -6920,7 +6920,7 @@ int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
** in a write transaction. Content has been written to the database file
** but has not yet committed. The transaction state will change to
** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
*/
#define SQLITE_TXN_NONE 0
#define SQLITE_TXN_READ 1
@@ -7201,7 +7201,7 @@ int sqlite3_db_release_memory(sqlite3*);
** CAPI3REF: Impose A Limit On Heap Size
**
** These interfaces impose limits on the amount of heap memory that will be
** by all database connections within a single process.
** used by all database connections within a single process.
**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
@@ -7259,7 +7259,7 @@ int sqlite3_db_release_memory(sqlite3*);
** </ul>)^
**
** The circumstances under which SQLite will enforce the heap limits may
** changes in future releases of SQLite.
** change in future releases of SQLite.
*/
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
@@ -7374,8 +7374,8 @@ int sqlite3_table_column_metadata(
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own. It first tries "sqlite3_extension_init".
** If that does not work, it constructs a name "sqlite3_X_init" where the
** X is consists of the lower-case equivalent of all ASCII alphabetic
** If that does not work, it constructs a name "sqlite3_X_init" where
** X consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
@@ -7446,7 +7446,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
** entry point where as follows:
** entry point were as follows:
**
** <blockquote><pre>
** &nbsp; int xEntryPoint(
@@ -7610,7 +7610,7 @@ struct sqlite3_module {
** virtual table and might not be checked again by the byte code.)^ ^(The
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
** is left in its default setting of false, the constraint will always be
** checked separately in byte code. If the omit flag is change to true, then
** checked separately in byte code. If the omit flag is changed to true, then
** the constraint may or may not be checked in byte code. In other words,
** when the omit flag is true there is no guarantee that the constraint will
** not be checked again using byte code.)^
@@ -7636,7 +7636,7 @@ struct sqlite3_module {
** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
** output to show the idxNum has hex instead of as decimal. Another flag is
** output to show the idxNum as hex instead of as decimal. Another flag is
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
** return at most one row.
**
@@ -7777,7 +7777,7 @@ struct sqlite3_index_info {
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
** when a new virtual table is be being created or reinitialized.
** when a new virtual table is being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
@@ -7942,7 +7942,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
** on *ppBlob after this function it returns.
** on *ppBlob after this function returns.
**
** This function fails with SQLITE_ERROR if any of the following are true:
** <ul>
@@ -8062,7 +8062,7 @@ int sqlite3_blob_close(sqlite3_blob *);
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
** incremental blob I/O routines can only read or overwriting existing
** incremental blob I/O routines can only read or overwrite existing
** blob content; they cannot change the size of a blob.
**
** This routine only works on a [BLOB handle] which has been created
@@ -8212,7 +8212,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
** ^The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
** routine returns NULL if it is unable to allocate the requested
** mutex. The argument to sqlite3_mutex_alloc() must one of these
** mutex. The argument to sqlite3_mutex_alloc() must be one of these
** integer constants:
**
** <ul>
@@ -8445,7 +8445,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
** ^This interface returns a pointer the [sqlite3_mutex] object that
** ^This interface returns a pointer to the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
@@ -8568,7 +8568,7 @@ int sqlite3_test_control(int op, ...);
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords
** recognized by SQLite. Applications can uses these routines to determine
** recognized by SQLite. Applications can use these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
@@ -8736,7 +8736,7 @@ void sqlite3_str_reset(sqlite3_str*);
** content of the dynamic string under construction in X. The value
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
** and might be freed or altered by any subsequent method on the same
** [sqlite3_str] object. Applications must not used the pointer returned
** [sqlite3_str] object. Applications must not use the pointer returned by
** [sqlite3_str_value(X)] after any subsequent method call on the same
** object. ^Applications may change the content of the string returned
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
@@ -8822,7 +8822,7 @@ int sqlite3_status64(
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
** buffer and where forced to overflow to [sqlite3_malloc()]. The
** returned value includes allocations that overflowed because they
** where too large (they were larger than the "sz" parameter to
** were too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
@@ -8906,28 +8906,29 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
** the current value is always zero.)^
** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
** the current value is always zero.)^
** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt>
@@ -8936,10 +8937,10 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** memory used by that pager cache is divided evenly between the attached
** connections.)^ In other words, if none of the pager caches associated
** with the database connection are shared, this request returns the same
** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are
** shared, the value returned by this call will be smaller than that returned
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.</dd>
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -8949,6 +8950,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -8985,7 +8987,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** been written to disk in the middle of a transaction due to the page
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
** additional overhead. This parameter can be used help identify
** additional overhead. This parameter can be used to help identify
** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
@@ -9465,7 +9467,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
** restarted by the next call to sqlite3_backup_step(). ^If the source
** database is modified by the using the same database connection as is used
** database is modified by using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
@@ -9482,7 +9484,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** and may not be used following a call to sqlite3_backup_finish().
**
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
** sqlite3_backup_step() errors occurred, regardless or whether or not
** sqlite3_backup_step() errors occurred, regardless of whether or not
** sqlite3_backup_step() completed.
** ^If an out-of-memory condition or IO error occurred during any prior
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
@@ -10521,14 +10523,14 @@ int sqlite3_stmt_scanstatus(
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
void *pOut /* Result written here */
);
);
int sqlite3_stmt_scanstatus_v2(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
int flags, /* Mask of flags defined below */
void *pOut /* Result written here */
);
);
/*
** CAPI3REF: Prepared Statement Scan Status
@@ -10552,7 +10554,7 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
+8 -6
View File
@@ -1031,8 +1031,8 @@ typedef INT16_TYPE LogEst;
** assuming n is a signed integer type. UMXV(n) is similar for unsigned
** integer types.
*/
#define SMXV(n) ((((i64)1)<<(sizeof(n)-1))-1)
#define UMXV(n) ((((i64)1)<<(sizeof(n)))-1)
#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1)
#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1)
/*
** Round up a number to the next larger multiple of 8. This is used
@@ -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
*/
@@ -1269,7 +1271,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear)
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -2894,7 +2896,7 @@ struct AggInfo {
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
u16 nSortingColumn; /* Number of columns in the sorting index */
u32 nSortingColumn; /* Number of columns in the sorting index */
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
int iFirstReg; /* First register in range for aCol[] and aFunc[] */
@@ -2903,8 +2905,8 @@ struct AggInfo {
Table *pTab; /* Source table */
Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
i16 iColumn; /* Column number within the source table */
i16 iSorterColumn; /* Column number in the sorting index */
int iColumn; /* Column number within the source table */
int iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
+59 -10
View File
@@ -792,6 +792,36 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
return rc;
}
/*
** Send a "statement aborts" message to the error log.
*/
static SQLITE_NOINLINE void sqlite3VdbeLogAbort(
Vdbe *p, /* The statement that is running at the time of failure */
int rc, /* Error code */
Op *pOp, /* Opcode that filed */
Op *aOp /* All opcodes */
){
const char *zSql = p->zSql; /* Original SQL text */
const char *zPrefix = ""; /* Prefix added to SQL text */
int pc; /* Opcode address */
char zXtra[100]; /* Buffer space to store zPrefix */
if( p->pFrame ){
assert( aOp[0].opcode==OP_Init );
if( aOp[0].p4.z!=0 ){
assert( aOp[0].p4.z[0]=='-'
&& aOp[0].p4.z[1]=='-'
&& aOp[0].p4.z[2]==' ' );
sqlite3_snprintf(sizeof(zXtra), zXtra,"/* %s */ ",aOp[0].p4.z+3);
zPrefix = zXtra;
}else{
zPrefix = "/* unknown trigger */ ";
}
}
pc = (int)(pOp - aOp);
sqlite3_log(rc, "statement aborts at %d: %s; [%s%s]",
pc, p->zErrMsg, zPrefix, zSql);
}
/*
** Return the symbolic name for the data type of a pMem
@@ -1317,8 +1347,7 @@ case OP_Halt: {
}else{
sqlite3VdbeError(p, "%s", pOp->p4.z);
}
pcx = (int)(pOp - aOp);
sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql);
sqlite3VdbeLogAbort(p, pOp->p1, pOp, aOp);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -3239,6 +3268,15 @@ op_column_corrupt:
** Take the affinities from the Table object in P4. If any value
** cannot be coerced into the correct type, then raise an error.
**
** If P3==0, then omit checking of VIRTUAL columns.
**
** If P3==1, then omit checking of all generated column, both VIRTUAL
** and STORED.
**
** If P3>=2, then only check column number P3-2 in the table (which will
** be a VIRTUAL column) against the value in reg[P1]. In this case,
** P2 will be 1.
**
** This opcode is similar to OP_Affinity except that this opcode
** forces the register type to the Table column type. This is used
** to implement "strict affinity".
@@ -3252,8 +3290,8 @@ op_column_corrupt:
**
** <ul>
** <li> P2 should be the number of non-virtual columns in the
** table of P4.
** <li> Table P4 should be a STRICT table.
** table of P4 unless P3>1, in which case P2 will be 1.
** <li> Table P4 is a STRICT table.
** </ul>
**
** If any precondition is false, an assertion fault occurs.
@@ -3262,16 +3300,28 @@ case OP_TypeCheck: {
Table *pTab;
Column *aCol;
int i;
int nCol;
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
assert( pTab->nNVCol==pOp->p2 );
assert( pOp->p3>=0 && pOp->p3<pTab->nCol+2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
for(i=0; i<pTab->nCol; i++){
if( aCol[i].colFlags & COLFLAG_GENERATED ){
if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
if( pOp->p3<2 ){
assert( pTab->nNVCol==pOp->p2 );
i = 0;
nCol = pTab->nCol;
}else{
i = pOp->p3-2;
nCol = i+1;
assert( i<pTab->nCol );
assert( aCol[i].colFlags & COLFLAG_VIRTUAL );
assert( pOp->p2==1 );
}
for(; i<nCol; i++){
if( (aCol[i].colFlags & COLFLAG_GENERATED)!=0 && pOp->p3<2 ){
if( (aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ) continue;
if( pOp->p3 ){ pIn1++; continue; }
}
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
@@ -9161,8 +9211,7 @@ abort_due_to_error:
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: %s; [%s]",
(int)(pOp - aOp), p->zErrMsg, p->zSql);
sqlite3VdbeLogAbort(p, rc, pOp, aOp);
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
+5
View File
@@ -2192,6 +2192,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
if( p->pPk ){
iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
}else if( iIdx >= p->pTab->nCol ){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_old_out;
}else{
iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
@@ -2347,6 +2350,8 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
}else if( iIdx >= p->pTab->nCol ){
return SQLITE_MISUSE_BKPT;
}else{
iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
+4
View File
@@ -3781,6 +3781,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
pWal->iReCksum = 0;
}
return rc;
}
@@ -3828,6 +3829,9 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
if( pWal->iReCksum>pWal->hdr.mxFrame ){
pWal->iReCksum = 0;
}
}
return rc;
+5 -4
View File
@@ -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);
+3
View File
@@ -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>" */
+27 -12
View File
@@ -931,30 +931,42 @@ 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) */
assert( pSrc!=0 );
if( pExpr->op==TK_IS
&& pSrc->nSrc
&& (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
){
return 0; /* (4) */
}
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
return 0;
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 +1124,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 +1234,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;
}
+10
View File
@@ -488,11 +488,21 @@ proc preupdate_hook {args} {
set type [lindex $args 0]
eval lappend ::preupdate $args
if {$type != "INSERT"} {
set x [catch {db preupdate old [db preupdate count]}]
if {!$x} {
lappend "ERROR: sqlite3_preupdate_old() accepted an out-of-bounds\
column index"
}
for {set i 0} {$i < [db preupdate count]} {incr i} {
lappend ::preupdate [db preupdate old $i]
}
}
if {$type != "DELETE"} {
set x [catch {db preupdate new [db preupdate count]}]
if {!$x} {
lappend "ERROR: sqlite3_preupdate_old() accepted an out-of-bounds\
column index"
}
for {set i 0} {$i < [db preupdate count]} {incr i} {
set rc [catch { db preupdate new $i } v]
lappend ::preupdate $v
+27
View File
@@ -1342,4 +1342,31 @@ 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
+97
View File
@@ -162,4 +162,101 @@ do_execsql_test strict1-8.2 {
SELECT *, '|' FROM t1;
} {/5.0 5.0 4.6116\d*e\+18 4.6116\d+e\+18 |/}
# 2025-06-18 https://sqlite.org/forum/forumpost/6caf195248a849e4
#
# Enforce STRICT table type constraints on STORED generated columns
#
do_execsql_test strict1-9.1 {
CREATE TABLE strict (
k INTEGER PRIMARY KEY,
c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) STORED,
c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) STORED,
c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) STORED,
c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) STORED,
c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) STORED
) STRICT;
INSERT INTO strict(k) VALUES(11);
INSERT INTO strict(k) VALUES(12);
INSERT INTO strict(k) VALUES(22);
INSERT INTO strict(k) VALUES(31);
INSERT INTO strict(k) VALUES(32);
INSERT INTO strict(k) VALUES(33);
INSERT INTO strict(k) VALUES(44);
PRAGMA integrity_check;
} {ok}
do_catchsql_test strict1-9.2.13 {
INSERT INTO strict(k) VALUES(13);
} {1 {cannot store TEXT value in REAL column strict.c1}}
do_catchsql_test strict1-9.2.14 {
INSERT INTO strict(k) VALUES(14);
} {1 {cannot store BLOB value in REAL column strict.c1}}
do_catchsql_test strict1-9.2.21 {
INSERT INTO strict(k) VALUES(21);
} {1 {cannot store REAL value in INT column strict.c2}}
do_catchsql_test strict1-9.2.23 {
INSERT INTO strict(k) VALUES(23);
} {1 {cannot store TEXT value in INT column strict.c2}}
do_catchsql_test strict1-9.2.24 {
INSERT INTO strict(k) VALUES(24);
} {1 {cannot store BLOB value in INT column strict.c2}}
do_catchsql_test strict1-9.2.34 {
INSERT INTO strict(k) VALUES(34);
} {1 {cannot store BLOB value in TEXT column strict.c3}}
do_catchsql_test strict1-9.2.41 {
INSERT INTO strict(k) VALUES(41);
} {1 {cannot store REAL value in BLOB column strict.c4}}
do_catchsql_test strict1-9.2.42 {
INSERT INTO strict(k) VALUES(42);
} {1 {cannot store INT value in BLOB column strict.c4}}
do_catchsql_test strict1-9.2.43 {
INSERT INTO strict(k) VALUES(43);
} {1 {cannot store TEXT value in BLOB column strict.c4}}
do_execsql_test strict1-9.3 {
DROP TABLE strict;
CREATE TABLE strict (
k INTEGER PRIMARY KEY,
c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) VIRTUAL,
c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) VIRTUAL,
c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) VIRTUAL,
c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) VIRTUAL,
c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) VIRTUAL
) STRICT;
INSERT INTO strict(k) VALUES(11);
INSERT INTO strict(k) VALUES(12);
INSERT INTO strict(k) VALUES(22);
INSERT INTO strict(k) VALUES(31);
INSERT INTO strict(k) VALUES(32);
INSERT INTO strict(k) VALUES(33);
INSERT INTO strict(k) VALUES(44);
PRAGMA integrity_check;
} {ok}
do_catchsql_test strict1-9.4.13 {
INSERT INTO strict(k) VALUES(13);
} {1 {cannot store TEXT value in REAL column strict.c1}}
do_catchsql_test strict1-9.4.14 {
INSERT INTO strict(k) VALUES(14);
} {1 {cannot store BLOB value in REAL column strict.c1}}
do_catchsql_test strict1-9.4.21 {
INSERT INTO strict(k) VALUES(21);
} {1 {cannot store REAL value in INT column strict.c2}}
do_catchsql_test strict1-9.4.23 {
INSERT INTO strict(k) VALUES(23);
} {1 {cannot store TEXT value in INT column strict.c2}}
do_catchsql_test strict1-9.4.24 {
INSERT INTO strict(k) VALUES(24);
} {1 {cannot store BLOB value in INT column strict.c2}}
do_catchsql_test strict1-9.4.34 {
INSERT INTO strict(k) VALUES(34);
} {1 {cannot store BLOB value in TEXT column strict.c3}}
do_catchsql_test strict1-9.4.41 {
INSERT INTO strict(k) VALUES(41);
} {1 {cannot store REAL value in BLOB column strict.c4}}
do_catchsql_test strict1-9.4.42 {
INSERT INTO strict(k) VALUES(42);
} {1 {cannot store INT value in BLOB column strict.c4}}
do_catchsql_test strict1-9.4.43 {
INSERT INTO strict(k) VALUES(43);
} {1 {cannot store TEXT value in BLOB column strict.c4}}
finish_test
+148
View File
@@ -16,6 +16,7 @@ source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
set testprefix walcksum
# Read and return the contents of file $filename. Treat the content as
# binary data.
@@ -331,5 +332,152 @@ do_test walcksum-2.1 {
catch { db close }
catch { db2 close }
#-------------------------------------------------------------------------
# Test cases based on the bug reported at:
#
# <https://sqlite.org/forum/forumpost/b490f726db>
#
reset_db
do_execsql_test 3.0 {
PRAGMA auto_vacuum = 0;
PRAGMA synchronous = NORMAL;
PRAGMA journal_mode = WAL;
PRAGMA cache_size = 1;
CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT);
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES(1, randomblob(2048), 'one');
} {wal 0 2 2}
do_execsql_test 3.1 {
BEGIN;
INSERT INTO t1 VALUES(2, randomblob(2048), 'two');
SAVEPOINT one;
INSERT INTO t1 VALUES(3, randomblob(2048), 'three');
INSERT INTO t1 VALUES(4, randomblob(2048), 'four');
INSERT INTO t1 VALUES(5, randomblob(2048), 'five');
INSERT INTO t1 VALUES(6, randomblob(2048), 'six');
INSERT INTO t1 VALUES(7, randomblob(2048), 'seven');
UPDATE t1 SET b=randomblob(2048) WHERE i=5;
UPDATE t1 SET b=randomblob(2048) WHERE i=6;
UPDATE t1 SET b=randomblob(2048) WHERE i=7;
ROLLBACK TO one;
INSERT INTO t1 VALUES(8, NULL, 'eight');
COMMIT;
} {}
do_execsql_test 3.2 {
SELECT i, t FROM t1
} {1 one 2 two 8 eight}
forcecopy test.db test2.db
forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
do_test 1.3 {
execsql {
SELECT i, t FROM t1
} db2
} {1 one 2 two 8 eight}
catch { db2 close }
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
PRAGMA auto_vacuum = 0;
PRAGMA synchronous = NORMAL;
PRAGMA journal_mode = WAL;
PRAGMA cache_size = 1;
CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT);
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES(1, randomblob(2048), 'one');
} {wal 0 2 2}
do_execsql_test 4.1.1 {
SAVEPOINT one;
INSERT INTO t1 VALUES(2, randomblob(2048), 'two');
INSERT INTO t1 VALUES(3, randomblob(2048), 'three');
INSERT INTO t1 VALUES(4, randomblob(2048), 'four');
INSERT INTO t1 VALUES(5, randomblob(2048), 'five');
INSERT INTO t1 VALUES(6, randomblob(2048), 'six');
INSERT INTO t1 VALUES(7, randomblob(2048), 'seven');
UPDATE t1 SET b=randomblob(2048) WHERE i=5;
UPDATE t1 SET b=randomblob(2048) WHERE i=6;
UPDATE t1 SET b=randomblob(2048) WHERE i=7;
}
do_execsql_test 4.1.2 {
ROLLBACK TO one;
INSERT INTO t1 VALUES(8, NULL, 'eight');
RELEASE one;
} {}
do_execsql_test 4.2 {
SELECT i, t FROM t1
} {1 one 8 eight}
forcecopy test.db test2.db
forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
do_test 4.3 {
execsql {
SELECT i, t FROM t1
} db2
} {1 one 8 eight}
catch { db2 close }
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
PRAGMA auto_vacuum = 0;
PRAGMA synchronous = NORMAL;
PRAGMA journal_mode = WAL;
PRAGMA cache_size = 1;
CREATE TABLE t1 (i INTEGER PRIMARY KEY, b BLOB, t TEXT);
INSERT INTO t1 VALUES(1, randomblob(2048), 'one');
INSERT INTO t1 VALUES(2, randomblob(2048), 'two');
INSERT INTO t1 VALUES(3, randomblob(2048), 'three');
PRAGMA wal_checkpoint;
} {wal 0 14 14}
do_execsql_test 5.1 {
BEGIN;
SELECT count(*) FROM t1;
SAVEPOINT one;
INSERT INTO t1 VALUES(4, randomblob(2048), 'four');
INSERT INTO t1 VALUES(5, randomblob(2048), 'five');
INSERT INTO t1 VALUES(6, randomblob(2048), 'six');
INSERT INTO t1 VALUES(7, randomblob(2048), 'seven');
ROLLBACK TO one;
INSERT INTO t1 VALUES(8, randomblob(2048), 'eight');
INSERT INTO t1 VALUES(9, randomblob(2048), 'nine');
COMMIT;
} {3}
forcecopy test.db test2.db
forcecopy test.db-wal test2.db-wal
sqlite3 db2 test2.db
do_test 5.2 {
execsql {
SELECT i, t FROM t1
} db2
} {1 one 2 two 3 three 8 eight 9 nine}
db2 close
do_execsql_test 5.3 {
SELECT i, t FROM t1
} {1 one 2 two 3 three 8 eight 9 nine}
finish_test
+43 -31
View File
@@ -17,6 +17,7 @@ Options:
--uninstall Uninstall the extension
--version-check Check extension version against this source tree
--destdir DIR Installation root (used by "make install DESTDIR=...")
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
Other options are retained and passed through into the compiler.}
@@ -29,6 +30,7 @@ set versioncheck 0
set CC {}
set OPTS {}
set DESTDIR ""; # --destdir "$(DESTDIR)"
set tclConfigSh ""; # --tclConfig.sh FILE
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="--install-only"} {
@@ -56,6 +58,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
} elseif {$a0=="--destdir" && $ii+1<[llength $argv]} {
incr ii
set DESTDIR [lindex $argv $ii]
} elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
incr ii
set tclConfigSh [lindex $argv $ii]
} elseif {[string match -* $a0]} {
append OPTS " $a0"
} else {
@@ -88,39 +93,46 @@ if {$tcl_platform(platform) eq "windows"} {
}
set OUT tclsqlite3.dll
} else {
# Figure out the location of the tclConfig.sh file used by the
# tclsh that is executing this script.
#
if {[catch {
set LIBDIR [tcl::pkgconfig get libdir,install]
}]} {
puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
exit 1
}
if {![file exists $LIBDIR]} {
puts stderr "$argv0: cannot find the tclConfig.sh file."
puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
does not exist."
exit 1
}
if {![file exists $LIBDIR/tclConfig.sh]
|| [file size $LIBDIR/tclConfig.sh]<5000} {
set n1 $LIBDIR/tcl$::tcl_version
if {[file exists $n1/tclConfig.sh]
&& [file size $n1/tclConfig.sh]>5000} {
set LIBDIR $n1
} else {
puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
exit 1
}
}
# Read the tclConfig.sh file into the $tclConfig variable
#
#puts "using $LIBDIR/tclConfig.sh"
set fd [open $LIBDIR/tclConfig.sh rb]
set tclConfig [read $fd]
close $fd
if {"" eq $tclConfigSh} {
# Figure out the location of the tclConfig.sh file used by the
# tclsh that is executing this script.
#
if {[catch {
set LIBDIR [tcl::pkgconfig get libdir,install]
}]} {
puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
exit 1
}
if {![file exists $LIBDIR]} {
puts stderr "$argv0: cannot find the tclConfig.sh file."
puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
does not exist."
exit 1
}
if {![file exists $LIBDIR/tclConfig.sh]
|| [file size $LIBDIR/tclConfig.sh]<5000} {
set n1 $LIBDIR/tcl$::tcl_version
if {[file exists $n1/tclConfig.sh]
&& [file size $n1/tclConfig.sh]>5000} {
set LIBDIR $n1
} else {
puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
exit 1
}
}
#puts "using $LIBDIR/tclConfig.sh"
set fd [open $LIBDIR/tclConfig.sh rb]
set tclConfig [read $fd]
close $fd
} else {
# User-provided tclConfig.sh
#
set fd [open $tclConfigSh rb]
set tclConfig [read $fd]
close $fd
}
# Extract parameter we will need from the tclConfig.sh file
#