Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 280559b446 | |||
| e2e81e6983 | |||
| e24f20a4f5 | |||
| 311d73efc2 | |||
| c52e9d97d4 | |||
| fbf1c0526e | |||
| e77e589a35 | |||
| 981022b7ff | |||
| a67c71224f | |||
| 66cd200ede | |||
| 513fff88c4 | |||
| fe182f74b2 | |||
| b1560be826 | |||
| 28789029ee | |||
| f453e8d84e | |||
| 4c1c400d64 | |||
| 87c807c6dd | |||
| b5aa9593ac | |||
| 5806a922ba | |||
| 427d2cd57d | |||
| db37e6097c | |||
| 6fcb7f22a1 | |||
| 2f7f948fa7 | |||
| 0cdde5b44f | |||
| a0c6de56ba | |||
| b68d63158a | |||
| 59de42763f | |||
| 37794b4ad0 | |||
| 397b82cf0f | |||
| 92d1bec584 | |||
| a5c484b432 | |||
| 64159096b8 | |||
| ab9c91ae82 | |||
| bcf25e7129 | |||
| 2be0a700ff | |||
| 3a26f72e20 | |||
| d961d49971 | |||
| 9a9140ba59 | |||
| 12bd8ea09a | |||
| 1e9baaf743 | |||
| df8aa3745a | |||
| 110055cd6c | |||
| 79a746b1f2 | |||
| 9ebf9d358b | |||
| e68aa0e44b | |||
| 6e1c2f0483 | |||
| 1ea6a53762 | |||
| 86d9c2d9f3 | |||
| d3a13f7d25 | |||
| 6ed5aa4b9b | |||
| 67f708298f |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {}}
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
a95d126e1330e1b83f42b51f97c4c216622cf38062f3b5d72ccb76313187e850
|
||||
d86eb16283c4b573c506d4faa422d5d9aeb6abc279d8e6a8e2104737162d417f
|
||||
|
||||
+16
-8
@@ -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
@@ -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, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
if( ExprHasProperty(pExpr, EP_Subquery) && p5!=SQLITE_NULLEQ ){
|
||||
addrIsNull = exprComputeOperands(pParse, pExpr,
|
||||
&r1, &r2, ®Free1, ®Free2);
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
}
|
||||
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, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
if( ExprHasProperty(pExpr, EP_Subquery) ){
|
||||
addrIsNull = exprComputeOperands(pParse, pExpr,
|
||||
&r1, &r2, ®Free1, ®Free2);
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
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, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
|
||||
addrIsNull = exprComputeOperands(pParse, pExpr,
|
||||
&r1, &r2, ®Free1, ®Free2);
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
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, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
|
||||
addrIsNull = exprComputeOperands(pParse, pExpr,
|
||||
&r1, &r2, ®Free1, ®Free2);
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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>
|
||||
** 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
@@ -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
@@ -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 ){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user