Compare commits
247 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f380599476 | |||
| de739c3450 | |||
| c597ed79d1 | |||
| f305e1921b | |||
| 3dbab77bf1 | |||
| da18b56b25 | |||
| ecd9748590 | |||
| 6ae9949399 | |||
| 37e253208f | |||
| b869ed6b06 | |||
| ccf23dadea | |||
| d3dc8e5ae5 | |||
| badc42fd74 | |||
| fd9eba554a | |||
| 8154476ff8 | |||
| d258b93356 | |||
| 3ef3ecdf8a | |||
| 632b618063 | |||
| d58b463ffb | |||
| 1a0555610d | |||
| 079f8dc682 | |||
| 4da2ddf50e | |||
| fdf746967c | |||
| c7ddaf2479 | |||
| 45b4213160 | |||
| cbbeddbd67 | |||
| db5aebce43 | |||
| 4d3f3c7070 | |||
| bc94e5dbb6 | |||
| d0fd0cc2fa | |||
| 1192d6f5b1 | |||
| a20f63e0ef | |||
| a497743e24 | |||
| a2d992a000 | |||
| 62cd986418 | |||
| 4dd11e33e4 | |||
| de94ec87fc | |||
| e087d0f266 | |||
| b6ea7f0550 | |||
| e4ba14bc40 | |||
| b969f8c2f1 | |||
| c1bf93ecb6 | |||
| fd88eed8fa | |||
| f77a5af2b3 | |||
| 6df919b723 | |||
| cb388ec9a3 | |||
| 0e30396fe2 | |||
| fc12461f5c | |||
| 3cfe5c3dad | |||
| d3265d1473 | |||
| 61d9f8f881 | |||
| 397a3c4a04 | |||
| 0c3b3f93d1 | |||
| 9f3208e1f8 | |||
| 672b87d0d5 | |||
| 02dc8d0c5f | |||
| 13b63ed930 | |||
| 6166c2ee48 | |||
| a3e7c597b5 | |||
| cf632ddb7e | |||
| a8fdc0e0c0 | |||
| 8b803c716c | |||
| 077be44cc2 | |||
| 1f9c2ed674 | |||
| 887fa2fe83 | |||
| 73da727480 | |||
| 94f56f5800 | |||
| 93d7dc266b | |||
| 1d2f71ce4a | |||
| 431b85963f | |||
| 054aff6272 | |||
| 657721fd32 | |||
| e14c16189e | |||
| 88be32c9d3 | |||
| cf420c9910 | |||
| 5f6a6fa6f0 | |||
| eb83e32cef | |||
| 79db323ce1 | |||
| 219acc9f4f | |||
| 8bee9cd3cf | |||
| f8ca671997 | |||
| 15670b1b3f | |||
| df300e8e51 | |||
| 2c8f97159c | |||
| 993bc6b171 | |||
| 86d1ef8bf7 | |||
| e707e68420 | |||
| 1788b7b719 | |||
| d4c4e91674 | |||
| 4f95a67b0c | |||
| 31c19f587d | |||
| bfc0414b9a | |||
| f9db8b2350 | |||
| ad37ec3aa2 | |||
| 4b77e36dec | |||
| 3ece90420d | |||
| 8ff6523afd | |||
| 821323938d | |||
| e572525306 | |||
| 082aebfa0d | |||
| 6f842b8da4 | |||
| 3d84988efe | |||
| 128f65ca6d | |||
| 79a4591478 | |||
| 14fa0e9b86 | |||
| b4d42c6702 | |||
| 3ed7926e2f | |||
| 8923a68c5f | |||
| c94c21d0a6 | |||
| fb7c642990 | |||
| 2bc658c387 | |||
| f02745088c | |||
| 596008f078 | |||
| 1c9e8ca88b | |||
| c70fbd39f9 | |||
| 9db9f18985 | |||
| f107c52d4c | |||
| 7509c6351e | |||
| 57e46429fe | |||
| a9c2e08087 | |||
| 7f1f4c803d | |||
| bd13573a96 | |||
| 0cadeecf6f | |||
| ad52288e0d | |||
| d5f0e01593 | |||
| 3e663bd8c7 | |||
| 97901bbd69 | |||
| c549e28c67 | |||
| 90dae0d01d | |||
| 0a0a52ae93 | |||
| e1d4680fdd | |||
| 532e506d18 | |||
| c9bed48c3c | |||
| 6b4eb6725f | |||
| 6176034151 | |||
| 7471b5d6c0 | |||
| 1fc7341ad2 | |||
| 6af10b0efd | |||
| 70d1e3e75e | |||
| 74006fdcdb | |||
| 4b9f9d6794 | |||
| 39b2fe7e5b | |||
| 01ec60bb87 | |||
| e2dbd0a578 | |||
| df7b22790e | |||
| 50811f74e0 | |||
| d7bf8233ff | |||
| 455486bbc4 | |||
| ba9092e228 | |||
| 67d4e0226f | |||
| 323b3fc121 | |||
| 78279e2550 | |||
| 4e4962f6b3 | |||
| ed95a9d103 | |||
| e791e7c7a0 | |||
| 2545d9c201 | |||
| 2a07c6de2c | |||
| 68b07ddd41 | |||
| 4b69e7704b | |||
| e17ab401f0 | |||
| 57ee077c5e | |||
| c7edd22456 | |||
| 8606a52934 | |||
| 5c6404aa77 | |||
| 429369f4aa | |||
| 9529894a29 | |||
| c4c47a49a8 | |||
| ee7f6f29fc | |||
| c3b52dff53 | |||
| 30af54043e | |||
| 4ebed2a4e5 | |||
| 532ed30ab2 | |||
| 5e99eeb3d8 | |||
| d3abfd77f5 | |||
| 63984b6ab7 | |||
| 93082e5589 | |||
| f6b807a022 | |||
| 8c6a6b85db | |||
| 9f76fb019e | |||
| 29997b4731 | |||
| f0c8e27670 | |||
| d6c985ad0b | |||
| 1696740fdc | |||
| 2cefd5954a | |||
| 8895c50403 | |||
| a2116f86b0 | |||
| 1e472f2d32 | |||
| e3dbf75160 | |||
| ade9289540 | |||
| dfba4eb34a | |||
| b57d2a5a51 | |||
| 84c1079220 | |||
| c8d866294b | |||
| f0baddb205 | |||
| ec2ea68d1f | |||
| c71e6dd054 | |||
| 9efde40a5d | |||
| afef1f2923 | |||
| 09f37099a7 | |||
| 846fbd6653 | |||
| 1b14a925dc | |||
| 526acc1834 | |||
| d962afef2d | |||
| 839433d457 | |||
| 395ac6c1bc | |||
| e9d0bc6b68 | |||
| 483f0ef13c | |||
| ab6a63ec67 | |||
| 57ed7f322f | |||
| 34c2c8dc47 | |||
| 3f9df1f5fb | |||
| 2eeac123c8 | |||
| 64a123a216 | |||
| a10e79d91a | |||
| 6e93d28950 | |||
| 008395614a | |||
| d20673a95f | |||
| f02d100e08 | |||
| 4c8f0621fd | |||
| dd1e2c39bc | |||
| 6abc21cfb8 | |||
| 20079bb358 | |||
| 3d6fa49c54 | |||
| 4df365e5a7 | |||
| 9d8bf6f04a | |||
| c0026ff7a6 | |||
| 1e3f888acf | |||
| 2d4dfbccdc | |||
| 6142310e08 | |||
| 42ae7e7f34 | |||
| 57cf5c2dfc | |||
| a212476ad2 | |||
| 0523cfda5a | |||
| d08caad3a5 | |||
| bc68ec78de | |||
| 28456958ca | |||
| 3b27ffa534 | |||
| fc2c730c87 | |||
| cd28797117 | |||
| c8b130f255 | |||
| 7a0a0a22e7 | |||
| 504cfd5ec7 | |||
| 9d950aa13b | |||
| b709ba8108 | |||
| 01e1be854b | |||
| 70868a5ae3 | |||
| d0065c8118 |
@@ -1766,6 +1766,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\analyze.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base64.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base85.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\completion.c
|
||||
@@ -2342,6 +2343,7 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
$(TOP)\ext\intck\sqlite3intck.h \
|
||||
$(TOP)\ext\misc\analyze.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
$(TOP)\ext\misc\base85.c \
|
||||
@@ -2741,6 +2743,9 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
$(AUXTEST).exe: $(TOP)\test\c\$(AUXTEST).c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\test\c\$(AUXTEST).c sqlite3.lo /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
THREADTEST3_SRC = \
|
||||
$(TOP)\test\threadtest3.c \
|
||||
$(TOP)\test\tt3_checkpoint.c \
|
||||
|
||||
@@ -33,10 +33,11 @@ verify its integrity, there are hints on how to do that in the
|
||||
|
||||
## Contacting The SQLite Developers
|
||||
|
||||
The preferred way to ask questions or make comments about SQLite or to
|
||||
report bugs against SQLite is to visit the
|
||||
[SQLite Forum](https://sqlite.org/forum) at <https://sqlite.org/forum/>.
|
||||
Anonymous postings are permitted.
|
||||
The preferred way to ask questions or make comments about SQLite is to
|
||||
visit the [SQLite Forum](https://sqlite.org/forum) at
|
||||
<https://sqlite.org/forum/>. Anonymous postings are permitted. For
|
||||
bug reports, please use the [SQLite bugs
|
||||
forum](https://sqlite.org/bugs) at <https://sqlite.org/bugs>.
|
||||
|
||||
If you think you have found a bug that has security implications and
|
||||
you do not want to report it on the public forum, you can send a private
|
||||
@@ -80,8 +81,8 @@ Then run commands like this:
|
||||
fossil open https://sqlite.org/src
|
||||
|
||||
The initial "fossil open" command will take two or three minutes. Afterwards,
|
||||
you can do fast, bandwidth-efficient updates to the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
you can do fast, bandwidth-efficient updates to whatever versions of SQLite you
|
||||
like. Some examples:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
+1657
-972
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -2028,7 +2028,7 @@ array set proj__Cache {}
|
||||
# Returns a cache key for the given argument:
|
||||
#
|
||||
# integer: relative call stack levels to get the scope name of for
|
||||
# use as a key. [proj-scope [expr {1 + $arg + addLevel}]] is
|
||||
# use as a key. [proj-scope [expr {1 + $arg + $addLevel}]] is
|
||||
# then used to generate the key. i.e. the default of 0 uses the
|
||||
# calling scope's name as the key.
|
||||
#
|
||||
@@ -2226,7 +2226,7 @@ proc proj-coalesce {args} {
|
||||
#
|
||||
# Pragmas:
|
||||
#
|
||||
# Passing :PRAGMAS to this function may modify how it works. The
|
||||
# The prototype list may contain :PRAGMAS to modify how it works. The
|
||||
# following pragmas are supported (note the leading ":"):
|
||||
#
|
||||
# :all-flags indicates that the whole input list should be scanned,
|
||||
|
||||
+40
-18
@@ -1067,7 +1067,7 @@ proc sqlite-get-readline-dir-list {} {
|
||||
}
|
||||
*-haiku {
|
||||
lappend dirs /boot/system/develop/headers
|
||||
if {[opt-val with-readline-ldflags] in {auto ""}} {
|
||||
if {![opt-bool editline] && [opt-val with-readline-ldflags] in {auto ""}} {
|
||||
# If the user did not supply their own --with-readline-ldflags
|
||||
# value, hijack that flag to inject options which are known to
|
||||
# work on Haiku OS installations.
|
||||
@@ -1094,16 +1094,30 @@ proc sqlite-get-readline-dir-list {} {
|
||||
# - HAVE_LINENOISE to 0, 1, or 2
|
||||
# - HAVE_EDITLINE to 0 or 1
|
||||
#
|
||||
# Only one of ^^^ those will be set to non-0.
|
||||
# Those will be set as follows:
|
||||
#
|
||||
# HAVE_LINENOISE=0, HAVE_EDITLINE=0, HAVE_READLINE=0: no line editing
|
||||
#
|
||||
# HAVE_LINENOISE>0: 1=antirez flavor, 2=msteveb flavor
|
||||
#
|
||||
# HAVE_EDITLINE=0, HAVE_READLINE=1: use GNU readline
|
||||
#
|
||||
# HAVE_EDITLINE=1, HAVE_READLINE=1: use BSD editline header
|
||||
# <readline/readline.h>.
|
||||
#
|
||||
# HAVE_EDITLINE=1, HAVE_READLINE=0: use BSD editline header
|
||||
# <editline/readline.h>.
|
||||
#
|
||||
# Other defines it sets:
|
||||
#
|
||||
# - LDFLAGS_READLINE = linker flags or empty string
|
||||
#
|
||||
# - CFLAGS_READLINE = compilation flags for clients or empty string.
|
||||
#
|
||||
# Note that LDFLAGS_READLINE and CFLAGS_READLINE may refer to
|
||||
# linenoise or editline, not necessarily libreadline. In some cases
|
||||
# it will set HAVE_READLINE=1 when it's really using editline, for
|
||||
# reasons described in this function's comments.
|
||||
# Both LDFLAGS_READLINE and CFLAGS_READLINE may refer to linenoise or
|
||||
# editline, not necessarily libreadline. In some cases it will set
|
||||
# HAVE_READLINE=1 when it's really using editline, for reasons
|
||||
# described in this function's comments.
|
||||
#
|
||||
# Returns a string describing which line-editing approach to use, or
|
||||
# "none" if no option is available.
|
||||
@@ -1141,7 +1155,7 @@ proc sqlite-check-line-editing {} {
|
||||
# If none of --with-linenoise, --enable-readline, or --enable-editline
|
||||
# are provided, but there exists a directory "linenoise" at $HOME or
|
||||
# a sibling of the build or source directory, then try to use that linenoise
|
||||
# direcctory.
|
||||
# directory.
|
||||
#
|
||||
if {"" eq $dirLn
|
||||
&& ![proj-opt-was-provided readline]
|
||||
@@ -1305,14 +1319,18 @@ proc sqlite-check-line-editing {} {
|
||||
|
||||
# If we found a library, configure the build to use it...
|
||||
if {"" ne $rlLib} {
|
||||
if {"editline" eq $editLibName && "HAVE_READLINE" eq $editLibDef} {
|
||||
# Alert the user that, despite outward appearances, we won't be
|
||||
# linking to the GPL'd libreadline. Presumably that distinction is
|
||||
# significant for those using --editline.
|
||||
proj-indented-notice {
|
||||
NOTE: the local libedit uses <readline/readline.h> so we
|
||||
will compile with -DHAVE_READLINE=1 but will link with
|
||||
libedit.
|
||||
if {"editline" eq $editLibName} {
|
||||
# sqlite-add-shell-opt -DEL_WIDECHAR=1;
|
||||
if {"HAVE_READLINE" eq $editLibDef} {
|
||||
sqlite-add-shell-opt -DHAVE_EDITLINE=1
|
||||
# Alert the user that, despite outward appearances, we won't be
|
||||
# linking to the GPL'd libreadline. Presumably that distinction is
|
||||
# significant for those using --editline.
|
||||
proj-indented-notice {
|
||||
NOTE: the local libedit uses <readline/readline.h> so we
|
||||
will compile with -DHAVE_READLINE=1 but will link with
|
||||
libedit.
|
||||
}
|
||||
}
|
||||
}
|
||||
set rlLib [join $rlLib]
|
||||
@@ -1745,8 +1763,12 @@ proc sqlite-handle-env-quirks {} {
|
||||
set autoDll 0; # true if --out-implib/--dll-basename should be implied
|
||||
set host [get-define host]
|
||||
switch -glob -- $host {
|
||||
*apple* -
|
||||
*darwin* { set instName darwin }
|
||||
*-*-darwin* {
|
||||
set instName darwin
|
||||
# We don't look for *apple* because:
|
||||
# https://sqlite.org/forum/forumpost/7b218c3c9f207646
|
||||
# There's at least one Linux out there which matches *apple*.
|
||||
}
|
||||
default {
|
||||
set x [sqlite-env-is-unix-on-windows $host]
|
||||
if {"" ne $x} {
|
||||
@@ -2042,7 +2064,7 @@ proc sqlite-check-tcl {} {
|
||||
}
|
||||
}
|
||||
if {![file-isexec $with_tclsh]} {
|
||||
proj-warn "Cannot find a usable tclsh (tried: $tryThese)
|
||||
proj-warn "Cannot find a usable tclsh (tried: $tryThese)"
|
||||
}
|
||||
}
|
||||
define TCLSH_CMD $with_tclsh
|
||||
|
||||
+6
-1
@@ -33,7 +33,7 @@
|
||||
The testrunner.tcl program is a Tcl script used to run multiple SQLite
|
||||
tests in parallel, thus reducing testing time on multi-core machines.
|
||||
The testrunner.tcl supports running tests that based on `testfixture`,
|
||||
`sqlite3`, and `fuzzcheck`.
|
||||
`sqlite3`, `fuzzcheck`, and C programs found in test/c.
|
||||
|
||||
<a name="runtr"></a>
|
||||
## 1.1 Running testrunner.tcl
|
||||
@@ -59,11 +59,16 @@ up front.
|
||||
The standard Makefiles for SQLite include targets that invoke
|
||||
testrunner.tcl. So the following commands also run testrunner.tcl:
|
||||
|
||||
* `make test`
|
||||
* `make devtest`
|
||||
* `make releasetest`
|
||||
* `make sdevtest`
|
||||
* `make testrunner`
|
||||
|
||||
Since SQLite 3.53.0, there is a "<tt>make.bat</tt>" script in the root
|
||||
of the source tree that causes the "make" command to work on Windows.
|
||||
There is no need to do something different using "nmake" on Windows.
|
||||
|
||||
<a name="outputs"></a>
|
||||
## 1.3 Outputs from testrunner.tcl
|
||||
|
||||
|
||||
+1
-1
@@ -341,7 +341,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
/* State 3. The integer just read is a column number. */
|
||||
default: assert( eState==3 );
|
||||
iCol = (int)v;
|
||||
if( iCol<1 ){
|
||||
if( iCol<1 || iCol>0x3fffffff ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -471,6 +471,7 @@ static int getNextNode(
|
||||
assert( nKey==4 );
|
||||
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
||||
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
||||
if( nNear>=1000000000 ) nNear = 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@ static int fts3ExprLHits(
|
||||
if( p->flag==FTS3_MATCHINFO_LHITS ){
|
||||
p->aMatchinfo[iStart + iCol] = (u32)nHit;
|
||||
}else if( nHit ){
|
||||
p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
|
||||
p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
|
||||
}
|
||||
}
|
||||
assert( *pIter==0x00 || *pIter==0x01 );
|
||||
|
||||
@@ -922,7 +922,7 @@ static void fts5DataRelease(Fts5Data *pData){
|
||||
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
||||
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
||||
if( pRet ){
|
||||
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
|
||||
if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
fts5DataRelease(pRet);
|
||||
pRet = 0;
|
||||
@@ -2576,6 +2576,10 @@ static void fts5LeafSeek(
|
||||
if( nKeep<nMatch ){
|
||||
goto search_failed;
|
||||
}
|
||||
if( (iOff+nNew)>n ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
return;
|
||||
}
|
||||
|
||||
assert( nKeep>=nMatch );
|
||||
if( nKeep==nMatch ){
|
||||
@@ -3702,7 +3706,7 @@ static void fts5IndexExtractColset(
|
||||
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
|
||||
** not part of a varint */
|
||||
while( p<pEnd && *p!=0x01 ){
|
||||
while( *p++ & 0x80 );
|
||||
while( p<pEnd && (*p++ & 0x80) );
|
||||
}
|
||||
|
||||
if( pColset->aiCol[i]==iCurrent ){
|
||||
|
||||
@@ -586,8 +586,14 @@ static int fts5PorterCreate(
|
||||
const char *zBase = "unicode61";
|
||||
fts5_tokenizer_v2 *pV2 = 0;
|
||||
|
||||
if( nArg>0 ){
|
||||
zBase = azArg[0];
|
||||
while( nArg>0 ){
|
||||
if( sqlite3_stricmp(azArg[0],"porter")==0 ){
|
||||
nArg--;
|
||||
azArg++;
|
||||
}else{
|
||||
zBase = azArg[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
|
||||
@@ -712,9 +718,9 @@ static int fts5Porter_Ostar(char *zStem, int nStem){
|
||||
for(i=0; i<nStem; i++){
|
||||
bCons = !fts5PorterIsVowel(zStem[i], bCons);
|
||||
assert( bCons==0 || bCons==1 );
|
||||
mask = (mask << 1) + bCons;
|
||||
mask = ((mask << 1) + bCons) & 0x0007;
|
||||
}
|
||||
return ((mask & 0x0007)==0x0005);
|
||||
return (mask==0x0005);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15153,9 +15153,9 @@ do_execsql_test 78.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col');
|
||||
}
|
||||
|
||||
do_execsql_test 78.2 {
|
||||
do_catchsql_test 78.2 {
|
||||
SELECT count(rowid) FROM t3 WHERE term>='nsocse';
|
||||
} 2
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -1220,7 +1220,7 @@ do_test 8.0 {
|
||||
|
||||
do_catchsql_test 8.1 {
|
||||
SELECT rowid FROM t1('a* NOT ý') ;
|
||||
} {0 {1 2 3 4 5 6 7}}
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# 2026 May 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corruptA
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t USING fts5(x, detail='full');
|
||||
INSERT INTO t(t, rank) VALUES('pgsz', 32);
|
||||
}
|
||||
|
||||
set big [string repeat "a " 200]
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO t(rowid, x) VALUES(1, $big)
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
db eval {
|
||||
SELECT min(rowid) AS base_rowid, count(*) AS page_count FROM t_data
|
||||
WHERE rowid>1000
|
||||
} {}
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
for {set ii 0} {$ii < 5} {incr ii} {
|
||||
db eval {
|
||||
INSERT INTO t_data(rowid, block)
|
||||
VALUES( $base_rowid + $page_count + $ii, zeroblob(4) );
|
||||
}
|
||||
}
|
||||
db eval {
|
||||
INSERT INTO t_data(rowid, block)
|
||||
VALUES( $base_rowid + $page_count + 5,
|
||||
unhex('00000080' || 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC') );
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
||||
do_test 1.4 {
|
||||
set hex [hexio_read test.db 0 [file size test.db]]
|
||||
|
||||
set off [string first "023061018310" $hex]
|
||||
set hex [string replace $hex $off [expr $off+11] 023061018370]
|
||||
hexio_write test.db 0 $hex
|
||||
} {6144}
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.5 {
|
||||
SELECT rowid FROM t WHERE t MATCH 'a'
|
||||
} {1 {fts5: corruption found reading blob 137438953481 from table "t"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
BEGIN;
|
||||
INSERT INTO t1(rowid, a) VALUES(1, 'aaaa');
|
||||
INSERT INTO t1(rowid, a) VALUES(2, 'bbbb');
|
||||
INSERT INTO t1(rowid, a) VALUES(3, 'cccc');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
do_test 2.1 {
|
||||
set hex [hexio_read test.db 0 [file size test.db]]
|
||||
set off [string first "010463636363" $hex]
|
||||
set hex [string replace $hex $off [expr $off+11] 017F63636363]
|
||||
hexio_write test.db 0 $hex
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT rowid FROM t1('cccccccccccccccccccccccccccccccccccccccccccccccc');
|
||||
} {1 {fts5: corruption on page 1, segment 1, table "t1"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
|
||||
INSERT INTO t1 VALUES(
|
||||
'hello',
|
||||
'alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu',
|
||||
'ant bear cat dog elephant fox gorilla hippo iguana jaguar kangaroo lion monkey newt octopus panda quail rabbit snake turtle unicorn vulture walrus xerus yak zebra'
|
||||
);
|
||||
|
||||
UPDATE t1_data SET block = unhex(
|
||||
-- Preserve bytes 0-168: header through hello's nSz field
|
||||
hex(substr(block, 1, 169))
|
||||
-- Inject 448 bytes of 0xFF: corrupted poslist + subsequent term data
|
||||
|| replace(hex(zeroblob(448)), '00', 'FF')
|
||||
-- Preserve 16 bytes of page index needed for hello lookup
|
||||
|| hex(substr(block, 618, 16))
|
||||
-- Corrupt remaining 37 footer bytes (not needed for hello lookup)
|
||||
|| replace(hex(zeroblob(37)), '00', 'FF')
|
||||
)
|
||||
WHERE id = 137438953473;
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
execsql { SELECT * FROM t1 WHERE t1 MATCH '{a b}: hello' }
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
@@ -65,5 +65,13 @@ foreach {in out} $test_vocab {
|
||||
incr i
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE tbl USING fts5(t, tokenize='porter unicode61');
|
||||
INSERT INTO tbl VALUES(' andeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -371,4 +371,14 @@ do_execsql_test 10.10 {
|
||||
a 2 2 b 2 2 c 2 2 d 1 1 e 1 1 f 1 1
|
||||
}
|
||||
|
||||
# Bug report 2026-05-18T05:19:01Z
|
||||
#
|
||||
set manyporters {porter Porter}
|
||||
for {set i 0} {$i<18} {incr i} {
|
||||
set manyporters "$manyporters $manyporters"
|
||||
}
|
||||
do_execsql_test 11.1 "
|
||||
CREATE VIRTUAL TABLE t11 USING fts5(a,b,tokenize=\"$manyporters\");
|
||||
" {}
|
||||
|
||||
finish_test
|
||||
|
||||
+4
-4
@@ -362,7 +362,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
const UChar *zInput; /* Pointer to input string */
|
||||
UChar *zOutput = 0; /* Pointer to output buffer */
|
||||
int nInput; /* Size of utf-16 input string in bytes */
|
||||
int nOut; /* Size of output buffer in bytes */
|
||||
sqlite3_int64 nOut; /* Size of output buffer in bytes */
|
||||
int cnt;
|
||||
int bToUpper; /* True for toupper(), false for tolower() */
|
||||
UErrorCode status;
|
||||
@@ -385,7 +385,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
}
|
||||
|
||||
for(cnt=0; cnt<2; cnt++){
|
||||
UChar *zNew = sqlite3_realloc(zOutput, nOut);
|
||||
UChar *zNew = sqlite3_realloc64(zOutput, nOut);
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(zOutput);
|
||||
sqlite3_result_error_nomem(p);
|
||||
@@ -394,9 +394,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
zOutput = zNew;
|
||||
status = U_ZERO_ERROR;
|
||||
if( bToUpper ){
|
||||
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}else{
|
||||
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}
|
||||
|
||||
if( U_SUCCESS(status) ){
|
||||
|
||||
+1
-1
@@ -1157,7 +1157,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){
|
||||
#endif
|
||||
nWord = (int)strlen(pWord->zWord+2);
|
||||
if( nWord+20>nBuf ){
|
||||
nBuf = (char)(nWord+100);
|
||||
nBuf = nWord+100;
|
||||
zBuf = sqlite3_realloc64(zBuf, nBuf);
|
||||
if( zBuf==0 ) return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,836 @@
|
||||
/*
|
||||
** 2026-04-13
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** Partial reimplement of the sqlite3_analyzer utility program as
|
||||
** loadable SQL function.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
** State information for the analysis
|
||||
*/
|
||||
typedef struct Analysis Analysis;
|
||||
struct Analysis {
|
||||
sqlite3 *db; /* Database connection */
|
||||
sqlite3_context *context; /* SQL function context */
|
||||
sqlite3_str *pOut; /* Write output here */
|
||||
char *zSU; /* Name of the temp.space_used table */
|
||||
const char *zSchema; /* Schema to be analyzed */
|
||||
};
|
||||
|
||||
/*
|
||||
** Free all resources that the Analysis object references and
|
||||
** reset the Analysis object.
|
||||
**
|
||||
** Call this routine multiple times on the same Analysis object
|
||||
** is a harmless no-op, as long as the memory for the object itself
|
||||
** has not been freed.
|
||||
*/
|
||||
static void analysisReset(Analysis *p){
|
||||
if( p->zSU ){
|
||||
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
|
||||
if( zSql ){
|
||||
sqlite3_exec(p->db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
sqlite3_str_free(p->pOut);
|
||||
sqlite3_free(p->zSU);
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
|
||||
/*
|
||||
** Report an error using formatted text. If zFormat==NULL then report
|
||||
** an OOM error.
|
||||
*/
|
||||
static void analysisError(Analysis *p, const char *zFormat, ...){
|
||||
char *zErr;
|
||||
if( zFormat ){
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zErr = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
}else{
|
||||
zErr = 0;
|
||||
}
|
||||
if( zErr==0 ){
|
||||
sqlite3_result_error_nomem(p->context);
|
||||
}else{
|
||||
sqlite3_result_error(p->context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
analysisReset(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare and return an SQL statement.
|
||||
*/
|
||||
static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
|
||||
char *zSql;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zSql==0 ){ analysisError(p,0); return 0; }
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), zSql);
|
||||
sqlite3_finalize(pStmt);
|
||||
analysisReset(p);
|
||||
pStmt = 0;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
return pStmt;
|
||||
}
|
||||
static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** If rc is something other than SQLITE_DONE or SQLITE_OK, then report
|
||||
** an error and return true.
|
||||
**
|
||||
** If rc is SQLITE_DONE or SQLITE_OK, then return false.
|
||||
**
|
||||
** The prepared statement is closed in either case.
|
||||
*/
|
||||
static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run SQL. Return the number of errors.
|
||||
*/
|
||||
static int analysisSql(Analysis *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run an SQL query that returns an integer. Write that integer
|
||||
** into *piRes. Return the number of errors.
|
||||
*/
|
||||
static int analysisSqlInt(
|
||||
Analysis *p,
|
||||
sqlite3_int64 *piRes,
|
||||
const char *zFormat, ...
|
||||
){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
*piRes = sqlite3_column_int64(pStmt, 0);
|
||||
rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
if( p->db ){
|
||||
/* p->db is NULL if there was some prior error */
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
}
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add to the output a title line that contains the text determined
|
||||
** by the format string. If the output is initially empty, begin
|
||||
** the title line with "/" so that it forms the beginning of a C-style
|
||||
** comment. Otherwise begin with a new-line. Always finish with a
|
||||
** newline.
|
||||
*/
|
||||
static void analysisTitle(Analysis *p, const char *zFormat, ...){
|
||||
char *zFirst;
|
||||
char *zTitle;
|
||||
size_t nTitle;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zTitle = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTitle==0 ){
|
||||
analysisError(p, 0);
|
||||
return;
|
||||
}
|
||||
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
|
||||
nTitle = strlen(zTitle);
|
||||
if( nTitle>=75 ){
|
||||
sqlite3_str_appendf(p->pOut, "%s** %z\n\n", zFirst, zTitle);
|
||||
}else{
|
||||
int nExtra = 74 - (int)nTitle;
|
||||
sqlite3_str_appendf(p->pOut, "%s** %z %.*c\n\n", zFirst, zTitle,
|
||||
nExtra, '*');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an output line that begins with the zDesc text extended out to
|
||||
** 50 columns with "." characters, and followed by whatever text is
|
||||
** described by zFormat.
|
||||
*/
|
||||
static void analysisLine(
|
||||
Analysis *p, /* Analysis context */
|
||||
const char *zDesc, /* Description */
|
||||
const char *zFormat, /* Argument to the description */
|
||||
...
|
||||
){
|
||||
char *zTxt;
|
||||
size_t nDesc;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zTxt = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTxt==0 ){
|
||||
analysisError(p, 0);
|
||||
return;
|
||||
}
|
||||
nDesc = strlen(zDesc);
|
||||
if( nDesc>=50 ){
|
||||
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
|
||||
}else{
|
||||
int nExtra = 50 - (int)nDesc;
|
||||
sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Write a percentage into the output. The number written should show
|
||||
** two or three significant digits, with the decimal point being the fourth
|
||||
** character.
|
||||
*/
|
||||
static void analysisPercent(Analysis *p, double r){
|
||||
char zNum[100];
|
||||
char *zDP;
|
||||
int nLeadingDigit;
|
||||
int sz;
|
||||
sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
|
||||
sz = (int)strlen(zNum);
|
||||
zDP = strchr(zNum, '.');
|
||||
if( zDP==0 ){
|
||||
memcpy(zNum+sz,".0",3);
|
||||
nLeadingDigit = sz;
|
||||
sz += 2;
|
||||
}else{
|
||||
nLeadingDigit = (int)(zDP - zNum);
|
||||
}
|
||||
if( nLeadingDigit<3 ){
|
||||
sqlite3_str_appendchar(p->pOut, 3-nLeadingDigit, ' ');
|
||||
}
|
||||
sqlite3_str_append(p->pOut, zNum, sz);
|
||||
sqlite3_str_append(p->pOut, "%\n", 2);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a subreport on a subset of tables and/or indexes.
|
||||
**
|
||||
** The title if the subreport is given by zTitle. zWhere is
|
||||
** a boolean expression that can go in the WHERE clause to select
|
||||
** the relevant rows of the s.zSU table.
|
||||
*/
|
||||
static int analysisSubreport(
|
||||
Analysis *p, /* Analysis context */
|
||||
char *zTitle, /* Title for this subreport */
|
||||
char *zWhere, /* WHERE clause for this subreport */
|
||||
sqlite3_int64 pgsz, /* Database page size */
|
||||
sqlite3_int64 nPage /* Number of pages in entire database */
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* Statement to query p->zSU */
|
||||
sqlite3_int64 nentry; /* Number of btree entires */
|
||||
sqlite3_int64 payload; /* Payload in bytes */
|
||||
sqlite3_int64 ovfl_payload; /* overflow payload in bytes */
|
||||
sqlite3_int64 mx_payload; /* largest individual payload */
|
||||
sqlite3_int64 ovfl_cnt; /* Number entries using overflow */
|
||||
sqlite3_int64 leaf_pages; /* Leaf pages */
|
||||
sqlite3_int64 int_pages; /* internal pages */
|
||||
sqlite3_int64 ovfl_pages; /* overflow pages */
|
||||
sqlite3_int64 leaf_unused; /* unused bytes on leaf pages */
|
||||
sqlite3_int64 int_unused; /* unused bytes on internal pages */
|
||||
sqlite3_int64 ovfl_unused; /* unused bytes on overflow pages */
|
||||
sqlite3_int64 int_cell; /* B-tree entries on internal pages */
|
||||
sqlite3_int64 depth; /* btree depth */
|
||||
sqlite3_int64 cnt; /* Number of s.zSU entries that match */
|
||||
sqlite3_int64 storage; /* Total bytes */
|
||||
sqlite3_int64 total_pages; /* Total page count */
|
||||
sqlite3_int64 total_unused; /* Total unused bytes */
|
||||
sqlite3_int64 total_meta; /* Total metadata */
|
||||
int rc;
|
||||
|
||||
if( zTitle==0 || zWhere==0 ){
|
||||
analysisError(p, 0);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pStmt = analysisPrepare(p,
|
||||
"SELECT\n"
|
||||
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
|
||||
" sum(payload),\n" /* 1 */
|
||||
" sum(ovfl_payload),\n" /* 2 */
|
||||
" max(mx_payload),\n" /* 3 */
|
||||
" sum(ovfl_cnt),\n" /* 4 */
|
||||
" sum(leaf_pages),\n" /* 5 */
|
||||
" sum(int_pages),\n" /* 6 */
|
||||
" sum(ovfl_pages),\n" /* 7 */
|
||||
" sum(leaf_unused),\n" /* 8 */
|
||||
" sum(int_unused),\n" /* 9 */
|
||||
" sum(ovfl_unused),\n" /* 10 */
|
||||
" max(depth),\n" /* 11 */
|
||||
" count(*),\n" /* 12 */
|
||||
" sum(int_entries)\n" /* 13 */
|
||||
" FROM temp.%s WHERE %s",
|
||||
p->zSU, zWhere);
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
analysisTitle(p, zTitle);
|
||||
|
||||
nentry = sqlite3_column_int64(pStmt, 0);
|
||||
payload = sqlite3_column_int64(pStmt, 1);
|
||||
ovfl_payload = sqlite3_column_int64(pStmt, 2);
|
||||
mx_payload = sqlite3_column_int64(pStmt, 3);
|
||||
ovfl_cnt = sqlite3_column_int64(pStmt, 4);
|
||||
leaf_pages = sqlite3_column_int64(pStmt, 5);
|
||||
int_pages = sqlite3_column_int64(pStmt, 6);
|
||||
ovfl_pages = sqlite3_column_int64(pStmt, 7);
|
||||
leaf_unused = sqlite3_column_int64(pStmt, 8);
|
||||
int_unused = sqlite3_column_int64(pStmt, 9);
|
||||
ovfl_unused = sqlite3_column_int64(pStmt, 10);
|
||||
depth = sqlite3_column_int64(pStmt, 11);
|
||||
cnt = sqlite3_column_int64(pStmt, 12);
|
||||
int_cell = sqlite3_column_int64(pStmt, 13);
|
||||
rc = SQLITE_DONE;
|
||||
|
||||
total_pages = leaf_pages + int_pages + ovfl_pages;
|
||||
analysisLine(p, "Percentage of total database", "%.3g%%\n",
|
||||
(total_pages*100.0)/(double)nPage);
|
||||
analysisLine(p, "Number of entries", "%lld\n", nentry);
|
||||
storage = total_pages*pgsz;
|
||||
analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
|
||||
analysisLine(p, "Bytes of payload", "%-11lld ", payload);
|
||||
analysisPercent(p, payload*100.0/(double)storage);
|
||||
if( ovfl_cnt>0 ){
|
||||
analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
|
||||
analysisPercent(p, ovfl_payload*100.0/(double)payload);
|
||||
}
|
||||
total_unused = leaf_unused + int_unused + ovfl_unused;
|
||||
total_meta = storage - payload - total_unused;
|
||||
analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
|
||||
analysisPercent(p, total_meta*100.0/(double)storage);
|
||||
if( cnt==1 ){
|
||||
analysisLine(p, "B-tree depth", "%lld\n", depth);
|
||||
if( int_cell>1 ){
|
||||
analysisLine(p, "Average fanout", "%.1f\n",
|
||||
(double)(int_cell+int_pages)/(double)int_pages);
|
||||
}
|
||||
}
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Average payload per entry", "%.1f\n",
|
||||
(double)payload/(double)nentry);
|
||||
analysisLine(p, "Average unused bytes per entry", "%.1f\n",
|
||||
(double)total_unused/(double)nentry);
|
||||
analysisLine(p, "Average metadata per entry", "%.1f\n",
|
||||
(double)total_meta/(double)nentry);
|
||||
}
|
||||
analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
|
||||
analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
|
||||
}
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Index pages used", "%lld\n", int_pages);
|
||||
}
|
||||
analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
|
||||
}
|
||||
analysisLine(p, "Total pages used", "%lld\n", total_pages);
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
|
||||
analysisPercent(p, total_unused*100.0/(double)storage);
|
||||
}
|
||||
return analysisStmtFinish(p, rc, pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL Function: analyze(SCHEMA)
|
||||
**
|
||||
** Analyze the database schema named in the argument. Return text
|
||||
** containing the analysis.
|
||||
*/
|
||||
static void analyzeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
int n;
|
||||
sqlite3_int64 ii;
|
||||
sqlite3_int64 pgsz;
|
||||
sqlite3_int64 nPage;
|
||||
sqlite3_int64 nPageInUse;
|
||||
sqlite3_int64 nFreeList;
|
||||
sqlite3_int64 nIndex;
|
||||
sqlite3_int64 nWORowid;
|
||||
Analysis s;
|
||||
sqlite3_uint64 r[2];
|
||||
|
||||
(void)argc;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.db = sqlite3_context_db_handle(context);
|
||||
s.context = context;
|
||||
s.pOut = sqlite3_str_new(0);
|
||||
if( sqlite3_str_errcode(s.pOut) ){
|
||||
analysisError(&s, 0);
|
||||
return;
|
||||
}
|
||||
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( s.zSchema==0 ){
|
||||
s.zSchema = "main";
|
||||
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
|
||||
" WHERE name=%Q COLLATE nocase",s.zSchema);
|
||||
if( rc || ii==0 ){
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
|
||||
if( s.zSU==0 ){ analysisError(&s, 0); return; }
|
||||
|
||||
/* The s.zSU table contains the data used for the analysis.
|
||||
** The table name contains 128-bits of randomness to avoid
|
||||
** collisions with preexisting tables in temp.
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
"CREATE TABLE temp.%s(\n"
|
||||
" name text, -- A table or index\n"
|
||||
" tblname text, -- Table that owns name\n"
|
||||
" is_index boolean, -- TRUE if it is an index\n"
|
||||
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
|
||||
" nentry int, -- Number of entries in the BTree\n"
|
||||
" leaf_entries int, -- Number of leaf entries\n"
|
||||
" depth int, -- Depth of the b-tree\n"
|
||||
" payload int, -- Total data stored in this table/index\n"
|
||||
" ovfl_payload int, -- Total data stored on overflow pages\n"
|
||||
" ovfl_cnt int, -- Number of entries that use overflow\n"
|
||||
" mx_payload int, -- Maximum payload size\n"
|
||||
" int_pages int, -- Interior pages used\n"
|
||||
" leaf_pages int, -- Leaf pages used\n"
|
||||
" ovfl_pages int, -- Overflow pages used\n"
|
||||
" int_unused int, -- Unused bytes on interior pages\n"
|
||||
" leaf_unused int, -- Unused bytes on primary pages\n"
|
||||
" ovfl_unused int, -- Unused bytes on overflow pages\n"
|
||||
" int_entries int -- Btree cells on internal pages\n"
|
||||
");",
|
||||
s.zSU
|
||||
);
|
||||
if( rc ) return;
|
||||
|
||||
/* Populate the s.zSU table
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
"WITH\n"
|
||||
" allidx(idxname) AS (\n"
|
||||
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
|
||||
" ),\n"
|
||||
" allobj(allname,tblname,isidx,isworowid) AS (\n"
|
||||
" SELECT 'sqlite_schema',\n"
|
||||
" 'sqlite_schema',\n"
|
||||
" 0,\n"
|
||||
" 0\n"
|
||||
" UNION ALL\n"
|
||||
" SELECT name,\n"
|
||||
" tbl_name,\n"
|
||||
" type='index',\n"
|
||||
" EXISTS(SELECT 1\n"
|
||||
" FROM pragma_index_list(sqlite_schema.name,%Q)\n"
|
||||
" WHERE pragma_index_list.origin='pk'\n"
|
||||
" AND pragma_index_list.name NOT IN allidx)\n"
|
||||
" FROM \"%w\".sqlite_schema\n"
|
||||
" )\n"
|
||||
"INSERT INTO temp.%s\n"
|
||||
" SELECT\n"
|
||||
" allname,\n"
|
||||
" tblname,\n"
|
||||
" isidx,\n"
|
||||
" isworowid,\n"
|
||||
" sum(ncell),\n"
|
||||
" sum((pagetype='leaf')*ncell),\n"
|
||||
" max((length(if(path GLOB '*+*','',path))+3)/4),\n"
|
||||
" sum(payload),\n"
|
||||
" sum((pagetype='overflow')*payload),\n"
|
||||
" sum(path GLOB '*+000000'),\n"
|
||||
" max(mx_payload),\n"
|
||||
" sum(pagetype='internal'),\n"
|
||||
" sum(pagetype='leaf'),\n"
|
||||
" sum(pagetype='overflow'),\n"
|
||||
" sum((pagetype='internal')*unused),\n"
|
||||
" sum((pagetype='leaf')*unused),\n"
|
||||
" sum((pagetype='overflow')*unused),\n"
|
||||
" sum(if(pagetype='internal',ncell))\n"
|
||||
" FROM allobj CROSS JOIN dbstat(%Q) \n"
|
||||
" WHERE dbstat.name=allobj.allname\n"
|
||||
" GROUP BY allname;\n",
|
||||
s.zSchema, /* %w.sqlite_schema -- in allidx */
|
||||
s.zSchema, /* pragma_index_list(...,%Q) */
|
||||
s.zSchema, /* %w.sqlite_schema */
|
||||
s.zSU, /* INTO temp.%s */
|
||||
s.zSchema /* JOIN dbstat(%Q) */
|
||||
);
|
||||
if( rc ) return;
|
||||
|
||||
nPage = 0;
|
||||
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nPage<=0 ){
|
||||
/* Very brief reply for an empty database */
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Begin generating the report */
|
||||
analysisTitle(&s, "Database storage utilization report");
|
||||
pgsz = 0;
|
||||
rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
|
||||
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
|
||||
|
||||
nPageInUse = 0;
|
||||
rc = analysisSqlInt(&s, &nPageInUse,
|
||||
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
|
||||
analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
|
||||
|
||||
nFreeList = 0;
|
||||
rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
|
||||
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( ii==0 || nPage<=1 ){
|
||||
ii = 0;
|
||||
}else{
|
||||
double rPtrsPerPage = pgsz/5;
|
||||
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
|
||||
ii = (sqlite3_int64)ceil(rAvPage);
|
||||
}
|
||||
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
|
||||
analysisPercent(&s, (ii*100.0)/(double)nPage);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of tables", "%lld\n", ii);
|
||||
nWORowid = 0;
|
||||
rc = analysisSqlInt(&s, &nWORowid,
|
||||
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
|
||||
analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
|
||||
}
|
||||
nIndex = 0;
|
||||
rc = analysisSqlInt(&s, &nIndex,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema"
|
||||
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
|
||||
analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
|
||||
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"SELECT sum(payload) FROM temp.%s"
|
||||
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
|
||||
s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
|
||||
analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables with their indexes");
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(tblname),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables and indexes separately");
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(name),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All rowid tables",
|
||||
"NOT is_without_rowid AND NOT is_index",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
}
|
||||
rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
|
||||
" GROUP BY 1 ORDER BY 1",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
const char *zUpper = (const char*)sqlite3_column_text(pStmt, 0);
|
||||
const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
int nSubIndex = sqlite3_column_int(pStmt, 2);
|
||||
if( nSubIndex==0 ){
|
||||
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}else{
|
||||
sqlite3_stmt *pS2;
|
||||
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
if( nSubIndex>1 ){
|
||||
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
|
||||
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
pS2 = analysisPrepare(&s,
|
||||
"SELECT name, upper(name) FROM temp.%s"
|
||||
" WHERE is_index AND tblname=%Q",
|
||||
s.zSU, zName);
|
||||
if( pS2==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
|
||||
const char *zU = (const char*)sqlite3_column_text(pS2, 1);
|
||||
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
|
||||
zTitle = sqlite3_mprintf("Index %s", zU);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zN);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
rc = analysisStmtFinish(&s, rc, pS2);
|
||||
if( rc ) break;
|
||||
}
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
/* Append SQL statements that will recreate the raw data used for
|
||||
** the analysis.
|
||||
*/
|
||||
analysisTitle(&s, "Raw data used to generate this report");
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
"The following SQL will create a table named \"space_used\" which\n"
|
||||
"contains most of the information used to generate the report above.\n"
|
||||
"*/\n"
|
||||
);
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
"BEGIN;\n"
|
||||
"CREATE TABLE space_used(\n"
|
||||
" name text, -- A table or index\n" /* 0 */
|
||||
" tblname text, -- Table that owns name\n" /* 1 */
|
||||
" is_index boolean, -- TRUE if it is an index\n" /* 2 */
|
||||
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n" /* 3 */
|
||||
" nentry int, -- Number of entries in the BTree\n" /* 4 */
|
||||
" leaf_entries int, -- Number of leaf entries\n" /* 5 */
|
||||
" depth int, -- Depth of the b-tree\n" /* 6 */
|
||||
" payload int, -- Total data in this table/index\n" /* 7 */
|
||||
" ovfl_payload int, -- Total data on overflow pages\n" /* 8 */
|
||||
" ovfl_cnt int, -- Entries that use overflow\n" /* 9 */
|
||||
" mx_payload int, -- Maximum payload size\n" /* 10 */
|
||||
" int_pages int, -- Interior pages used\n" /* 11 */
|
||||
" leaf_pages int, -- Leaf pages used\n" /* 12 */
|
||||
" ovfl_pages int, -- Overflow pages used\n" /* 13 */
|
||||
" int_unused int, -- Unused bytes on interior pages\n" /* 14 */
|
||||
" leaf_unused int, -- Unused bytes on primary pages\n" /* 15 */
|
||||
" ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
|
||||
" int_entries int -- B-tree entries on internal pages\n"/* 17 */
|
||||
");\n"
|
||||
"INSERT INTO space_used VALUES\n"
|
||||
);
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
|
||||
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
|
||||
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
|
||||
" int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
|
||||
" leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
|
||||
" FROM temp.%s;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
n = 0;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
if( n++ ) sqlite3_str_appendf(s.pOut,",\n");
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
" (%s,%s,%lld,%lld,%lld,%lld,%lld,%lld,%lld,"
|
||||
"%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld)",
|
||||
sqlite3_column_text(pStmt, 0),
|
||||
sqlite3_column_text(pStmt, 1),
|
||||
sqlite3_column_int64(pStmt, 2),
|
||||
sqlite3_column_int64(pStmt, 3),
|
||||
sqlite3_column_int64(pStmt, 4),
|
||||
sqlite3_column_int64(pStmt, 5),
|
||||
sqlite3_column_int64(pStmt, 6),
|
||||
sqlite3_column_int64(pStmt, 7),
|
||||
sqlite3_column_int64(pStmt, 8),
|
||||
sqlite3_column_int64(pStmt, 9),
|
||||
sqlite3_column_int64(pStmt, 10),
|
||||
sqlite3_column_int64(pStmt, 11),
|
||||
sqlite3_column_int64(pStmt, 12),
|
||||
sqlite3_column_int64(pStmt, 13),
|
||||
sqlite3_column_int64(pStmt, 14),
|
||||
sqlite3_column_int64(pStmt, 15),
|
||||
sqlite3_column_int64(pStmt, 16),
|
||||
sqlite3_column_int64(pStmt, 17));
|
||||
}
|
||||
if( rc!=SQLITE_DONE ){
|
||||
analysisError(&s, "SQL run-time error: %s\nSQL: %s",
|
||||
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
|
||||
sqlite3_finalize(pStmt);
|
||||
return;
|
||||
}
|
||||
sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
if( sqlite3_str_length(s.pOut) ){
|
||||
sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
|
||||
sqlite3_free);
|
||||
s.pOut = 0;
|
||||
}
|
||||
analysisReset(&s);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_analyze_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "analyze", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, analyzeFunc, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
+1
-1
@@ -261,7 +261,7 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
|
||||
sqlite3_result_null(pCtx);
|
||||
return;
|
||||
}
|
||||
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
|
||||
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+8 );
|
||||
if( z==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return;
|
||||
|
||||
+62
-9
@@ -97,8 +97,6 @@ SQLITE_EXTENSION_INIT1
|
||||
# define STRUCT_STAT struct _stat
|
||||
# define chmod(path,mode) fileio_chmod(path,mode)
|
||||
# define mkdir(path,mode) fileio_mkdir(path)
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -125,13 +123,69 @@ SQLITE_EXTENSION_INIT1
|
||||
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
|
||||
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
** Convert a UTF-8 string to Microsoft Unicode.
|
||||
**
|
||||
** Space to hold the returned string is obtained from sqlite3_malloc().
|
||||
*/
|
||||
static wchar_t *winUtf8To16(const char *zText){
|
||||
int nChar;
|
||||
wchar_t *zWideText;
|
||||
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
|
||||
if( nChar==0 ){
|
||||
return 0;
|
||||
}
|
||||
zWideText = sqlite3_malloc64(nChar*sizeof(WCHAR) );
|
||||
if( zWideText==0 ){
|
||||
return 0;
|
||||
}
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
|
||||
nChar);
|
||||
if( nChar==0 ){
|
||||
sqlite3_free(zWideText);
|
||||
zWideText = 0;
|
||||
}
|
||||
return zWideText;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
** Convert a Microsoft Unicode string to UTF-8.
|
||||
**
|
||||
** Space to hold the returned string is obtained from sqlite3_malloc().
|
||||
*/
|
||||
static char *winUtf16To8(wchar_t *zWideText){
|
||||
int nByte;
|
||||
char *zText;
|
||||
|
||||
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
|
||||
if( nByte == 0 ){
|
||||
return 0;
|
||||
}
|
||||
zText = sqlite3_malloc64( nByte );
|
||||
if( zText==0 ){
|
||||
return 0;
|
||||
}
|
||||
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
|
||||
0, 0);
|
||||
if( nByte == 0 ){
|
||||
sqlite3_free(zText);
|
||||
zText = 0;
|
||||
}
|
||||
return zText;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
** UTF8 chmod() function for Windows
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_chmod(const char *zPath, int pmode){
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
rc = _wchmod(b1, pmode);
|
||||
sqlite3_free(b1);
|
||||
@@ -145,7 +199,7 @@ static int fileio_chmod(const char *zPath, int pmode){
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_mkdir(const char *zPath){
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
rc = _wmkdir(b1);
|
||||
sqlite3_free(b1);
|
||||
@@ -272,7 +326,7 @@ static int fileStat(
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return 1;
|
||||
rc = _wstat(b1, pStatBuf);
|
||||
if( rc==0 ){
|
||||
@@ -425,14 +479,13 @@ static int writeFile(
|
||||
LONGLONG intervals;
|
||||
HANDLE hFile;
|
||||
LPWSTR zUnicodeName;
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
|
||||
GetSystemTime(¤tTime);
|
||||
SystemTimeToFileTime(¤tTime, &lastAccess);
|
||||
intervals = (mtime*10000000) + 116444736000000000;
|
||||
lastWrite.dwLowDateTime = (DWORD)intervals;
|
||||
lastWrite.dwHighDateTime = intervals >> 32;
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
||||
zUnicodeName = winUtf8To16(zFile);
|
||||
if( zUnicodeName==0 ){
|
||||
return 1;
|
||||
}
|
||||
@@ -1090,12 +1143,12 @@ static char *portable_realpath(const char *zPath){
|
||||
|
||||
if( zPath==0 ) return 0;
|
||||
|
||||
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
zPath16 = winUtf8To16(zPath);
|
||||
if( zPath16==0 ) return 0;
|
||||
z = _wfullpath(NULL, zPath16, 0);
|
||||
sqlite3_free(zPath16);
|
||||
if( z ){
|
||||
zOut = sqlite3_win32_unicode_to_utf8(z);
|
||||
zOut = winUtf16To8(z);
|
||||
free(z);
|
||||
}
|
||||
return zOut;
|
||||
|
||||
+19
-7
@@ -29,6 +29,17 @@
|
||||
** RBU does not use this extension directly. Rather, this extension is
|
||||
** provided as a convenience to developers who want to analyze RBU files
|
||||
** that contain deltas.
|
||||
**
|
||||
** Typical build commands assuming
|
||||
**
|
||||
** DIR=ext/misc
|
||||
* NAME=fossildelta
|
||||
**
|
||||
** First run "make sqlite3ext.h" then:
|
||||
**
|
||||
** linux: gcc -shared -I. -fPIC -o $NAME.so $DIR/$NAME.c
|
||||
** OS-X: gcc -dynamiclib -fPIC -I. -o $NAME.dylib $DIR/$NAME.c
|
||||
** Win11: cl -I. $DIR/$NAME.c -link -dll -out:$NAME.dll
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@@ -43,6 +54,7 @@ SQLITE_EXTENSION_INIT1
|
||||
*/
|
||||
typedef unsigned int u32;
|
||||
typedef sqlite3_uint64 u64;
|
||||
typedef sqlite3_int64 i64;
|
||||
|
||||
/*
|
||||
** Must be a 16-bit value
|
||||
@@ -769,11 +781,11 @@ struct deltaparsevtab_vtab {
|
||||
struct deltaparsevtab_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
char *aDelta; /* The delta being parsed */
|
||||
int nDelta; /* Number of bytes in the delta */
|
||||
int iCursor; /* Current cursor location */
|
||||
i64 iCursor; /* Current cursor location */
|
||||
i64 iNext; /* Next cursor value */
|
||||
i64 nDelta; /* Number of bytes in the delta */
|
||||
int eOp; /* Name of current operator */
|
||||
unsigned int a1, a2; /* Arguments to current operator */
|
||||
int iNext; /* Next cursor value */
|
||||
};
|
||||
|
||||
/* Operator names:
|
||||
@@ -887,14 +899,14 @@ static int deltaparsevtabNext(sqlite3_vtab_cursor *cur){
|
||||
}
|
||||
pCur->a2 = deltaGetInt(&z, &i);
|
||||
pCur->eOp = DELTAPARSE_OP_COPY;
|
||||
pCur->iNext = (int)(&z[1] - pCur->aDelta);
|
||||
pCur->iNext = (i64)(&z[1] - pCur->aDelta);
|
||||
break;
|
||||
}
|
||||
case ':': {
|
||||
z++;
|
||||
pCur->a2 = (unsigned int)(z - pCur->aDelta);
|
||||
pCur->eOp = DELTAPARSE_OP_INSERT;
|
||||
pCur->iNext = (int)(&z[pCur->a1] - pCur->aDelta);
|
||||
pCur->iNext = (i64)(&z[pCur->a1] - pCur->aDelta);
|
||||
break;
|
||||
}
|
||||
case ';': {
|
||||
@@ -938,7 +950,7 @@ static int deltaparsevtabColumn(
|
||||
if( pCur->eOp==DELTAPARSE_OP_COPY ){
|
||||
sqlite3_result_int(ctx, pCur->a2);
|
||||
}else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
|
||||
if( pCur->a2 + pCur->a1 > pCur->nDelta ){
|
||||
if( (i64)pCur->a2 + (i64)pCur->a1 > pCur->nDelta ){
|
||||
sqlite3_result_zeroblob(ctx, pCur->a1);
|
||||
}else{
|
||||
sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
|
||||
@@ -1014,7 +1026,7 @@ static int deltaparsevtabFilter(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
a++;
|
||||
pCur->iNext = (unsigned int)(a - pCur->aDelta);
|
||||
pCur->iNext = (i64)(a - pCur->aDelta);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -289,6 +289,10 @@ static void prefixLengthFunc(
|
||||
int nL = sqlite3_value_bytes(apVal[0]);
|
||||
int nR = sqlite3_value_bytes(apVal[1]);
|
||||
int i;
|
||||
if( zL==0 || zR==0 ){
|
||||
sqlite3_result_int(ctx, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
nByte = (nL > nR ? nL : nR);
|
||||
for(i=0; i<nByte; i++){
|
||||
|
||||
+7
-8
@@ -865,7 +865,6 @@ static void re_bytecode_func(
|
||||
return;
|
||||
}
|
||||
pStr = sqlite3_str_new(0);
|
||||
if( pStr==0 ) goto re_bytecode_func_err;
|
||||
if( pRe->nInit>0 ){
|
||||
sqlite3_str_appendf(pStr, "INIT ");
|
||||
for(i=0; i<pRe->nInit; i++){
|
||||
@@ -877,15 +876,15 @@ static void re_bytecode_func(
|
||||
sqlite3_str_appendf(pStr, "%-8s %4d\n",
|
||||
ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
|
||||
}
|
||||
if( sqlite3_str_errcode(pStr)==SQLITE_NOMEM ){
|
||||
sqlite3_str_finish(pStr);
|
||||
re_free(pRe);
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
n = sqlite3_str_length(pStr);
|
||||
z = sqlite3_str_finish(pStr);
|
||||
if( n==0 ){
|
||||
sqlite3_free(z);
|
||||
}else{
|
||||
sqlite3_result_text(context, z, n-1, sqlite3_free);
|
||||
}
|
||||
|
||||
re_bytecode_func_err:
|
||||
sqlite3_result_text(context, z, n-1, sqlite3_free);
|
||||
re_free(pRe);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -536,7 +536,7 @@ static int seriesFilter(
|
||||
if( r<(double)SMALLEST_INT64 ){
|
||||
iMin = SMALLEST_INT64;
|
||||
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
||||
iMin = (sqlite3_int64)seriesCeil(r+1.0);
|
||||
iMin = (sqlite3_int64)seriesCeil(r)+1;
|
||||
}else{
|
||||
iMin = (sqlite3_int64)seriesCeil(r);
|
||||
}
|
||||
@@ -557,7 +557,7 @@ static int seriesFilter(
|
||||
if( r>(double)LARGEST_INT64 ){
|
||||
iMax = LARGEST_INT64;
|
||||
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
||||
iMax = (sqlite3_int64)(r-1.0);
|
||||
iMax = ((sqlite3_int64)r)-1;
|
||||
}else{
|
||||
iMax = (sqlite3_int64)seriesFloor(r);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ SQLITE_EXTENSION_INIT1
|
||||
/******************************************************************************
|
||||
** The Hash Engine
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||
#endif
|
||||
/* Context for the SHA1 hash */
|
||||
typedef struct SHA1Context SHA1Context;
|
||||
struct SHA1Context {
|
||||
@@ -226,6 +230,9 @@ static void hash_finish(
|
||||
zOut[i*2]= 0;
|
||||
}
|
||||
}
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
/* End of the hashing logic
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
+12
-3
@@ -352,6 +352,7 @@ static int substituteCost(char cPrev, char cFrom, char cTo){
|
||||
** -1 One of the inputs is NULL
|
||||
** -2 Non-ASCII characters on input
|
||||
** -3 Unable to allocate memory
|
||||
** -4 Inputs too large
|
||||
**
|
||||
** If pnMatch is not NULL, then *pnMatch is set to the number of bytes
|
||||
** of zB that matched the pattern in zA. If zA does not end with a '*',
|
||||
@@ -390,9 +391,11 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
for(nA=0; zA[nA]; nA++){
|
||||
if( zA[nA]&0x80 ) return -2;
|
||||
}
|
||||
if( nA>=100000 ) return -4;
|
||||
for(nB=0; zB[nB]; nB++){
|
||||
if( zB[nB]&0x80 ) return -2;
|
||||
}
|
||||
if( nB>=100000 ) return -4;
|
||||
|
||||
/* Special processing if either string is empty */
|
||||
if( nA==0 ){
|
||||
@@ -419,7 +422,7 @@ static int editdist1(const char *zA, const char *zB, int *pnMatch){
|
||||
if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){
|
||||
m = mStack;
|
||||
}else{
|
||||
m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 );
|
||||
m = toFree = sqlite3_malloc64( (nB+1)*5LL*sizeof(m[0])/4 );
|
||||
if( m==0 ) return -3;
|
||||
}
|
||||
cx = (char*)&m[nB+1];
|
||||
@@ -527,6 +530,8 @@ static void editdistSqlFunc(
|
||||
if( res<0 ){
|
||||
if( res==(-3) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( res==(-4) ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( res==(-2) ){
|
||||
sqlite3_result_error(context, "non-ASCII input to editdist()", -1);
|
||||
}else{
|
||||
@@ -1008,6 +1013,8 @@ static int editDist3Core(
|
||||
unsigned int stackSpace[SQLITE_SPELLFIX_STACKALLOC_SZ/sizeof(unsigned int)];
|
||||
|
||||
/* allocate the Wagner matrix and the aTo[] array for the TO string */
|
||||
if( n2>10000 ) return -2;
|
||||
if( f.n>10000 ) return -2;
|
||||
n = (f.n+1)*(n2+1);
|
||||
n = (n+1)&~1;
|
||||
nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
|
||||
@@ -1198,6 +1205,8 @@ static void editDist3SqlFunc(
|
||||
editDist3FromStringDelete(pFrom);
|
||||
if( dist==(-1) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( dist==(-2) ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else{
|
||||
sqlite3_result_int(context, dist);
|
||||
}
|
||||
@@ -2461,7 +2470,7 @@ static void spellfix1RunQuery(MatchQuery *p, const char *zQuery, int nQuery){
|
||||
iDist = editdist1(p->zPattern, zK1, 0);
|
||||
}
|
||||
if( iDist<0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
p->rc = iDist==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
pCur->nSearch++;
|
||||
@@ -2773,7 +2782,7 @@ static int spellfix1Column(
|
||||
if( !zTranslit ) return SQLITE_NOMEM;
|
||||
res = editdist1(pCur->zPattern, zTranslit, &iMatchlen);
|
||||
sqlite3_free(zTranslit);
|
||||
if( res<0 ) return SQLITE_NOMEM;
|
||||
if( res<0 ) return res==(-4) ? SQLITE_TOOBIG : SQLITE_NOMEM;
|
||||
iMatchlen = translen_to_charlen(zWord, nWord, iMatchlen);
|
||||
}else{
|
||||
iMatchlen = utf8Charlen(zWord, nWord);
|
||||
|
||||
+48
-29
@@ -252,6 +252,10 @@ static void qrfApproxInt64(sqlite3_str *pOut, i64 N){
|
||||
sqlite3_str_appendf(pOut, "%4lld ", N);
|
||||
return;
|
||||
}
|
||||
if( N>=9223372036854775800LL ){
|
||||
sqlite3_str_appendf(pOut, "%.2fE", 1e-18*(double)N);
|
||||
return;
|
||||
}
|
||||
for(i=1; i<=18; i++){
|
||||
N = (N+5)/10;
|
||||
if( N<10000 ){
|
||||
@@ -411,8 +415,8 @@ static void qrfEqpStats(Qrf *p){
|
||||
sqlite3_str_reset(pStats);
|
||||
if( nCycle>=0 && nTotal>0 ){
|
||||
qrfApproxInt64(pStats, nCycle);
|
||||
sqlite3_str_appendf(pStats, " %3d%%",
|
||||
((nCycle*100)+nTotal/2) / nTotal
|
||||
sqlite3_str_appendf(pStats, " %3.0f%%",
|
||||
((100.0*(double)nCycle)+nTotal/2.0) / (double)nTotal
|
||||
);
|
||||
nSp = 2;
|
||||
}
|
||||
@@ -428,7 +432,6 @@ static void qrfEqpStats(Qrf *p){
|
||||
if( nRow>=0 ){
|
||||
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
|
||||
qrfApproxInt64(pStats, nRow);
|
||||
nSp = 2;
|
||||
if( p->spec.eStyle==QRF_STYLE_StatsEst ){
|
||||
sqlite3_str_appendf(pStats, " ");
|
||||
qrfApproxInt64(pStats, (i64)rEstCum);
|
||||
@@ -718,19 +721,16 @@ static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
|
||||
}
|
||||
|
||||
/*
|
||||
** Escape the input string if it is needed and in accordance with
|
||||
** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
|
||||
** Escape the text starting at byte iStart of pStr, if needed, using the
|
||||
** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
|
||||
** The pStr string is modified appropriately.
|
||||
**
|
||||
** Escaping is needed if the string contains any control characters
|
||||
** other than \t, \n, and \r\n
|
||||
**
|
||||
** If no escaping is needed (the common case) then set *ppOut to NULL
|
||||
** and return 0. If escaping is needed, write the escaped string into
|
||||
** memory obtained from sqlite3_malloc64() and make *ppOut point to that
|
||||
** memory and return 0. If an error occurs, return non-zero.
|
||||
**
|
||||
** The caller is responsible for freeing *ppFree if it is non-NULL in order
|
||||
** to reclaim memory.
|
||||
** If no escaping is needed (the common case) then pStr is unchanged.
|
||||
** If escaping is required, then pStr is expanded and modified to hold
|
||||
** an escaped representation of the text.
|
||||
*/
|
||||
static void qrfEscape(
|
||||
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
|
||||
@@ -738,20 +738,22 @@ static void qrfEscape(
|
||||
int iStart /* Begin escapding on this byte of pStr */
|
||||
){
|
||||
sqlite3_int64 i, j; /* Loop counters */
|
||||
sqlite3_int64 sz; /* Size of the string prior to escaping */
|
||||
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
|
||||
unsigned char *zIn; /* Text to be escaped */
|
||||
unsigned int nIn; /* Bytes of text to be escaped */
|
||||
unsigned char c; /* A single character of the text */
|
||||
unsigned char *zOut; /* Where to write the results */
|
||||
|
||||
/* Find the text to be escaped */
|
||||
zIn = (unsigned char*)sqlite3_str_value(pStr);
|
||||
nIn = sqlite3_str_length(pStr);
|
||||
if( zIn==0 ) return;
|
||||
zIn += iStart;
|
||||
nIn -= iStart;
|
||||
|
||||
/* Count the control characters */
|
||||
for(i=0; (c = zIn[i])!=0; i++){
|
||||
if( c<=0x1f
|
||||
for(i=0; i<nIn; i++){
|
||||
if( (c = zIn[i])<=0x1f
|
||||
&& c!='\t'
|
||||
&& c!='\n'
|
||||
&& (c!='\r' || zIn[i+1]!='\n')
|
||||
@@ -763,18 +765,17 @@ static void qrfEscape(
|
||||
|
||||
/* Make space to hold the escapes. Copy the original text to the end
|
||||
** of the available space. */
|
||||
sz = sqlite3_str_length(pStr) - iStart;
|
||||
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
|
||||
sqlite3_str_appendchar(pStr, nCtrl, ' ');
|
||||
zOut = (unsigned char*)sqlite3_str_value(pStr);
|
||||
if( zOut==0 ) return;
|
||||
zOut += iStart;
|
||||
zIn = zOut + nCtrl;
|
||||
memmove(zIn,zOut,sz);
|
||||
memmove(zIn,zOut,nIn);
|
||||
|
||||
/* Convert the control characters */
|
||||
for(i=j=0; (c = zIn[i])!=0; i++){
|
||||
if( c>0x1f
|
||||
for(i=j=0; i<nIn; i++){
|
||||
if( (c = zIn[i])>0x1f
|
||||
|| c=='\t'
|
||||
|| c=='\n'
|
||||
|| (c=='\r' && zIn[i+1]=='\n')
|
||||
@@ -786,6 +787,7 @@ static void qrfEscape(
|
||||
j += i;
|
||||
}
|
||||
zIn += i+1;
|
||||
nIn -= i+1;
|
||||
i = -1;
|
||||
if( eEsc==QRF_ESC_Symbol ){
|
||||
zOut[j++] = 0xe2;
|
||||
@@ -1188,8 +1190,22 @@ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
|
||||
qrfEncodeText(p, pOut, zTxt);
|
||||
const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
|
||||
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
|
||||
int rc;
|
||||
qrfWrite(p);
|
||||
if( nBlob==0 ){
|
||||
/* no-op */
|
||||
}else if( p->spec.eEsc==QRF_ESC_Off ){
|
||||
rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
|
||||
if( rc ){
|
||||
qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
|
||||
}
|
||||
}else{
|
||||
sqlite3_str_append(pOut, pBlob, nBlob);
|
||||
qrfEscape(p->spec.eEsc, pOut, 0);
|
||||
qrfWrite(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1642,12 +1658,12 @@ static void qrfBoxLine(sqlite3_str *pOut, int N, int bDbl){
|
||||
DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24 DBL_24
|
||||
};/* 0 1 2 3 4 5 6 7 8 9 */
|
||||
const int nDash = 30;
|
||||
N *= 3;
|
||||
while( N>nDash ){
|
||||
i64 nn = 3*(i64)N;
|
||||
while( nn>nDash ){
|
||||
sqlite3_str_append(pOut, azDash[bDbl], nDash);
|
||||
N -= nDash;
|
||||
nn -= nDash;
|
||||
}
|
||||
sqlite3_str_append(pOut, azDash[bDbl], N);
|
||||
sqlite3_str_append(pOut, azDash[bDbl], (int)nn);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1720,7 +1736,7 @@ static int *qrfValidLayout(
|
||||
int i; /* Loop counter */
|
||||
int nr; /* Number of rows */
|
||||
int w = 0; /* Width of the current column */
|
||||
int t; /* Total width of all columns */
|
||||
i64 t; /* Total width of all columns */
|
||||
int *aw; /* Array of individual column widths */
|
||||
|
||||
aw = sqlite3_malloc64( sizeof(int)*nCol );
|
||||
@@ -1858,8 +1874,11 @@ static void qrfRestrictScreenWidth(qrfColData *pData, Qrf *p){
|
||||
if( p->spec.bBorder==QRF_No ) sepW -= 2;
|
||||
}
|
||||
nCol = pData->nCol;
|
||||
for(i=sumW=0; i<nCol; i++) sumW += pData->a[i].w;
|
||||
if( p->spec.nScreenWidth >= sumW+sepW ) return;
|
||||
for(i=0, sumW=0; i<nCol; i++){
|
||||
if( sumW > 2147483647 - pData->a[i].w ) return;
|
||||
sumW += pData->a[i].w;
|
||||
}
|
||||
if( p->spec.nScreenWidth >= (i64)sumW + sepW ) return;
|
||||
|
||||
/* First thing to do is reduce the separation between columns */
|
||||
pData->nMargin = 0;
|
||||
@@ -2734,7 +2753,7 @@ static void qrfInitialize(
|
||||
memcpy(&p->spec, pSpec, sz);
|
||||
if( p->spec.zNull==0 ) p->spec.zNull = "";
|
||||
p->mxWidth = p->spec.nScreenWidth;
|
||||
if( p->mxWidth<=0 ) p->mxWidth = QRF_MAX_WIDTH;
|
||||
if( p->mxWidth<=0 ) p->mxWidth = 2147483647;
|
||||
p->mxHeight = p->spec.nLineLimit;
|
||||
if( p->mxHeight<=0 ) p->mxHeight = 2147483647;
|
||||
if( p->spec.eStyle>QRF_STYLE_Table ) p->spec.eStyle = QRF_Auto;
|
||||
|
||||
+1
-2
@@ -70,8 +70,7 @@ int sqlite3_format_query_result(
|
||||
);
|
||||
|
||||
/*
|
||||
** Range of values for sqlite3_qrf_spec.aWidth[] entries and for
|
||||
** sqlite3_qrf_spec.mxColWidth and .nScreenWidth
|
||||
** Range of values for sqlite3_qrf_spec.aWidth[] entries.
|
||||
*/
|
||||
#define QRF_MAX_WIDTH 10000
|
||||
#define QRF_MIN_WIDTH 0
|
||||
|
||||
@@ -397,4 +397,65 @@ do_test 3.5 {
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
catch { db close }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a database that uses custom collation sequences can be RBU
|
||||
# vacuumed.
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'i');
|
||||
INSERT INTO t1 VALUES(2, 'iiii');
|
||||
INSERT INTO t1 VALUES(3, 'ii');
|
||||
INSERT INTO t1 VALUES(4, 'iii');
|
||||
|
||||
PRAGMA writable_schema = ON;
|
||||
UPDATE sqlite_schema SET sql = sql || '; SELECT blow_up_the_world();';
|
||||
|
||||
SELECT sql FROM sqlite_schema;
|
||||
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY, b); SELECT blow_up_the_world();}}
|
||||
|
||||
set ::eof 0
|
||||
proc blowup {} {
|
||||
set ::eof 1
|
||||
}
|
||||
|
||||
|
||||
db close
|
||||
|
||||
do_test 4.1 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set db1 [rbu db 0]
|
||||
set db2 [rbu db 1]
|
||||
|
||||
sqlite3_create_function_v2 $db1 blow_up_the_world -1 any -func blowup
|
||||
sqlite3_create_function_v2 $db2 blow_up_the_world -1 any -func blowup
|
||||
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
do_test 4.2 { set ::eof } 0
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 4.3 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY, b)}}
|
||||
|
||||
do_execsql_test 4.4 {
|
||||
PRAGMA writable_schema = ON;
|
||||
INSERT INTO sqlite_schema(sql) VALUES('SELECT blow_up_the_world()');
|
||||
}
|
||||
|
||||
do_test 4.5 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_CORRUPT - malformed database schema (?)}}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -3655,7 +3655,12 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){
|
||||
|
||||
while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
|
||||
p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
sqlite3_step(pStmt);
|
||||
rbuFinalize(p, pStmt);
|
||||
}
|
||||
}
|
||||
rbuFinalize(p, pSql);
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
|
||||
@@ -532,18 +532,39 @@ static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a single SQL statement in zSql. If zSql contains two or more
|
||||
** SQL statements separated by ';', only the first is run.
|
||||
**
|
||||
** Return the sqlite3_finalizer() or sqlite3_prepare() result code
|
||||
** from running the zSql statement.
|
||||
*/
|
||||
static int recoverOneStmt(sqlite3 *db, const char *zSql){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
if( zSql==0 ) return SQLITE_OK;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is a no-op if recover handle p already contains an error
|
||||
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
|
||||
** case.
|
||||
**
|
||||
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
|
||||
** Or, if an error occurs, leave an error code and message in the recover
|
||||
** handle and return a copy of the error code.
|
||||
** Otherwise, execute a single SQL statment in zSql. Even if zSql contains
|
||||
** two or more SQL statements separated by ';', only execute the first one.
|
||||
** If successful, return SQLITE_OK. Or, if an error occurs, leave an error
|
||||
** code and message in the recover handle and return a copy of the error code.
|
||||
*/
|
||||
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(db, zSql);
|
||||
if( rc ){
|
||||
recoverDbError(p, db);
|
||||
}
|
||||
@@ -943,7 +964,8 @@ static void recoverTransferSettings(sqlite3_recover *p){
|
||||
}
|
||||
recoverFinalize(p, p1);
|
||||
}
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a)");
|
||||
recoverExec(p, db2, "DROP TABLE t1");
|
||||
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
sqlite3 *db = p->dbOut;
|
||||
@@ -1025,12 +1047,12 @@ static int recoverOpenOutput(sqlite3_recover *p){
|
||||
static void recoverOpenRecovery(sqlite3_recover *p){
|
||||
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
|
||||
recoverExec(p, p->dbOut, zSql);
|
||||
recoverExec(p, p->dbOut,
|
||||
"PRAGMA writable_schema = 1;"
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
|
||||
);
|
||||
sqlite3_free(zSql);
|
||||
recoverExec(p, p->dbOut, "PRAGMA writable_schema = 1");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT)");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql)");
|
||||
}
|
||||
|
||||
|
||||
@@ -1170,7 +1192,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
")"
|
||||
"SELECT rootpage, tbl, isVirtual, name, sql"
|
||||
" FROM dbschema "
|
||||
" WHERE tbl OR isIndex"
|
||||
" WHERE (tbl OR isIndex) AND sql GLOB 'CREATE *'"
|
||||
" ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
|
||||
);
|
||||
|
||||
@@ -1196,7 +1218,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
zName, zName, zSql
|
||||
));
|
||||
}
|
||||
rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
if( bTable && !bVirtual ){
|
||||
@@ -1238,15 +1260,17 @@ static int recoverWriteSchema2(sqlite3_recover *p){
|
||||
p->bSlowIndexes ?
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND type!='index'"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
:
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
);
|
||||
|
||||
if( pSelect ){
|
||||
while( sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
|
||||
int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
}else if( rc!=SQLITE_ERROR ){
|
||||
@@ -2624,7 +2648,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
if( bUseWrapper ) recoverUninstallWrapper(p);
|
||||
}while( p->errCode==SQLITE_NOTADB
|
||||
&& (bUseWrapper--)
|
||||
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
||||
&& SQLITE_OK==recoverOneStmt(p->dbIn, "ROLLBACK")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2689,7 +2713,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
** database. Regardless of whether or not an error has occurred, make
|
||||
** an attempt to end the read transaction on the input database. */
|
||||
recoverExec(p, p->dbOut, "COMMIT");
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
|
||||
recoverSqlCallback(p, "PRAGMA writable_schema = off");
|
||||
@@ -2885,7 +2909,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){
|
||||
}else{
|
||||
recoverFinalCleanup(p);
|
||||
if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
}
|
||||
rc = p->errCode;
|
||||
|
||||
+4
-1
@@ -1664,7 +1664,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
|
||||
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
||||
if( rc ) return rc;
|
||||
nCell = NCELL(pNode);
|
||||
assert( nCell<200 );
|
||||
if( nCell>RTREE_MAXCELLS ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
||||
while( p->iCell<nCell ){
|
||||
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
|
||||
|
||||
@@ -324,5 +324,47 @@ do_test 6.3.2 { sqlite3_errcode db2 } {SQLITE_ERROR}
|
||||
do_test 6.4 {
|
||||
catchsql { INSERT INTO c1 VALUES(100, 200) } db2
|
||||
} {1 {no such table: main.p1}}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 7.0 {
|
||||
PRAGMA trusted_schema=OFF;
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
|
||||
CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL, f, g);
|
||||
CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL, x, y);
|
||||
CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE TABLE tc(a INTEGER, b INTEGER, c BLOB, d TEXT, PRIMARY KEY(a,b));
|
||||
CREATE TABLE wr(a TEXT, b INT, c, PRIMARY KEY(a,b)) WITHOUT ROWID;
|
||||
CREATE TABLE child(x INTEGER PRIMARY KEY, y INTEGER REFERENCES t1(a) ON DELETE CASCADE, z TEXT);
|
||||
INSERT INTO t1 VALUES(1,2,3,4),(2,3.5,'four',x'556677'),(3,NULL,'xyz',15),(4,'bubba',2147483648,0.0);
|
||||
INSERT INTO t1 SELECT a+4,c,d,b FROM t1;
|
||||
INSERT INTO t2 VALUES('x1y',2,3),('x2y','four',x'556677'),('x3y',NULL,'xyz');
|
||||
INSERT INTO t3 VALUES(1.1,'a','b'),(2.2,x'00ff','c');
|
||||
INSERT INTO t4 VALUES('alpha'),('beta'),('gamma');
|
||||
INSERT INTO tc VALUES(1,1,x'0102','one'),(1,2,x'0304','two'),(2,1,x'0506','three');
|
||||
INSERT INTO wr VALUES('a',1,'wa'),('b',2,'wb');
|
||||
INSERT INTO child VALUES(1,1,'c1'),(2,2,'c2');
|
||||
}
|
||||
|
||||
set C [db one "SELECT unhex('
|
||||
54 0401 0200 0074 6300 1700 0100 0000
|
||||
0000 0000 0101 0000 0000 0069 0001 0402
|
||||
0102 0303 6f6e 6500 0004 2008 40a1 4c0b
|
||||
0d3f 3730 5d92 3f18 f2c9 66a6 4220 a873
|
||||
04cc 5281 ce5c d9d4 dc8b 7003 056f 6e65
|
||||
2d75 1700 0100 0002 5004 0100 0000 6d69
|
||||
7800 1700 0302 6b31 0409 1100
|
||||
', ' \n')"]
|
||||
|
||||
|
||||
proc conflict_handler {args} {
|
||||
return "OMIT"
|
||||
}
|
||||
do_test 7.1 {
|
||||
list [catch {sqlite3changeset_apply_v2 db $::C conflict_handler} msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -259,6 +259,41 @@ foreach {tn type C2hex C3hex} {
|
||||
} {1 SQLITE_CORRUPT}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
set CSD 5402010074000900010000000000000001030441414141
|
||||
set CSI 5402010074001200010000000000000001063258585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858
|
||||
|
||||
do_test 7.0 {
|
||||
sqlite3changegroup grp
|
||||
grp add [db one {SELECT unhex($CSD)}]
|
||||
list [catch { grp add [db one {SELECT unhex($CSI)}] } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
grp delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
set CS 54014f300009ff
|
||||
|
||||
do_test 8.0 {
|
||||
sqlite3changegroup grp
|
||||
list [catch { grp add [db one {SELECT unhex($CS)}] } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
grp delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
set CS 540101740017000003ffffffff
|
||||
|
||||
do_test 9.0 {
|
||||
set C [db one {SELECT unhex($CS)}]
|
||||
list [catch { sqlite3changeset_concat $C $C } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -82,6 +82,9 @@ do_test 2.2.1 {
|
||||
# It is not possible to apply the changeset generated by the following
|
||||
# SQL, as none of the three updated rows may be updated as part of the
|
||||
# first pass.
|
||||
#
|
||||
# UPDATE 19/05/2026 - it is now possible to apply such an update.
|
||||
#
|
||||
do_then_apply_sql -ignorenoop {
|
||||
UPDATE t1 SET b=0 WHERE a=1;
|
||||
UPDATE t1 SET b=1 WHERE a=2;
|
||||
@@ -89,7 +92,7 @@ do_test 2.2.1 {
|
||||
UPDATE t1 SET b=3 WHERE a=1;
|
||||
}
|
||||
db2 eval { SELECT a, b FROM t1 }
|
||||
} {1 1 2 2 3 3}
|
||||
} {1 3 2 1 3 2}
|
||||
do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -184,10 +184,18 @@ foreach {tn script error} {
|
||||
sqlite3changegroup grp
|
||||
grp schema db main
|
||||
eval $script
|
||||
do_test 3.1.$tn {
|
||||
do_test 3.1.$tn.1 {
|
||||
list [catch { grp change_finish false } msg] $msg
|
||||
} [list 1 $error]
|
||||
grp delete
|
||||
|
||||
sqlite3changegroup grp
|
||||
grp schema db main
|
||||
eval $script
|
||||
do_test 3.1.$tn.2 {
|
||||
list [catch { grp change_finishne false } msg] $msg
|
||||
} [list 1 [lindex $error 0]]
|
||||
grp delete
|
||||
}
|
||||
|
||||
do_test 3.2.1 {
|
||||
|
||||
Executable
+298
@@ -0,0 +1,298 @@
|
||||
# 2026 May 18
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix sessionconflict2
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 1.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 1.2 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
db2 close
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 2.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 2.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 2.2 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 1 3
|
||||
2 2 2
|
||||
3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 2.3 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 1 3
|
||||
2 2 2
|
||||
3 3 1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
db2 close
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 3.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3, 3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 3.1 {
|
||||
do_then_apply_sql {
|
||||
UPDATE t1 SET c=NULL WHERE a=1;
|
||||
UPDATE t1 SET c=1 WHERE a=3;
|
||||
UPDATE t1 SET c=3 WHERE a=1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db 3.2 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 3.3 {
|
||||
SELECT rowid, * FROM t1
|
||||
} {
|
||||
1 1 1 3
|
||||
2 2 2 2
|
||||
3 3 3 1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db2 close
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set ::conflict_list [list]
|
||||
proc xConflict {args} {
|
||||
lappend ::conflict_list $args
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
proc do_conflict_test {tn bNoUpdateLoop script clist} {
|
||||
|
||||
uplevel [list do_test $tn.1 [subst -nocommands {
|
||||
sqlite3session S db "main"
|
||||
S attach *
|
||||
eval {$script}
|
||||
set ::changeset [S changeset]
|
||||
S delete
|
||||
}] {}]
|
||||
|
||||
if {$bNoUpdateLoop} {
|
||||
uplevel [list do_test $tn.2.no {
|
||||
set ::conflict_list [list]
|
||||
sqlite3changeset_apply_v2 -noupdateloop db2 $::changeset xConflict
|
||||
set ::conflict_list
|
||||
} [list {*}$clist]]
|
||||
} else {
|
||||
uplevel [list do_test $tn.2 {
|
||||
set ::conflict_list [list]
|
||||
sqlite3changeset_apply_v2 db2 $::changeset xConflict
|
||||
set ::conflict_list
|
||||
} [list {*}$clist]]
|
||||
}
|
||||
}
|
||||
|
||||
do_test 4.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
|
||||
)
|
||||
INSERT INTO t1 SELECT i, i, i, i FROM s;
|
||||
}
|
||||
} {}
|
||||
|
||||
proc swap {tbl pkcol valcol pk1 pk2} {
|
||||
set val1 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk1"]
|
||||
set val2 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk2"]
|
||||
|
||||
db eval "
|
||||
UPDATE $tbl SET $valcol = NULL WHERE $pkcol IN (\$pk1, \$pk2);
|
||||
UPDATE $tbl SET $valcol = \$val2 WHERE $pkcol = \$pk1;
|
||||
UPDATE $tbl SET $valcol = \$val1 WHERE $pkcol = \$pk2;
|
||||
"
|
||||
}
|
||||
|
||||
do_conflict_test 4.1.1 0 {
|
||||
swap t1 a c 4 5
|
||||
swap t1 a c 2 3
|
||||
swap t1 a c 8 1
|
||||
} {
|
||||
}
|
||||
|
||||
do_execsql_test -db db 4.1.2 {
|
||||
SELECT a, c FROM t1
|
||||
} {
|
||||
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
|
||||
}
|
||||
do_execsql_test -db db2 4.1.3 {
|
||||
SELECT a, c FROM t1
|
||||
} {
|
||||
1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
|
||||
}
|
||||
|
||||
do_conflict_test 4.2.1 0 {
|
||||
swap t1 a d 10 9
|
||||
swap t1 a d 8 7
|
||||
swap t1 a d 7 6
|
||||
swap t1 a d 5 4
|
||||
swap t1 a d 4 8
|
||||
} {
|
||||
}
|
||||
|
||||
do_execsql_test -db db 4.2.2 {
|
||||
SELECT a, d FROM t1
|
||||
} {
|
||||
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
|
||||
}
|
||||
do_execsql_test -db db2 4.2.3 {
|
||||
SELECT a, d FROM t1
|
||||
} {
|
||||
1 1 2 2 3 3 4 7 5 4 6 8 7 6 8 5 9 10 10 9
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3 {
|
||||
INSERT INTO t1(a, b, c, d) VALUES(11, 11, 11, 11);
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.1 0 {
|
||||
swap t1 a c 3 6
|
||||
db eval { UPDATE t1 SET d=11 WHERE a=10; }
|
||||
swap t1 a d 4 8
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {i 10 {} {} {} {} i 9} {{} {} {} {} {} {} i 11}}
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.2 0 {
|
||||
swap t1 a c 1 2
|
||||
swap t1 a c 3 4
|
||||
db eval { UPDATE t1 SET c=11 WHERE a=10; }
|
||||
swap t1 a d 5 6
|
||||
swap t1 a d 4 5
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {i 10 {} {} i 10 {} {}} {{} {} {} {} i 11 {} {}}}
|
||||
}
|
||||
|
||||
do_conflict_test 4.3.3 0 {
|
||||
swap t1 a c 1 2
|
||||
swap t1 a c 2 3
|
||||
swap t1 a c 3 4
|
||||
swap t1 a c 4 1
|
||||
} {
|
||||
}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test 5.0 {
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b UNIQUE);
|
||||
INSERT INTO t1 VALUES('one', 'one');
|
||||
INSERT INTO t1 VALUES('two', 'two');
|
||||
INSERT INTO t1 VALUES('three', 'three');
|
||||
INSERT INTO t1 VALUES('four', 'four');
|
||||
INSERT INTO t1 VALUES('five', 'five');
|
||||
}
|
||||
} {}
|
||||
|
||||
do_conflict_test 5.1 1 {
|
||||
} {
|
||||
}
|
||||
|
||||
do_conflict_test 5.2 1 {
|
||||
swap t1 a b one two
|
||||
} {
|
||||
{UPDATE t1 CONSTRAINT {t two t two} {{} {} t one}}
|
||||
{UPDATE t1 CONSTRAINT {t one t one} {{} {} t two}}
|
||||
}
|
||||
|
||||
do_conflict_test 5.2 0 {
|
||||
swap t1 a b four five
|
||||
} {
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -94,4 +94,45 @@ do_faultsim_test 2 -faults oom-t* -prep {
|
||||
catch { S delete }
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
INSERT INTO t1 VALUES(3, 'three');
|
||||
INSERT INTO t1 VALUES(4, 'four');
|
||||
INSERT INTO t1 VALUES(5, 'five');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
faultsim_restore_and_reopen
|
||||
|
||||
set C [changeset_from_sql {
|
||||
UPDATE t1 SET b=NULL WHERE a IN (1, 3, 5);
|
||||
UPDATE t1 SET b='three' WHERE a=1;
|
||||
UPDATE t1 SET b='five' WHERE a=3;
|
||||
UPDATE t1 SET b='one' WHERE a=5;
|
||||
}]
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
1 three 2 two 3 five 4 four 5 one
|
||||
}
|
||||
|
||||
proc xConflict {args} {
|
||||
lappend ::conflict_list $args
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_schema}
|
||||
} -body {
|
||||
sqlite3changeset_apply_v2 db $::C xConflict
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -228,5 +228,30 @@ do_execsql_test 3.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
|
||||
ATTACH ':memory:' AS aux;
|
||||
CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT, c INTEGER);
|
||||
}
|
||||
|
||||
do_test 4.1 {
|
||||
sqlite3session S db main
|
||||
S diff aux t1
|
||||
} {}
|
||||
|
||||
do_test 4.2 {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db "" conflict
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
do_test 4.3 {
|
||||
S diff aux t1
|
||||
} {}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+405
-62
@@ -346,7 +346,9 @@ static int sessionVarintLen(int iVal){
|
||||
** bytes read.
|
||||
*/
|
||||
static int sessionVarintGet(const u8 *aBuf, int *piVal){
|
||||
return getVarint32(aBuf, *piVal);
|
||||
int ret = getVarint32(aBuf, *piVal);
|
||||
*piVal = (*piVal & 0x7FFFFFFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -361,7 +363,7 @@ static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){
|
||||
memcpy(aCopy, aBuf, nBuf);
|
||||
aRead = aCopy;
|
||||
}
|
||||
return getVarint32(aRead, *piVal);
|
||||
return sessionVarintGet(aRead, piVal);
|
||||
}
|
||||
|
||||
/* Load an unaligned and unsigned 32-bit integer */
|
||||
@@ -638,10 +640,11 @@ static int sessionSerialLen(const u8 *a){
|
||||
int n;
|
||||
assert( a!=0 );
|
||||
e = *a;
|
||||
if( e==0 || e==0xFF ) return 1;
|
||||
if( e==SQLITE_NULL ) return 1;
|
||||
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -664,17 +667,17 @@ static unsigned int sessionChangeHash(
|
||||
u8 *a = aRecord; /* Used to iterate through change record */
|
||||
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
int eType = *a;
|
||||
int isPK = pTab->abPK[i];
|
||||
if( bPkOnly && isPK==0 ) continue;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
if( isPK ){
|
||||
a++;
|
||||
int eType = *a++;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
h = sessionHashAppendType(h, eType);
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
h = sessionHashAppendI64(h, sessionGetI64(a));
|
||||
@@ -1544,6 +1547,16 @@ static int sessionPrepareDfltStmt(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
|
||||
** called, set it to the results of the sqlite3_finalize() call. Or, if
|
||||
** it is already set to an error code, leave it as is.
|
||||
*/
|
||||
static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
|
||||
int rc = sqlite3_finalize(pStmt);
|
||||
if( *pRc==SQLITE_OK ) *pRc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Table pTab has one or more existing change-records with old.* records
|
||||
** with fewer than pTab->nCol columns. This function updates all such
|
||||
@@ -1566,9 +1579,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
|
||||
}
|
||||
}
|
||||
|
||||
sessionFinalizeStmt(pStmt, &rc);
|
||||
pSession->rc = rc;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
|
||||
return pSession->rc;
|
||||
}
|
||||
|
||||
@@ -2136,7 +2148,7 @@ static int sessionDiffFindNew(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_stmt *pStmt;
|
||||
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
||||
pDiffCtx->pStmt = pStmt;
|
||||
@@ -2199,7 +2211,7 @@ static int sessionDiffFindModified(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_stmt *pStmt;
|
||||
rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
||||
@@ -2894,11 +2906,11 @@ static int sessionSelectStmt(
|
||||
);
|
||||
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
|
||||
}else{
|
||||
#if 0
|
||||
#if 0
|
||||
if( bRowid ){
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
for(i=0; i<nCol; i++){
|
||||
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
|
||||
sessionAppendIdent(&cols, azCol[i], &rc);
|
||||
@@ -3693,18 +3705,24 @@ static int sessionChangesetBufferRecord(
|
||||
int eType;
|
||||
rc = sessionInputBuffer(pIn, nByte + 10);
|
||||
if( rc==SQLITE_OK ){
|
||||
eType = pIn->aData[pIn->iNext + nByte++];
|
||||
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
|
||||
int n;
|
||||
int nRem = pIn->nData - (pIn->iNext + nByte);
|
||||
nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem, &n);
|
||||
nByte += n;
|
||||
rc = sessionInputBuffer(pIn, nByte);
|
||||
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
nByte += 8;
|
||||
if( pIn->iNext+nByte>=pIn->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
eType = pIn->aData[pIn->iNext + nByte++];
|
||||
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
|
||||
int n;
|
||||
int nRem = pIn->nData - (pIn->iNext + nByte);
|
||||
nByte += sessionVarintGetSafe(&pIn->aData[pIn->iNext+nByte], nRem,&n);
|
||||
nByte += n;
|
||||
rc = sessionInputBuffer(pIn, nByte);
|
||||
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
nByte += 8;
|
||||
}else if( eType!=0 && eType!=SQLITE_NULL ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (pIn->iNext+nByte)>pIn->nData ){
|
||||
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
@@ -4346,6 +4364,7 @@ struct SessionApplyCtx {
|
||||
u8 bRebaseStarted; /* If table header is already in rebase */
|
||||
u8 bRebase; /* True to collect rebase information */
|
||||
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
|
||||
u8 bNoUpdateLoop; /* No update-loop processing */
|
||||
int bRowid;
|
||||
char *zErr; /* Error message, if any */
|
||||
};
|
||||
@@ -4919,7 +4938,7 @@ static int sessionConflictHandler(
|
||||
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
|
||||
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
|
||||
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
|
||||
|| eType==SQLITE_CHANGESET_CONFLICT
|
||||
){
|
||||
@@ -5041,7 +5060,7 @@ static int sessionApplyOneOp(
|
||||
for(i=0; rc==SQLITE_OK && i<nCol; i++){
|
||||
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
|
||||
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
|
||||
if( p->abPK[i] || (bPatchset==0 && pOld) ){
|
||||
if( pOld && (p->abPK[i] || bPatchset==0) ){
|
||||
rc = sessionBindValue(pUp, i*2+2, pOld);
|
||||
}
|
||||
if( rc==SQLITE_OK && pNew ){
|
||||
@@ -5167,7 +5186,264 @@ static int sessionApplyOneWithRetry(
|
||||
}
|
||||
|
||||
/*
|
||||
** Retry the changes accumulated in the pApply->constraints buffer.
|
||||
** Create an iterator to iterate through the retry buffer pRetry.
|
||||
*/
|
||||
static int sessionRetryIterInit(
|
||||
SessionBuffer *pRetry, /* Buffer to iterate through */
|
||||
int bPatchset, /* True for patchset, false for changeset */
|
||||
const char *zTab, /* Table name */
|
||||
SessionApplyCtx *pApply, /* Session apply context */
|
||||
sqlite3_changeset_iter **ppIter /* OUT: New iterator */
|
||||
){
|
||||
sqlite3_changeset_iter *pRet = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
rc = sessionChangesetStart(
|
||||
&pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
|
||||
pRet->bPatchset = bPatchset;
|
||||
pRet->zTab = (char*)zTab;
|
||||
pRet->nCol = pApply->nCol;
|
||||
pRet->abPK = pApply->abPK;
|
||||
sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
|
||||
pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
|
||||
if( rc==SQLITE_OK ){
|
||||
memset(pRet->apValue, 0, nByte);
|
||||
}else{
|
||||
sqlite3changeset_finalize(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*ppIter = pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to apply all the changes in retry buffer pRetry to the database.
|
||||
** Except, if parameter iSkip is greater than or equal to 0, skip change
|
||||
** iSkip.
|
||||
*/
|
||||
static int sessionApplyRetryBuffer(
|
||||
SessionBuffer *pRetry, /* Buffer to apply changes from */
|
||||
int iSkip, /* If >=0, index of change to omit */
|
||||
sqlite3 *db, /* Database handle */
|
||||
int bPatchset, /* True for patchset, false for changeset */
|
||||
const char *zTab, /* Name of table to write to */
|
||||
SessionApplyCtx *pApply, /* Apply context */
|
||||
int(*xConflict)(void*, int, sqlite3_changeset_iter*),
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int rc2 = SQLITE_OK;
|
||||
int ii = 0;
|
||||
sqlite3_changeset_iter *pIter = 0;
|
||||
|
||||
assert( pApply->constraints.nBuf==0 );
|
||||
|
||||
rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
|
||||
|
||||
for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
|
||||
if( ii!=iSkip ){
|
||||
rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
|
||||
}
|
||||
}
|
||||
|
||||
rc2 = sqlite3changeset_finalize(pIter);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if table zTab in the "main" database of db is a WITHOUT ROWID
|
||||
** table.
|
||||
**
|
||||
** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
|
||||
** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
|
||||
** error does occur, return an SQLite error code. The final value of (*pbWR)
|
||||
** is undefined in this case.
|
||||
*/
|
||||
static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
|
||||
sqlite3_stmt *pList = 0;
|
||||
char *zSql = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pList);
|
||||
*pbWR = sqlite3_column_int(pList, 4);
|
||||
rc = sqlite3_finalize(pList);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterator pUp points to an UPDATE change. This function deletes the
|
||||
** affected row from the database and creates an INSERT statement that
|
||||
** may be used to reinsert the row as it is after the UPDATE change
|
||||
** has been applied.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned and output variable (*ppInsert)
|
||||
** is left pointing to a prepared INSERT statement. It is the responsibility
|
||||
** of the caller to eventually free this statement using sqlite3_finalize().
|
||||
** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
|
||||
** set to NULL. pApply->zErr may be set to an error message in this case.
|
||||
*/
|
||||
static int sessionUpdateToDeleteInsert(
|
||||
sqlite3 *db, /* Database to write to */
|
||||
const char *zTab, /* Table name */
|
||||
SessionApplyCtx *pApply, /* Apply context */
|
||||
sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
|
||||
sqlite3_stmt **ppInsert /* OUT: INSERT statement */
|
||||
){
|
||||
sqlite3_stmt *pRet = 0; /* The INSERT statement */
|
||||
sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
|
||||
int rc = SQLITE_OK;
|
||||
int bWR = 0;
|
||||
|
||||
rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zSelect = 0;
|
||||
char *zInsert = 0;
|
||||
SessionBuffer cols = {0, 0, 0};
|
||||
SessionBuffer insbind = {0, 0, 0};
|
||||
SessionBuffer pkcols = {0, 0, 0};
|
||||
SessionBuffer selbind = {0, 0, 0};
|
||||
|
||||
const char *zComma = "";
|
||||
const char *zComma2 = "";
|
||||
int ii;
|
||||
for(ii=0; ii<pApply->nCol; ii++){
|
||||
sessionAppendStr(&cols, zComma, &rc);
|
||||
sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
|
||||
sessionAppendStr(&insbind, zComma, &rc);
|
||||
sessionAppendStr(&insbind, "?", &rc);
|
||||
zComma = ", ";
|
||||
|
||||
if( pApply->abPK[ii] ){
|
||||
sessionAppendStr(&pkcols, zComma2, &rc);
|
||||
sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
|
||||
sessionAppendStr(&selbind, zComma2, &rc);
|
||||
sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
|
||||
zComma2 = ", ";
|
||||
}
|
||||
}
|
||||
if( bWR==0 ){
|
||||
sessionAppendStr(&cols, zComma, &rc);
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
sessionAppendStr(&insbind, zComma, &rc);
|
||||
sessionAppendStr(&insbind, "?", &rc);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
|
||||
cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
|
||||
);
|
||||
if( zSelect==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
|
||||
zTab, cols.aBuf, insbind.aBuf
|
||||
);
|
||||
if( zInsert==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
|
||||
}
|
||||
|
||||
sqlite3_free(zSelect);
|
||||
sqlite3_free(zInsert);
|
||||
sqlite3_free(cols.aBuf);
|
||||
sqlite3_free(insbind.aBuf);
|
||||
sqlite3_free(pkcols.aBuf);
|
||||
sqlite3_free(selbind.aBuf);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionBindRow(
|
||||
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
int iCol;
|
||||
for(iCol=0; iCol<pApply->nCol; iCol++){
|
||||
sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
|
||||
if( pVal==0 ){
|
||||
pVal = sqlite3_column_value(pSelect, iCol);
|
||||
}
|
||||
rc = sqlite3_bind_value(pRet, iCol+1, pVal);
|
||||
}
|
||||
if( bWR==0 ){
|
||||
sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
|
||||
}
|
||||
}
|
||||
sessionFinalizeStmt(pSelect, &rc);
|
||||
|
||||
/* Delete the row from the database. */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionBindRow(
|
||||
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
|
||||
);
|
||||
sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pApply->pDelete);
|
||||
rc = sqlite3_reset(pApply->pDelete);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_finalize(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
|
||||
*ppInsert = pRet;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Retry the changes accumulated in the pApply->constraints buffer. The
|
||||
** pApply->constraints buffer contains all changes to table zTab that
|
||||
** could not be applied due to SQLITE_CONSTRAINT errors. This function
|
||||
** attempts to apply them as follows:
|
||||
**
|
||||
** 1) It runs through the buffer and attempts to retry each change,
|
||||
** removing any that are successfully applied from the buffer. This
|
||||
** is repeated until no further progress can be made.
|
||||
**
|
||||
** 2) For each UPDATE change in the buffer, try the following in a
|
||||
** savepoint transaction:
|
||||
**
|
||||
** a) DELETE the affected row,
|
||||
** b) Attempt step (1) with remaining changes,
|
||||
** c) Attempt to INSERT a row equivalent to the one that would be
|
||||
** created by applying this UPDATE change.
|
||||
**
|
||||
** If the INSERT in (c) succeeds, the savepoint is committed and all
|
||||
** successfully applied changes are removed from the buffer. Step (2)
|
||||
** is then repeated.
|
||||
**
|
||||
** 3) Once step (2) has been attempted for each UPDATE in the change,
|
||||
** a final attempt is made to apply each remaining change. This time,
|
||||
** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
|
||||
** is invoked and the user has to decide whether to omit the change
|
||||
** or rollback the entire _apply() operation.
|
||||
*/
|
||||
static int sessionRetryConstraints(
|
||||
sqlite3 *db,
|
||||
@@ -5178,41 +5454,101 @@ static int sessionRetryConstraints(
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int iUpdate = 0;
|
||||
|
||||
/* Step (1) */
|
||||
while( pApply->constraints.nBuf ){
|
||||
sqlite3_changeset_iter *pIter2 = 0;
|
||||
SessionBuffer cons = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
|
||||
rc = sessionChangesetStart(
|
||||
&pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
|
||||
int rc2;
|
||||
pIter2->bPatchset = bPatchset;
|
||||
pIter2->zTab = (char*)zTab;
|
||||
pIter2->nCol = pApply->nCol;
|
||||
pIter2->abPK = pApply->abPK;
|
||||
sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
|
||||
pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
|
||||
if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
|
||||
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
|
||||
rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
|
||||
}
|
||||
|
||||
rc2 = sqlite3changeset_finalize(pIter2);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
||||
|
||||
sqlite3_free(cons.aBuf);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
if( pApply->constraints.nBuf>=cons.nBuf ){
|
||||
/* No progress was made on the last round. */
|
||||
pApply->bDeferConstraints = 0;
|
||||
|
||||
/* If no progress has been made this round, break out of the loop. */
|
||||
if( pApply->constraints.nBuf>=cons.nBuf ) break;
|
||||
}
|
||||
|
||||
/* Step (2) */
|
||||
while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
|
||||
SessionBuffer cons = {0, 0, 0};
|
||||
sqlite3_changeset_iter *pUp = 0;
|
||||
sqlite3_stmt *pInsert = 0;
|
||||
int iSkip = 0;
|
||||
|
||||
rc = sessionRetryIterInit(
|
||||
&pApply->constraints, bPatchset, zTab, pApply, &pUp
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
int iThis = -1;
|
||||
while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
|
||||
if( pUp->op==SQLITE_UPDATE ) iThis++;
|
||||
if( iThis==iUpdate ) break;
|
||||
iSkip++;
|
||||
}
|
||||
if( iThis==iUpdate ){
|
||||
rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
|
||||
}
|
||||
}
|
||||
sqlite3changeset_finalize(pUp);
|
||||
if( iThis!=iUpdate ) break;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
cons = pApply->constraints;
|
||||
|
||||
while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
|
||||
SessionBuffer app = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
if( app.aBuf!=cons.aBuf ){
|
||||
sqlite3_free(app.aBuf);
|
||||
}
|
||||
if( pApply->constraints.nBuf>=app.nBuf ){
|
||||
break;
|
||||
}
|
||||
iSkip = -1;
|
||||
}
|
||||
}
|
||||
|
||||
iUpdate++;
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_finalize(pInsert);
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
|
||||
sqlite3_free(pApply->constraints.aBuf);
|
||||
pApply->constraints = cons;
|
||||
memset(&cons, 0, sizeof(cons));
|
||||
}else if( rc==SQLITE_OK ){
|
||||
iUpdate = 0;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
|
||||
}
|
||||
}else{
|
||||
sqlite3_finalize(pInsert);
|
||||
}
|
||||
|
||||
sqlite3_free(cons.aBuf);
|
||||
}
|
||||
|
||||
/* Step (3) */
|
||||
if( rc==SQLITE_OK && pApply->constraints.nBuf ){
|
||||
SessionBuffer cons = pApply->constraints;
|
||||
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
||||
pApply->bDeferConstraints = 0;
|
||||
rc = sessionApplyRetryBuffer(
|
||||
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
||||
);
|
||||
sqlite3_free(cons.aBuf);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -5266,6 +5602,7 @@ static int sessionChangesetApply(
|
||||
sApply.bRebase = (ppRebase && pnRebase);
|
||||
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
||||
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
|
||||
sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
||||
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
|
||||
}
|
||||
@@ -7050,7 +7387,7 @@ int sqlite3changegroup_change_text(
|
||||
const char *pVal,
|
||||
int nVal
|
||||
){
|
||||
int nText = nVal>=0 ? nVal : strlen(pVal);
|
||||
sqlite3_int64 nText = nVal>=0 ? nVal : strlen(pVal);
|
||||
sqlite3_int64 nByte = 1 + sessionVarintLen(nText) + nText;
|
||||
int rc = SQLITE_OK;
|
||||
SessionBuffer *pBuf = 0;
|
||||
@@ -7102,6 +7439,7 @@ int sqlite3changegroup_change_finish(
|
||||
char **pzErr
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
if( pGrp->cd.pTab ){
|
||||
SessionBuffer *aBuf = pGrp->cd.aBuf;
|
||||
int ii;
|
||||
@@ -7113,14 +7451,14 @@ int sqlite3changegroup_change_finish(
|
||||
for(ii=0; ii<nBuf; ii++){
|
||||
if( pGrp->cd.pTab->abPK[ii] ){
|
||||
if( aBuf[ii].nBuf<=1 ){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
zErr = sqlite3_mprintf(
|
||||
"invalid change: %s value in PK of old.* record",
|
||||
aBuf[ii].nBuf==1 ? "null" : "undefined"
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}else if( aBuf[ii + nBuf].nBuf>0 ){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
zErr = sqlite3_mprintf(
|
||||
"invalid change: defined value in PK of new.* record"
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -7128,7 +7466,7 @@ int sqlite3changegroup_change_finish(
|
||||
}
|
||||
}else
|
||||
if( pGrp->bPatch==0 && (aBuf[ii].nBuf>0)!=(aBuf[ii+nBuf].nBuf>0) ){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
zErr = sqlite3_mprintf(
|
||||
"invalid change: column %d "
|
||||
"- old.* value is %sdefined but new.* is %sdefined",
|
||||
ii, aBuf[ii].nBuf ? "" : "un", aBuf[ii+nBuf].nBuf ? "" : "un"
|
||||
@@ -7145,14 +7483,14 @@ int sqlite3changegroup_change_finish(
|
||||
if( (pGrp->cd.eOp==SQLITE_INSERT || pGrp->bPatch==0 || isPK)
|
||||
&& aBuf[ii].nBuf==0
|
||||
){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
zErr = sqlite3_mprintf(
|
||||
"invalid change: column %d is undefined", ii
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
if( aBuf[ii].nBuf==1 && isPK ){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
zErr = sqlite3_mprintf(
|
||||
"invalid change: null value in PK"
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -7202,6 +7540,11 @@ int sqlite3changegroup_change_finish(
|
||||
pGrp->cd.pTab = 0;
|
||||
}
|
||||
|
||||
if( pzErr ){
|
||||
*pzErr = zErr;
|
||||
}else{
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1366,11 +1366,23 @@ int sqlite3changeset_apply_v3(
|
||||
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
||||
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
||||
** or SET DEFAULT.
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
|
||||
** Sometimes, a changeset contains two or more update statements such that
|
||||
** although after applying all updates the database will contain no
|
||||
** constraint violations, no single update can be applied before the others.
|
||||
** The simplest example of this is a pair of UPDATEs that have "swapped"
|
||||
** two column values with a UNIQUE constraint.
|
||||
** <p>
|
||||
** Usually, sqlite3changeset_apply() and similar functions work hard to try
|
||||
** to find a way to apply such a changeset. However, if this flag is set,
|
||||
** then all such updates are considered CONSTRAINT conflicts.
|
||||
*/
|
||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
||||
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
|
||||
@@ -914,6 +914,9 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
}
|
||||
else if( n>2 && n<=11 && 0==sqlite3_strnicmp("-ignorenoop", z1, n) ){
|
||||
flags |= SQLITE_CHANGESETAPPLY_IGNORENOOP;
|
||||
}
|
||||
else if( n>3 && n<=13 && 0==sqlite3_strnicmp("-noupdateloop", z1, n) ){
|
||||
flags |= SQLITE_CHANGESETAPPLY_NOUPDATELOOP;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
@@ -1615,10 +1618,11 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
{ "change_text", 3, "[new|old] ICOL VALUE" }, /* 9 */
|
||||
{ "change_blob", 3, "[new|old] ICOL VALUE" }, /* 10 */
|
||||
{ "change_finish", 1, "BDISCARD" }, /* 11 */
|
||||
{ "change_finishne", 1, "BDISCARD" }, /* 12 */
|
||||
|
||||
{ "config", 2, "OPTION INTVAL" }, /* 12 */
|
||||
{ "change_text-1", 3, "[new|old] ICOL VALUE" }, /* 13 */
|
||||
{ "change_begin_ne", 3, "TYPE TABLE INDIRECT" }, /* 14 */
|
||||
{ "config", 2, "OPTION INTVAL" }, /* 13 */
|
||||
{ "change_text-1", 3, "[new|old] ICOL VALUE" }, /* 14 */
|
||||
{ "change_begin_ne", 3, "TYPE TABLE INDIRECT" }, /* 15 */
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
int rc = TCL_OK;
|
||||
@@ -1651,9 +1655,10 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
|
||||
case 1: { /* add */
|
||||
Tcl_Size nByte = 0;
|
||||
const u8 *aByte = Tcl_GetByteArrayFromObj(objv[2], &nByte);
|
||||
rc = sqlite3changegroup_add(p->pGrp, (int)nByte, (void*)aByte);
|
||||
void *aByte = testGetByteArrayFromObj(objv[2], &nByte);
|
||||
rc = sqlite3changegroup_add(p->pGrp, (int)nByte, aByte);
|
||||
if( rc!=SQLITE_OK ) rc = test_session_error(interp, rc, 0);
|
||||
free(aByte);
|
||||
break;
|
||||
};
|
||||
|
||||
@@ -1688,7 +1693,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
break;
|
||||
};
|
||||
|
||||
case 14: /* change_beginne */
|
||||
case 15: /* change_beginne */
|
||||
case 5: { /* change_begin */
|
||||
struct ChangeType {
|
||||
const char *zType;
|
||||
@@ -1815,13 +1820,16 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 12: /* change_finishne */
|
||||
case 11: { /* change_finish */
|
||||
int bDiscard = 0;
|
||||
if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &bDiscard) ){
|
||||
rc = TCL_ERROR;
|
||||
}else{
|
||||
char *zErr = 0;
|
||||
rc = sqlite3changegroup_change_finish(p->pGrp, bDiscard, &zErr);
|
||||
char **pz = &zErr;
|
||||
if( iSub==12 ) pz = 0;
|
||||
rc = sqlite3changegroup_change_finish(p->pGrp, bDiscard, pz);
|
||||
if( rc!=SQLITE_OK ){
|
||||
rc = test_session_error(interp, rc, zErr);
|
||||
}
|
||||
@@ -1829,7 +1837,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 12: { /* config */
|
||||
case 13: { /* config */
|
||||
struct OptionName {
|
||||
const char *zOpt;
|
||||
int op;
|
||||
@@ -1858,7 +1866,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 13: { /* change_text-1 */
|
||||
case 14: { /* change_text-1 */
|
||||
int bNew = 0;
|
||||
int iCol = 0;
|
||||
if( TCL_OK!=testGetNewOrOld(interp, objv[2], &bNew)
|
||||
|
||||
@@ -352,7 +352,7 @@ else
|
||||
SQLITE_C_IS_SEE = 0
|
||||
else
|
||||
SQLITE_C_IS_SEE = 1
|
||||
$(info This is an SEE build)
|
||||
$(info $(emo.lock)$(emo.lock)$(emo.lock) This is an SEE build $(emo.lock)$(emo.lock)$(emo.lock))
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -245,4 +245,5 @@ _fiddle_reset_db
|
||||
_fiddle_db_handle
|
||||
_fiddle_db_vfs
|
||||
_fiddle_export_db
|
||||
_fiddle_get_prompt
|
||||
//#/if fiddle
|
||||
|
||||
@@ -363,11 +363,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
called this way, the resolved value of the returned Promise is
|
||||
the number of bytes written to the target file.
|
||||
|
||||
It very specifically requires the input to be an SQLite3
|
||||
database and throws if that's not the case. It does so in
|
||||
order to prevent this function from taking on a larger scope
|
||||
than it is specifically intended to. i.e. we do not want it to
|
||||
become a convenience for importing arbitrary files into OPFS.
|
||||
It very specifically requires the input to be an SQLite3 database
|
||||
and throws if that's not the case. It does so in order to
|
||||
prevent this function from taking on a larger scope than it is
|
||||
specifically intended to. i.e. we do not want it to become a
|
||||
convenience for importing arbitrary files into OPFS. Caveat: as
|
||||
of 3.54 in SEE builds, the "is this a db?" check is necessarily
|
||||
lax to account for SEE-encrypted databases not having a legible
|
||||
header. In such builds, only the db size is relevant for the
|
||||
check.
|
||||
|
||||
This routine rewrites the database header bytes in the output
|
||||
file (not the input array) to force disabling of WAL mode.
|
||||
@@ -1099,20 +1103,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return promiseResolve_(sqlite3);
|
||||
};
|
||||
const options = opfsUtil.options;
|
||||
let proxyUri = options.proxyUri +(
|
||||
//#if not target:es6-bundler-friendly
|
||||
const proxyUri = options.proxyUri +(
|
||||
(options.proxyUri.indexOf('?')<0) ? '?' : '&'
|
||||
)+'vfs='+vfsName;
|
||||
//sqlite3.config.error("proxyUri",options.proxyUri, (new Error()));
|
||||
//#/if
|
||||
const W = opfsVfs.worker =
|
||||
//#if target:es6-bundler-friendly
|
||||
(()=>{
|
||||
/* _Sigh_... */
|
||||
switch(vfsName){
|
||||
case 'opfs':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs", import.meta.url));
|
||||
case 'opfs-wl':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs-wl", import.meta.url));
|
||||
}
|
||||
/* Discussion explaining this formulation:
|
||||
https://github.com/sqlite/sqlite-wasm/pull/159 */
|
||||
const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url);
|
||||
url.searchParams.set('vfs', vfsName);
|
||||
return new Worker(url.toString());
|
||||
})();
|
||||
//#elif target:es6-module
|
||||
new Worker(new URL(proxyUri, import.meta.url));
|
||||
|
||||
@@ -771,7 +771,11 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
lead bytes of that buffer do not hold a SQLite3 database header,
|
||||
else it returns without side effects.
|
||||
|
||||
Added in 3.44.
|
||||
Added in 3.44. As of 3.54 in SEE builds it performs only a
|
||||
rudimentary length check and does not fail for invalid header
|
||||
bytes, under the assumption that the input may be an encrypted
|
||||
db. We cannot unambiguously distinguish an encrypted db from
|
||||
garbage bytes.
|
||||
*/
|
||||
affirmDbHeader: function(bytes){
|
||||
if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes);
|
||||
@@ -781,7 +785,12 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
}
|
||||
for(let i = 0; i < header.length; ++i){
|
||||
if( header.charCodeAt(i) !== bytes[i] ){
|
||||
//#if enable-see
|
||||
break /* assume this might be an encrypted db.
|
||||
https://sqlite.org/see/forumpost/f84bef3552 */;
|
||||
//#else
|
||||
toss3("Input does not contain an SQLite3 database header.");
|
||||
//#/if
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -791,7 +800,8 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
database. It only examines the size and header, but further
|
||||
checks may be added in the future.
|
||||
|
||||
Added in 3.44.
|
||||
Added in 3.44. See notes in affirmDbHeader() regarding SEE
|
||||
builds.
|
||||
*/
|
||||
affirmIsDb: function(bytes){
|
||||
if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes);
|
||||
|
||||
@@ -1040,19 +1040,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
importDb(name, bytes){
|
||||
if( bytes instanceof ArrayBuffer ) bytes = new Uint8Array(bytes);
|
||||
else if( bytes instanceof Function ) return this.importDbChunked(name, bytes);
|
||||
util.affirmIsDb(bytes);
|
||||
const sah = this.#mapFilenameToSAH.get(name)
|
||||
|| this.nextAvailableSAH()
|
||||
|| toss("No available handles to import to.");
|
||||
const n = bytes.byteLength;
|
||||
if(n<512 || n%512!=0){
|
||||
toss("Byte array size is invalid for an SQLite db.");
|
||||
}
|
||||
const header = "SQLite format 3";
|
||||
for(let i = 0; i < header.length; ++i){
|
||||
if( header.charCodeAt(i) !== bytes[i] ){
|
||||
toss("Input does not contain an SQLite database header.");
|
||||
}
|
||||
}
|
||||
const nWrote = sah.write(bytes, {at: HEADER_OFFSET_DATA});
|
||||
if(nWrote != n){
|
||||
this.setAssociatedPath(sah, '', 0);
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
if(capi.sqlite3_vfs_find("opfs")){
|
||||
stdout("\nOPFS is available. To open a persistent db, use:\n\n",
|
||||
" .open file:name?vfs=opfs\n\nbut note that some",
|
||||
"features (e.g. upload) do not yet work with OPFS.");
|
||||
"features (e.g. upload) do not work with OPFS.");
|
||||
}
|
||||
stdout('\nEnter ".help" for usage hints.');
|
||||
return true;
|
||||
@@ -186,6 +186,7 @@
|
||||
if(!f._){
|
||||
if(!this.runMain()) return;
|
||||
f._ = sqlite3.wasm.xWrap('fiddle_exec', undefined, ['string']);
|
||||
f.getPrompt = sqlite3.wasm.xWrap('fiddle_get_prompt', 'string:dealloc', []);
|
||||
}
|
||||
if(fiddleModule.isDead){
|
||||
stderr("shell module has exit()ed. Cannot run SQL.");
|
||||
@@ -207,7 +208,8 @@
|
||||
wMsg('working','end');
|
||||
wMsg('wasm-info', {
|
||||
pointerSize: sqlite3.wasm.ptr.size,
|
||||
heapSize: sqlite3.wasm.heap8().byteLength
|
||||
heapSize: sqlite3.wasm.heap8().byteLength,
|
||||
prompt: f.getPrompt()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -349,9 +349,10 @@
|
||||
SF.e.wasmInfo.innerText = 'WASM: '+(
|
||||
4===v.pointerSize ? 32 : 64
|
||||
)+'-bit'
|
||||
//+' heap size: '+Number(v.heapSize)
|
||||
+' heap: '+Number(v.heapSize)
|
||||
// Heap size is not changing even when loading a huge db?
|
||||
;
|
||||
SF.jqTerm?.set_prompt?.(v.prompt);
|
||||
});
|
||||
|
||||
/* querySelectorAll() proxy */
|
||||
@@ -865,8 +866,14 @@
|
||||
const jqeTerm = window.jQuery(SF.e.terminal).empty();
|
||||
SF.jqTerm = jqeTerm.terminal(SF.dbExec.bind(SF),{
|
||||
prompt: 'sqlite> ',
|
||||
greetings: false /* note that the docs incorrectly call this 'greeting' */
|
||||
greetings: false /* the docs incorrectly call this 'greeting' */
|
||||
});
|
||||
/* Disable all special handling of the input:
|
||||
https://sqlite.org/forum/forumpost/c6665017c0dbba1f
|
||||
https://github.com/jcubic/jquery.terminal/issues/1044 */
|
||||
const no_formatting = (str)=>window.jQuery.terminal.escape_formatting(str);
|
||||
no_formatting.__meta__ = true;
|
||||
window.jQuery.terminal.new_formatter(no_formatting);
|
||||
EAll('.unhide-if-terminal-available').forEach(e=>{
|
||||
e.classList.remove('hidden');
|
||||
});
|
||||
@@ -890,5 +897,6 @@
|
||||
SF.dbExec(urlParams.get('sql') || null);
|
||||
delete SF.ForceResizeKludge.$disabled;
|
||||
SF.ForceResizeKludge();
|
||||
globalThis.fiddle = SF;
|
||||
}/*onSFLoaded()*/;
|
||||
})();
|
||||
|
||||
@@ -322,8 +322,9 @@
|
||||
<h1>Usage Summary</h1>
|
||||
|
||||
<ul>
|
||||
<li class='hidden unhide-if-terminal-available'>In "terminal
|
||||
mode" it accepts input just like the CLI shell does.</li>
|
||||
<li class='hidden unhide-if-terminal-available'>In
|
||||
<a href="https://github.com/jcubic/jquery.terminal">"terminal
|
||||
mode"</a> it accepts input just like the CLI shell does.</li>
|
||||
<li>In split-view mode:
|
||||
<ul>
|
||||
<li>Input can be executed with either the Run
|
||||
|
||||
@@ -1021,11 +1021,15 @@ static void mk_fiddle(void){
|
||||
pf("\t@$(call b.call.wasm-strip,%s)\n", zBuildName);
|
||||
pf("\t@$(call b.strip-js-emcc-bindings,$(logtag.%s))\n",
|
||||
zBuildName);
|
||||
pf("\t@$(call b.cp,%s,$(dir.dout)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n", zBuildName);
|
||||
if( isDebug ){
|
||||
pf("\t@$(call b.cp,%s,"
|
||||
"$(dir.fiddle)/index.html "
|
||||
"$(dir.fiddle)/fiddle.js "
|
||||
"$(dir.fiddle)/fiddle-worker.js,"
|
||||
"$(dir.fiddle)/fiddle-worker.js "
|
||||
"$(dir.fiddle)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n",
|
||||
zBuildName);
|
||||
|
||||
+68
-22
@@ -380,16 +380,19 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
function which must return a constructor args object for ctor. It
|
||||
is passed true if the db needs to be cleaned up/unlinked before
|
||||
opening it (OPFS) and false if not (how that is done is
|
||||
VFS-dependent). dbUnlink is a function which is expected to
|
||||
unlink() the db file if the ctorOpfFunc does not do so when
|
||||
passed true (kvvfs).
|
||||
VFS-dependent). dbUnlink is a _synchronous_ function which is
|
||||
expected to unlink() the db file if the ctorOpfFunc does not do
|
||||
so when passed true (namely for kvvfs).
|
||||
|
||||
This function initializes the db described by ctorOptFunc(...),
|
||||
writes some secret info into it, and re-opens it twice to
|
||||
confirmi that it can be read with an SEE key and cannot be read
|
||||
without one.
|
||||
This function initializes the db described by the result of
|
||||
ctorOptFunc(bool), writes some secret info into it, and re-opens
|
||||
it twice to confirm that it can be read with an SEE key and
|
||||
cannot be read without one.
|
||||
|
||||
If unlinkDbAtEnd is truthy then dbUnlink() is (on success)
|
||||
called before returning.
|
||||
*/
|
||||
T.seeBaseCheck = function(ctor, ctorOptFunc, dbUnlink){
|
||||
T.seeBaseCheck = function(ctor, ctorOptFunc, dbUnlink, unlinkDbAtEnd=true){
|
||||
let initDb = true;
|
||||
const tryKey = function(keyKey, key, expectCount){
|
||||
let db;
|
||||
@@ -450,7 +453,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
tryKey('hexkey', hexFoo, 3);
|
||||
T.assert( !initDb );
|
||||
tryKey('hexkey', hexFoo, 6);
|
||||
dbUnlink();
|
||||
if( unlinkDbAtEnd ) dbUnlink();
|
||||
};
|
||||
//#/if enable-see
|
||||
|
||||
@@ -3596,7 +3599,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
name: 'kvvfs SEE encryption in sessionStorage',
|
||||
predicate: ()=>(!!globalThis.sessionStorage
|
||||
|| "sessionStorage is not available"),
|
||||
test: function(sqlite3){
|
||||
test: async function(sqlite3){
|
||||
const JDb = sqlite3.oo1.JsStorageDb;
|
||||
T.seeBaseCheck(JDb,
|
||||
(isInit)=>{
|
||||
@@ -3923,16 +3926,39 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
.t({
|
||||
name: '@vfsName@ with SEE encryption',
|
||||
predicate: (sqlite3)=>!!sqlite3.oo1.@oo1Ctor@,
|
||||
test: function(sqlite3){
|
||||
T.seeBaseCheck(
|
||||
sqlite3.oo1.@oo1Ctor@,
|
||||
function(isInit){
|
||||
const opt = {filename: 'file:///sqlite3-see.edb'};
|
||||
if( isInit ) opt.filename += '?delete-before-open=1';
|
||||
return opt;
|
||||
},
|
||||
()=>{}
|
||||
);
|
||||
test: async function(sqlite3){
|
||||
const ctor = sqlite3.oo1.@oo1Ctor@;
|
||||
const filename = 'sqlite3-see.edb';
|
||||
const ctorOpt = {filename: 'file:///'+filename};
|
||||
const opfs = sqlite3.opfs;
|
||||
const initer = function(isInit){
|
||||
const opt = {...ctorOpt};
|
||||
if( isInit ) opt.filename += '?delete-before-open=1';
|
||||
return opt;
|
||||
};
|
||||
|
||||
T.seeBaseCheck(ctor, initer, ()=>{}, false);
|
||||
/*
|
||||
Ensure that ctor.importDb() correctly handles SEE-encrypted
|
||||
dbs. For more details search below for forumpost/f84bef3552.
|
||||
*/
|
||||
let exp = await opfs.getRootDir()
|
||||
.then(d=>d.getFileHandle(filename))
|
||||
.then(fh=>fh.getFile())
|
||||
.then(f=>f.bytes());
|
||||
await opfs.unlink(filename);
|
||||
T.assert( exp.byteLength > 100 && 0===(exp.byteLength % 512) );
|
||||
const got = await ctor.importDb(filename, exp);
|
||||
T.assert(exp.byteLength === got);
|
||||
exp = null;
|
||||
const db = new ctor({...initer(false), key: 'foo'});
|
||||
try{
|
||||
T.assert( 4 === db.selectValue("select count(*) from t") )
|
||||
.assert( 6 === db.selectValue("select sum(a) from t") );
|
||||
}finally{
|
||||
db.close();
|
||||
await opfs.unlink(filename);
|
||||
}
|
||||
}
|
||||
})
|
||||
//#/if enable-see
|
||||
@@ -3940,7 +3966,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
//#/query
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('OPFS SyncAccessHandle Pool VFS',
|
||||
(sqlite3)=>(!!sqlite3.installOpfsSAHPoolVfs || "requires OPFS SAH Pool APIs"))
|
||||
(sqlite3)=>((isWorker() && !!sqlite3.installOpfsSAHPoolVfs) || "requires OPFS SAH Pool APIs"))
|
||||
.t({
|
||||
name: 'SAH sanity checks',
|
||||
test: async function(sqlite3){
|
||||
@@ -4136,12 +4162,32 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
}
|
||||
let poolUtil;
|
||||
const P1 = await inst(poolConfig).then(u=>poolUtil = u).catch(catcher);
|
||||
if( !poolUtil ) return;
|
||||
const dbFile = '/sqlite3-see.edb';
|
||||
T.seeBaseCheck(
|
||||
poolUtil.OpfsSAHPoolDb,
|
||||
(isInit)=>{return {filename: dbFile}},
|
||||
()=>poolUtil.unlink(dbFile)
|
||||
()=>poolUtil.unlink(dbFile),
|
||||
false
|
||||
);
|
||||
/* Ensure that importDb() does the right thing for an
|
||||
SEE-encrypted DB: https://sqlite.org/see/forumpost/f84bef3552 */
|
||||
let exp = poolUtil.exportFile(dbFile);
|
||||
T.assert( exp.byteLength > 100 && 0===(exp.byteLength % 512) );
|
||||
poolUtil.unlink(dbFile);
|
||||
const got = poolUtil.importDb(dbFile, exp);
|
||||
T.assert(exp.byteLength === got);
|
||||
exp = null;
|
||||
const db = new poolUtil.OpfsSAHPoolDb({
|
||||
filename: dbFile,
|
||||
key: 'foo'
|
||||
});
|
||||
try{
|
||||
T.assert( 4 === db.selectValue("select count(*) from t") )
|
||||
.assert( 6 === db.selectValue("select sum(a) from t") );
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
poolUtil.removeVfs();
|
||||
}
|
||||
})/*opfs-sahpool with SEE*/
|
||||
|
||||
@@ -982,6 +982,7 @@ FUZZCHECK_SRC = sqlite3.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/test/vt02.c \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
@@ -1678,7 +1679,8 @@ tclsqlite3.c: sqlite3.c tclsqlite-ex.c
|
||||
#
|
||||
# $(CFLAGS.tclextension) = CFLAGS for the tclextension* targets.
|
||||
#
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS)
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) \
|
||||
$(OPT_FEATURE_FLAGS) $(OPTS) $(CFLAGS.icu)
|
||||
#
|
||||
# Build the SQLite TCL extension in a way that make it compatible
|
||||
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
|
||||
@@ -1686,7 +1688,8 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
|
||||
#
|
||||
tclextension: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
|
||||
@@ -1694,7 +1697,8 @@ tclextension: tclsqlite3.c
|
||||
#
|
||||
tclextension-install: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
|
||||
@@ -2341,6 +2345,7 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
$(TOP)/ext/intck/sqlite3intck.h \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
@@ -2422,6 +2427,10 @@ sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(DEPS_EXT_COMMON)
|
||||
stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON)
|
||||
$(T.cc.extension) -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
$(AUXTEST): $(TOP)/test/c/$(AUXTEST).c
|
||||
$(T.cc.sqlite) -o $@ $(TOP)/test/c/$(AUXTEST).c sqlite3.o $(LDFLAGS.libsqlite3)
|
||||
|
||||
|
||||
#
|
||||
# Windows section
|
||||
#
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
C Add\sthe\s\B\sescape\sfor\sCLI\sprompts.\s\sChange\sthe\sdefault\sprompts\sto\nuse\s\f,\s\H,\sand\s\B.
|
||||
D 2026-04-10T20:06:34.810
|
||||
C Add\sthe\sSQLITE_CHANGESETAPPLY_NOUPDATELOOP\soption\sto\sthe\ssqlite3_changeset_apply_v2/3()\smethod.\sTo\sdisable\sthe\sextra\sprocessing\sto\scommit\schangesets\sthat\sswap\stwo\sor\smore\svalues\ssubject\sto\sa\sUNIQUE\sconstraint\sbetween\srows.
|
||||
D 2026-05-22T14:22:14.502
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
|
||||
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 06b757f8648f1d9dd9683dbd72350cf0cf20d6fe09168cac455569b81dd97ddc
|
||||
F README.md f49fbd826941842e348242f3ab62f240c985ceafdf8fbe576abf4eb75317468c
|
||||
F Makefile.msc 6f4294982758b5eeeac740c1a263186c3fcb9ba51d1b48261e321bcb37a41dbb
|
||||
F README.md f00091ffb5c6379b783afb57ca5f443a5742e119082f37c407f64a5e16c56346
|
||||
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
@@ -44,10 +44,10 @@ F autosetup/cc-lib.tcl 493c5935b5dd3bf9bd4eca89b07c8b1b1a9356d61783035144e21795f
|
||||
F autosetup/cc-shared.tcl 163eda58c14cd662fd8a504bd2ad8a716ef4db7015dc1de0095d5de8dd601a4b
|
||||
F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f
|
||||
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
|
||||
F autosetup/jimsh0.c 916bbdf8023fbda9937afae57d81a853d8c2ea00f2320aa27becbc33574f963d
|
||||
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
|
||||
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
|
||||
F autosetup/proj.tcl 67683f214977a416baafc4c1020f9940ff047a7306b2292c5872d6287460b7d5
|
||||
F autosetup/sqlite-config.tcl 2205b8bcc193a5d46584ebc1cf44c7a93a977d155e20dc38b18dcce720e58074
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
|
||||
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
|
||||
@@ -63,7 +63,7 @@ F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
|
||||
F doc/lemon.html 2085fda0a90a94fe92159a79dccc5c30d5a2313524887a31659cd66162f17233
|
||||
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
|
||||
F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
|
||||
F doc/testrunner.md daffa0ebbbe397a73537ae1b19b3124d489ce5f89dfe570781d1f1ef1809597c
|
||||
F doc/testrunner.md 3589f7914d36adaff6d108566e09b2c6166887bea00580e5343f8b43615ffe12
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
|
||||
F doc/vfs-shm.txt 1a55f3f0e7b6745931b117ba5c9df3640d7a0536f532ef0052563100f4416f86
|
||||
@@ -82,13 +82,13 @@ F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 6cc7bbc307f27e7b6ee2e1d5ff63ffff4df3b42529dfe00eb34ddded417961b3
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 277f32f304e82f4397fc2a74793c0a95318b7abb9670b519e4805a00946cbd9b
|
||||
F ext/fts3/fts3_aux.c 37ba1b10bbd163ddc6b05dbc3a306a0d5d68aee3d30f33b4dc5794955cc50887
|
||||
F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
|
||||
F ext/fts3/fts3_aux.c c105f6502df588f49a383eb22aed953844fb0e31265361a0cc8dd73037b37e39
|
||||
F ext/fts3/fts3_expr.c 907dd64deb881c0586d5ecbabc96cfebdbe2ff9e7a052d379fd3b606edfa21ea
|
||||
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
|
||||
F ext/fts3/fts3_porter.c 024417020c57dd1ab39816f5fe6cf45222a857b78a1f6412f040ada1ceabd4ff
|
||||
F ext/fts3/fts3_snippet.c abe3b2998e7cb6d1ab6019f87f021758a0df3ee4010fe144a174a524cff96fe6
|
||||
F ext/fts3/fts3_snippet.c 65e178107b59ad4724a11339a645f2e3789f3cf59b2f4e29c90efd864e53c5b4
|
||||
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
|
||||
F ext/fts3/fts3_test.c cc329471e573f95a6ea9fbca87e89dcfa1d355591c80172ffcd759ac521d25d8
|
||||
F ext/fts3/fts3_tokenize_vtab.c 66eba6c2baa04b2b15e80d68341b8fd0b4d3831f6b2edb33916a2906ff2d4389
|
||||
@@ -113,13 +113,13 @@ F ext/fts5/fts5_buffer.c dcc3f0352339fe79c9d8abbc1c2009bc3469206467880bf43558447
|
||||
F ext/fts5/fts5_config.c bfba970fe1e4eed18ee57c8d51458e226db9a960ddf775c5e50e3d76603a667e
|
||||
F ext/fts5/fts5_expr.c 71d48e8cf0358deace4949276647d317ff7665db6db09f40b81e2e7fe6664c7c
|
||||
F ext/fts5/fts5_hash.c d5871df92ce3fa210a650cf419ee916b87c29977e86084d06612edf772bff6f5
|
||||
F ext/fts5/fts5_index.c f8cfa37bb7397e5ede20242e4c9cb030bc8b4584ce3f23a5e2495038c0ae64bd
|
||||
F ext/fts5/fts5_index.c 4ac3d9e9f83280d9b7bf29c0948c3a1ed17533ecaab3fbf0ad95218c3409b42e
|
||||
F ext/fts5/fts5_main.c b0fed47b3b4420ba6810373480a75bc28a9c0b7d16478d19a396436fb3ff17d7
|
||||
F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
|
||||
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
|
||||
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
|
||||
F ext/fts5/fts5_tokenize.c 0469b30e7bf25255fbb7c101e2b549a521fb501342e7269cf73cbb6b2dbd8da2
|
||||
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
|
||||
@@ -162,13 +162,14 @@ F ext/fts5/test/fts5contentless4.test ec34dc69ef474ca9997dae6d91e072906e0e9a5a4b
|
||||
F ext/fts5/test/fts5contentless5.test 38cd0392c730dc7090c550321ce3c24ba4c392bc97308b51a4180e9959dca7b5
|
||||
F ext/fts5/test/fts5corrupt.test 237fce1c3261bb3a5bec333b0f0dbf5b105ec32627ef14cccbda3cfe13833193
|
||||
F ext/fts5/test/fts5corrupt2.test 4a03a158c2cb617c9f76d26b35c1ef2534124bc0bbddcea38dfd5b170ebea27b
|
||||
F ext/fts5/test/fts5corrupt3.test e489b51b6c4ded2a808e0f78bdbe126f6d369de41a59ac2717878e37fc3db0e8
|
||||
F ext/fts5/test/fts5corrupt3.test 121a8a7622dfe1be1bc55cbe70eddd6a3416f76a837dc8c06a11a32e781595a4
|
||||
F ext/fts5/test/fts5corrupt4.test dc08d19f5b8943e95a7778a7d8da592042504faf18dd93f68f7d7a0d7d7dd733
|
||||
F ext/fts5/test/fts5corrupt5.test 73985d4fe6d8f0d5d5c7bcf79ae7c6522c376cd6ad710a0ff2f26e0c2e222abe
|
||||
F ext/fts5/test/fts5corrupt5.test 329fb0e21b1dfb9752e1769ca078f27a8e99cfcc017055c8a6d724011b73c9c6
|
||||
F ext/fts5/test/fts5corrupt6.test 2d72db743db7b5d9c9a6d0cfef24d799ed1aa5e8192b66c40e871a37ed9eed06
|
||||
F ext/fts5/test/fts5corrupt7.test 814aab492d7a09abb5bfdd81cc66fc206d7f3868f9a3bae91876e02efc466fb3
|
||||
F ext/fts5/test/fts5corrupt8.test 0b10750caf8aa23fa1c379ca4caf6130d41454505e4d5315590f4061eedcbe44
|
||||
F ext/fts5/test/fts5corrupt9.test 4253b9b59f33effac8b67da72ec34309c738aca2d5e8e2656bfbbd6a489a1dfe
|
||||
F ext/fts5/test/fts5corruptA.test 7b31551444569420903d34ae50a55a1227d16969264f0b50de2dc812bc0b3414
|
||||
F ext/fts5/test/fts5corruptbig.test 9f95b40fa36e292feceab02b2ef06e21878bfa1ac7afefa138aae05518b51774
|
||||
F ext/fts5/test/fts5delete.test 2a5008f8b1174ef41d1974e606928c20e4f9da77d9f8347aed818994d89cced4
|
||||
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
|
||||
@@ -227,7 +228,7 @@ F ext/fts5/test/fts5origintext6.test 09eb1347cb0dceaebbebf3d3e6bd5d24c7c1006efdd
|
||||
F ext/fts5/test/fts5phrase.test bb2554bb61d15f859678c96dc89a7de415cd5fc3b7b54c29b82a0d0ad138091c
|
||||
F ext/fts5/test/fts5plan.test f8b0d752a818059a934cdc96c0f77de058a67a0a57bb3a8181d28307ab5b1626
|
||||
F ext/fts5/test/fts5porter.test 15b514fac8690b58e99c330efe5bf5615bc43f2fae4a3cca3f923dbaff55a0c0
|
||||
F ext/fts5/test/fts5porter2.test 94f0e4351e2c99b4e74f1fae05a4ddf1cb5b926620a8c14554160d075ddc7a59
|
||||
F ext/fts5/test/fts5porter2.test 1dab0fe41342ebed32ca36a145de3e50be9093cb71e9f5250f6ebc589207982a
|
||||
F ext/fts5/test/fts5prefix.test c0b7842f1a2d830c0b146cd438a95ea4c5a25635719ed0d973ffe41907338b83
|
||||
F ext/fts5/test/fts5prefix2.test a5bb43b8a2687efafa7ac4e5ccff6812015cf8cf18e3086bb0eb3126f30fbbf6
|
||||
F ext/fts5/test/fts5query.test 0320a7a4b58a6e3e50ec8910b301649da90ace675001f9e0bf6392750ad4591d
|
||||
@@ -253,7 +254,7 @@ F ext/fts5/test/fts5synonym2.test 58f357b997cf2fedeeb9d0de4db9f880fa96fa2fe27a74
|
||||
F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokendata.test 7cad79af82e8e81b7a36b450087233d2fca051bb0d584421afc375d6dd26d6f6
|
||||
F ext/fts5/test/fts5tokenizer.test 7937cec672b148223fff8746d21d3e7ed0965fd7caf35ccdc888a005bb452f98
|
||||
F ext/fts5/test/fts5tokenizer.test 738e9c3e1b338028e202d0fcd33aa39f1bd3f8444d14f9a408e8a617b1361d3f
|
||||
F ext/fts5/test/fts5tokenizer2.test ddb8b10fbe4b84b2a75812671f127774c1d2e3e2bf82d2e0e4f0bb1cd8a2b2d6
|
||||
F ext/fts5/test/fts5tokenizer3.test eea778f7bb7024c3e904e28915f9d53286141671b138722148be22a9c758bdc3
|
||||
F ext/fts5/test/fts5trigram.test a55fde7065ae69a0f82c5a7a5bf5286a97de11ae4bff6537fd3e27ca9a01416f
|
||||
@@ -278,7 +279,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
F ext/fts5/tool/mkfts5c.tcl 135b9e160f8e10211c10c5873d5e8c3eaebd3da9ec56a12ae4db157d4738ffe4
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt 1f8d76e10d2385fc77914a14ccd99acfbaf68111dfcf26a360ad9063787f57fb
|
||||
F ext/icu/icu.c 9837f4611915baad1edbe38222f3ee7d1b5e118ab16fec9ba603720f72c78b2a
|
||||
F ext/icu/icu.c 535d0d61f109e760a56e1afc450414ebfb0e2d594e2233b30315b815e3433ac2
|
||||
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
|
||||
F ext/intck/intck1.test 53d885075abeb45aeb1eeffeaa8560b329060835ade4af5c44cf5fcb581c1e63
|
||||
F ext/intck/intck2.test a29343a8e65c5c3400e10747f394924f3df95a5b2de94f46e9b5c9b97f5e7339
|
||||
@@ -357,7 +358,8 @@ F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43
|
||||
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
||||
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
|
||||
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
|
||||
F ext/misc/amatch.c 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
|
||||
F ext/misc/amatch.c 972a250631d481f38736b46740bf7f5c9646a0f2bb53800543299a746ff1bac6
|
||||
F ext/misc/analyze.c 77e0f45a44c13d66f30922db553072305521c0fb3a448b920e641fccd2498527
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
|
||||
@@ -371,11 +373,11 @@ F ext/misc/completion.c 3f5db28e88c3313103b2dd86d910a2944fd500c46754e473493968ce
|
||||
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
|
||||
F ext/misc/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
|
||||
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
|
||||
F ext/misc/decimal.c 23698283d9365ce66d54b5bb97c01e69b4aa7ac804f226f9117a0d42efd15a65
|
||||
F ext/misc/decimal.c 432e5b03a0e2a68a1846a9852a565a1b546ca9b295deda834e4653f0f5577daa
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 9670c8ff7b255eea7845abc5123a4958e74016c16990b10497e56380f91704b9
|
||||
F ext/misc/fileio.c e72033f987894ed821bf324a426ed462743399c274f1290dcb646349b6d7548f
|
||||
F ext/misc/fossildelta.c 40add35db7f355d29ae856fe09043e66802fceff6f2551baccb28d794cadbc77
|
||||
F ext/misc/fileio.c 936c0a7b3382a047d833ad33f62ba59a3847b79ea745bf529797cd344966fbb0
|
||||
F ext/misc/fossildelta.c 6aa3f15279cd2d796583e3ff654be7d2df745fdbea7987c1640e78ce1fac899e
|
||||
F ext/misc/fuzzer.c decaca5a3479dfba69576cd41d4e17161eaf154a5438e12d316bbc5853571802
|
||||
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
|
||||
F ext/misc/memstat.c 03ab52d2d841eb3f55118105c1964d5225f152b23bd708844c648b48d14ccbcf
|
||||
@@ -386,18 +388,18 @@ F ext/misc/noop.c f1a21cc9b7a4e667e5c8458d80ba680b8bd4315a003f256006046879f679c5
|
||||
F ext/misc/normalize.c fbb144a861809686ff2b5b6eee8bb2e1207f9bf13ce7376e5273c700a1eafbd5
|
||||
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
|
||||
F ext/misc/percentile.c 72e05a21db20a2fa85264b99515941f00ae698824c9db82d7edfbb16cea8ec80
|
||||
F ext/misc/prefixes.c aa15fd268e7d1336d1a1d4bc79265860d1d2ad68bba4cbcab61f83e4989dc68c
|
||||
F ext/misc/prefixes.c efc261429fd8ab43cedc0d38b94d86d87437af5550651bceb618bd7e84e25125
|
||||
F ext/misc/qpvtab.c 470a5fffba005c8e1994209e59c1848122351e19522de71beb68d666c4fa39a5
|
||||
F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e6262c4ed
|
||||
F ext/misc/regexp.c 9dada9e9aa91f0cc23e35429e5d1111f110cc201b4c8dcc49aa6d2fc4b2a865d
|
||||
F ext/misc/regexp.c 378e6e84516952a4b9f3f4df88927f20e6538e2609f55b773ed78899dab8206e
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
|
||||
F ext/misc/series.c 9454c7ef27d3729432496f31caabc892aeee1c21377d403f681126d93c09d6e9
|
||||
F ext/misc/sha1.c 8bf60344c11a525384c2efd1ae77f160b06be336db679effaadf292d4b41451c
|
||||
F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
|
||||
F ext/misc/sha1.c 9a11826db885e8afd997c0a1b28bb799a43e462ef770ac33f19e744887c9c6fa
|
||||
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 693c8fd3293087fa821322967a97e59dfa24051e5d2ca7fa85790a4034db6fa4
|
||||
F ext/misc/spellfix.c 36b0f4893ff583b6dcc727beca44cc262e7855713aea57a0154766936352cf81
|
||||
F ext/misc/sqlar.c 97c100b010159c08a7a9acd8eb1ea510a5522e64741aaafcd7b6c629de682edc
|
||||
F ext/misc/sqlite3_stdio.c b43a0f530c6f0fb3d41d9af8c0b40f3f71198a1db55ab8ffffbef5c8cc329d22
|
||||
F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bfa08ab1ce99f
|
||||
@@ -421,8 +423,8 @@ F ext/misc/zipfile.c 5a583b5e72b4d777dc9f845529e6bd185d58024b633aafc93588679c787
|
||||
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
|
||||
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
|
||||
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
|
||||
F ext/qrf/qrf.c 64203184d9fc6ee75439fb6da70fd51dc7aaf3243600e52aa87d18ea1e4d6e73
|
||||
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
|
||||
F ext/qrf/qrf.c 02fce2add53dda452ca7b74a3e8f5de3c2b75919fd1a29f7393c1e4cf1272370
|
||||
F ext/qrf/qrf.h 7a832022bc3f40dc09fff1cb6f18025395a19313de090265a4a1d22bb9b400be
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363
|
||||
@@ -463,11 +465,11 @@ F ext/rbu/rburesume.test 1403752d152b55efb7fc25749c0fccc790061371ec9ffe428cc04f8
|
||||
F ext/rbu/rbusave.test 588b618dad9d65c4b13d03a79931de82213503fedc26bdf5789c996ecf427fba
|
||||
F ext/rbu/rbusplit.test a6dedd23cf37bcf2e8646d9d7139846e96d60d92f9bc6d6ba6ca8c24c0bd1f72
|
||||
F ext/rbu/rbutemplimit.test 4980df2d4b74f4dd982add8f78809106154ef5a3c4bdce747422ab0b0481e029
|
||||
F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f323783b15311e
|
||||
F ext/rbu/rbuvacuum.test e3585cfda220038e8186c583e9bd2aaa9eccd0a5c2e40ed861de3c987c93f68c
|
||||
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c e99400d29d029936075e27495b269a2dcdceae3cf8c86b1d0869b4af487be3ab
|
||||
F ext/rbu/sqlite3rbu.c 28246b647831409e84dfb8286fbeda55f1de89e934571509a23a67ada572d0c0
|
||||
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
|
||||
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
|
||||
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
|
||||
@@ -486,12 +488,12 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
|
||||
F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f8cc843b2e20217e
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
|
||||
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
|
||||
F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
|
||||
F ext/rtree/rtree.c 44abdd5df278ca1901daf29c82cce6785f0ee82ce59e28160ee988c17a9a185b
|
||||
F ext/rtree/rtree.c acc098e82686fa278c20973d601b4c2489389f5d580d42efe0f799d2cf8cdf38
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
@@ -537,14 +539,14 @@ F ext/session/session4.test ad0ddaaddb9a99dac433d83fc6674aae2af072b8f57e63a6b3f2
|
||||
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
|
||||
F ext/session/session6.test 35279f2ec45448cd2e24a61688219dc6cf7871757716063acf4a8b5455e1e926
|
||||
F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605e6607ee29904
|
||||
F ext/session/session9.test 0c4a8fbe7a5031f50855f020f3408e1f07fd7859f1daa1629eadcec3422072d6
|
||||
F ext/session/session9.test ce2b898aa4caf0e492b57c29cb707224e0a33479e4f019785a81828273143ba5
|
||||
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
|
||||
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
|
||||
F ext/session/sessionC.test 2bd42225efdf5f5b1a20f75b672665bcd4f67e2a6d7ddf7420fe7bf523ba41f8
|
||||
F ext/session/sessionC.test 7c9b5e90194b3b7ad8bcbc6fcbac77d2c572ec3566a30fce1e82f4d64fb9aa3f
|
||||
F ext/session/sessionD.test 470ff917dc849e2eb78142ade63aaabd729d773833cff0ff01bca0eda68a21ce
|
||||
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
|
||||
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
|
||||
F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a
|
||||
F ext/session/sessionG.test 64c2b69531aebdb36d5977a5f832d77e4c8bda0c746a6c630adf23660bb1c7c2
|
||||
F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
|
||||
F ext/session/sessionI.test 11e7b6729fc942982a5104a40132f70a2e964d64d60dc5809b8206465af74822
|
||||
F ext/session/session_common.tcl a31f537a929a695a852d241c9434f2847cadf329856401921139fbb03a5a7697
|
||||
@@ -555,15 +557,16 @@ F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b8541
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194d64a39d8faff00a
|
||||
F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
|
||||
F ext/session/sessionchange2.test 6b5b7e3d1cc4ede43817f7fb68e3771aac4aa6500adb21a458b3e5a9fd841f83
|
||||
F ext/session/sessionchange2.test 8f59185216882adc8b34bb5ba63887459acf3df58493bcffa12e4d05ab6a6b85
|
||||
F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
|
||||
F ext/session/sessionconflict2.test d7f4caf59360dbca8a4698b9a3a322adf6f547f810ad41d131cacb730e02dd5e x
|
||||
F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
|
||||
F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
|
||||
F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
|
||||
F ext/session/sessionfault3.test 9397819ec25b0960c5bc03c78613f9cb5cacc970f83e817aec1775c2a839a787
|
||||
F ext/session/sessionfault3.test aea5331fa6dbe5ca4e19826605e624c0e1767545411479f27c5ef82b41046925
|
||||
F ext/session/sessioninvert.test 9018f6a7387ac745084b6374c5e1aa14d648b372e6e1181cfab3df632b662d26 x
|
||||
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
|
||||
F ext/session/sessionnoact.test 4c7ae5c7d351cb5323bca62b6b095592ad24bd90a6713c178b62ab0063d23e19
|
||||
F ext/session/sessionnoact.test 2cf060c12a7a23e663f0ec796561e58638c5c10a846653d37be886414b06ddc9
|
||||
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
|
||||
F ext/session/sessionnoop2.test 2d8146321785bdc7cee8966d984560184cfca83fd46da2ff81ea883d6e977b36
|
||||
F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
|
||||
@@ -571,10 +574,10 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c d5c91d5b07d2b8e860f2782ae23f7b44ce929280e00645418ee84a0fd14525b2
|
||||
F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
|
||||
F ext/session/test_session.c 2a02a68b522e2f3d4a64b2a4733af54b0f3e500769aeccd5bcbdd440103db069
|
||||
F ext/wasm/GNUmakefile 68c750f173106d9d63f12c1edf1256c6f4bad9894b155da5db64322f4912de4b
|
||||
F ext/session/sqlite3session.c 9d1cce13a48d821a31b36d99123ab25da87c3ae8b3bb96a926dfcc233a35ba9c
|
||||
F ext/session/sqlite3session.h ca7c4422c1514a95056cc8d333217df6b1829d39058126b1de85d10cd62d7a9c
|
||||
F ext/session/test_session.c 05c1f90c04de5474158bf8f7712a6f7a1d47477ce0402bbe0e55fc4a9ef1f49b
|
||||
F ext/wasm/GNUmakefile 65feef4ec48e62249f90278c4c08a3fe3c69e2461ff560b61c03cd73606e0949
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md 2e87804e12c98f1d194b7a06162a88441d33bb443efcfe00dc6565a780d2f259
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
@@ -582,24 +585,24 @@ F ext/wasm/SQLTester/SQLTester.mjs 6b3c52ed36a5573ca4883176f326332a8d4c0cecf5efd
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0
|
||||
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp de2ce128aebeff9ef4161cff7a0ff0089be866121bcb8941ad44a38a65f1d436
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp 189935d0106bca86661efc991ab13e1d5d6e1f55ec34dc7b5055a99321397edd
|
||||
F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b47244781a7e81
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
F ext/wasm/api/opfs-common-inline.c-pp.js 496ca858af09b7fef2efaece467960611d35f57254078424bcdeac42ded9e85d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js d0bff21d34fa05a7eb975c4ee608165f96387332101cb05e976953c77434374d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js d0a62a1d367d850d8e07c06e82499a5006f347e4025dbd59a8623048d858e7a1
|
||||
F ext/wasm/api/post-js-footer.js a50c1a2c4d008aede7b2aa1f18891a7ee71437c2f415b8aeb3db237ddce2935b
|
||||
F ext/wasm/api/post-js-header.js f35d2dcf1ab7f22a93d565f8e0b622a2934fc4e743edf3b708e4dd8140eeff55
|
||||
F ext/wasm/api/pre-js.c-pp.js d6bf82f83f60caa2904bddb95a29cb738b310f672d2796cdc5fe54463ab0d6cd
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 31a721ada7225838a61310a9f3f797fa5275353f8e9b0ae769d85b437be061f5
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 35e4727010f15fd72ead0dd1eb4e3c2c9bb1cc60e51544cbdff1f7c14f209de2
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 29ca376ff5d5f189714cf10b2b93b136e91b06ec8616579b53b2af9dfb4796bf
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 0084e15d66fbcd75cacbaa58e3b473d5e57082c30f3122be7fdadff5589cf6b6
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1fa34e9b0e3b90a8898e4f700d7125e44c81877f182627bb8564b97989bc6e78
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.c-pp.js 25e31482b04293a33d7599f1459eb552b3eb36ca10c02c816122d3308bf80cb2
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-kvvfs.c-pp.js 27fb135ba3b805b66c90a7333b56080345bf1db79335c3e48b6d01ad7aa09607
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 1c742ed92c0515c8ef97d2b132feb01168252bfd847fed5d52607d8a42d23c6a
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 4325cb9a5ebfbff7cd3060e309b167116a2a1bcb9f8d69dd8e6d023dbdd783bb
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-wl.c-pp.js 3dbd918ef037cd8fa9c7b4dccb3c8637b228638654c429e7df6acab5981c75e2
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 3da8fe72dc9e76614a9c102b92e777ce03f81d788b607701c828d8fcbac44b06
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js 366596d8ff73d4cefb938bbe95bc839d503c3fab6c8335ce4bf52f0d8a7dee81
|
||||
@@ -621,16 +624,16 @@ F ext/wasm/demo-worker1-promiser.c-pp.js d210aa1e8a74ea6244fe2290de5710bb55b3a9e
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js fdfa90aa9d6b402bfed802cf1595fe4da6cc834ac38c8ff854bf1ee01f5ff9bb
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle/fiddle-worker.js 6c72acac2d381480bc9f5eb538e3f2faf2c1f72dd4fcbd05d3b409818a9a8fd5
|
||||
F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc63649b31a4893
|
||||
F ext/wasm/fiddle/index.c-pp.html 02f063ef30b8124f311029855c4439e77bc6505d1bf65a163d88c064a63ee9d9
|
||||
F ext/wasm/fiddle/fiddle-worker.js e45bfe9ce4cf0d0270ca0ed254af8deecc7d46c399db4a56fd1d0846d5e258ec
|
||||
F ext/wasm/fiddle/fiddle.js 2a0984cc4a35e6889c0d84ee9bf853317d5545ddb3966dfb995bbe589f923c4c
|
||||
F ext/wasm/fiddle/index.c-pp.html 5fd1f462864710d1b00d27fc4bc6190cb846cc865d7cc93b99644423f2c4cc84
|
||||
F ext/wasm/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290
|
||||
F ext/wasm/index.html 5bf6cf1b0a3c8b9f5f54d77f2219d7ae87a15162055ce308109c49b1dcab4239
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
|
||||
F ext/wasm/libcmpp.c 0e2cec7de7c9cbe7941e6a4dc0c123cec736578a3eeae7828ac18706acd3cea6
|
||||
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
|
||||
F ext/wasm/mkwasmbuilds.c d4479af2774a43104b819d9286961b7c09793ca39440e20191e693ceff21f911
|
||||
F ext/wasm/mkwasmbuilds.c 60706fb66db7f1e24d876e3cb2493484cfb27e7b103c7741c384505dd678769c
|
||||
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -646,7 +649,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.c-pp.html 7171022e7f4da8f46e5f50ea81dd6ce840b9235c47653a5deeb3764ccc2fe472
|
||||
F ext/wasm/tester1.c-pp.html bd927ccf51ddd65e924660a0487add99e1b044afe03950e49d87ccf44efdddb6
|
||||
F ext/wasm/tester1.c-pp.js 581be6f3228351bc77512ba743912d1ad52f40dde1fef1a943fd568b0cfc51b1
|
||||
F ext/wasm/tester1.c-pp.js 38beb509f2136851760db79becd41a1ec0abcaaec01de27749b0fafcb0372e54
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 706eab6308343c04ac2360aba6001af4ffaf46d8f33a0ccd02c64d93e3216a43
|
||||
F ext/wasm/tests/opfs/concurrency/test.js 6919778fceaac1b7cc78caf41d796f545d2c4433b31188aa9689f05b5ad28828
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 704d82c5e287e47f612349e027765943a58ad967dcf178fb5a1c3a8eaafb09af
|
||||
@@ -656,7 +659,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 48f6b3557cefd79e5cfae1f15e32d6a0dffd7b689c582a9a7b3920a4ee18affd
|
||||
F main.mk d9cbbee974a8cd3999430130378878bd87b8c5754397a69ec322f4c9cc3e4e41
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -667,52 +670,52 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
|
||||
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
|
||||
F src/alter.c fc36b19273ffe364aeb4d00ba04bda8798ad7a67fec7a035ee8ee56272e1bdbe
|
||||
F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 7cf07d4fa42b9fc8662237c60c40b730326c30aa90ae5fffc0b18b2d726ebf61
|
||||
F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
|
||||
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
|
||||
F src/backup.c 6ebe22ccbedfcb92423833992130e8d65824be4e6599c3a03f540ab38fc7d13c
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c fb350c445316c1cc0529703c0b76450770a1de0ab0440641a56b19f05d6fefbe
|
||||
F src/btree.c 8aa7c903ef0181ff92c8365545ae75a1d648f57151b60c03c11b0a51da979edb
|
||||
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 8581de0af3b6c448f5d64e2d18a91ac1e7057b3bcb8b8827e1240f80d87486a4
|
||||
F src/build.c 866e584cdf40fbc83f530af9fd4d0991582a6fdbd8a9911b7cdbbea5f26a4a9e
|
||||
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
|
||||
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
|
||||
F src/complete.c 9304071c5f2ddd040cd786ec5d157c6a5592561674816e4a9e74164a0ba40647
|
||||
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
|
||||
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
|
||||
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
|
||||
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
|
||||
F src/expr.c d2188a699ded4522f15cf23d4c82da0ad73dcda09cd943982906824ef019947f
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
|
||||
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
|
||||
F src/func.c e8525e6c5493149680b0ebd3352e7f004ee7283181f24809b603329afe911443
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
|
||||
F src/insert.c 8dbc22f6ddcc5f0af3abf11daeb89b1978f00059cda15ebc61251fa7724fc7ee
|
||||
F src/json.c fadf5f0a00c1af99dbc6ac78dd3c2064c40bb28e602a5746f7c66c1ec8cbb006
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
|
||||
F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
|
||||
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
|
||||
F src/main.c 6180079f53ccdd784df2eddc3751f49ea7153c5959bee792b19ad9f4bdbcf437
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
|
||||
F src/memdb.c 0a0e827311cec57fdea2ed3142d6684704a1b90e7995b286f74fd7d1a6c5a62c
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
|
||||
F src/mutex.c 00b8cee206a67fd764d001f3a148494331d8d0b3b9c3974ecd69ff29bb444462
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
|
||||
F src/mutex_w32.c e1d317d29cb623667d43de94714264d1e1871cc4bb39fa67dd17048e8138c739
|
||||
F src/mutex_unix.c caec9862aeebad01f6c8997cf709a239abeb0715fcce1895720b87fe7e2ef42f
|
||||
F src/mutex_w32.c d44e94c064f8ab39e0318fb6fa00171cf7e5645bd4241129b07d655a8ddbd44b
|
||||
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
|
||||
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
|
||||
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
@@ -720,32 +723,32 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
|
||||
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
|
||||
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
|
||||
F src/os_unix.c a07dce662f6c4e18098f6faa9f7ec7cf311f56ee9151bed2aad4dcd55852c9e2
|
||||
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
|
||||
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
|
||||
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
|
||||
F src/os_win.c beae6892a5301541b932e8ada4c34dc871d96d4d98a28051382f32138501b1b9
|
||||
F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721
|
||||
F src/pager.c fbec9063ea139dfa5d94ce540671752b89f8e8dc38f8a1f614bab1aa04a2dd40
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
|
||||
F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
|
||||
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
|
||||
F src/printf.c d442fda86ad11da7923dbb354d3761229b5b51dbe06c5c208fa75e3411c79434
|
||||
F src/prepare.c 084a037fd3810cb7ffbfc001cd58c0ffac68ba36598a5084b55ea2a090014ebd
|
||||
F src/printf.c 2bc09ee91d69c709528575bbbee2199e16d6a7e68e1508ac7cf998a7289170ca
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
|
||||
F src/resolve.c 7e936a09405cb59e2b3e51a3ad23753e4803afc5269c5171a54c9bdd70f4fc50
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
|
||||
F src/shell.c.in ccadf849cfa03871c93f2869e27af177408ad028a4897626a1550d3fdbdcca18
|
||||
F src/sqlite.h.in a5605faa9479bbaac16c4ab43eb09ff50632004a8e05084d3fde56063ef73766
|
||||
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
|
||||
F src/shell.c.in 9dcc77636cdc48d67ea0cd7f4d54d791202e435e05598ec0a147cd61269e1c4d
|
||||
F src/sqlite.h.in 749454ec71c875bc130d399ff9a7e47191d143d1b9d8b4af3839b6028df9eda9
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
|
||||
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
|
||||
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
|
||||
F src/sqliteInt.h 5bec8cfdc8346a122b35312452eb6af33fc750a6c901f2c651a2f53eba0b979f
|
||||
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 7401c73c917a4d1b380c896a324c8d8eb533a999559d9e339d479596553bebfd
|
||||
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
|
||||
F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
|
||||
F src/test1.c fe1316579a1778eb96d0bd12807f9dddc5e3984f5950127e2e1718c050cb6304
|
||||
F src/test2.c 2b9ab96bba63a1c369d5769390475259ad210f144a877805f2e32e563f9e93c1
|
||||
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
|
||||
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
|
||||
@@ -799,13 +802,13 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 377af5da226519a0f374dc3c6d408c9d303a92943e3ae5986432c7d52e6679a2
|
||||
F src/util.c 98cf12c8ba65623a76c1eb6e6afa98ff40107c9919bf79af42f4bfc70e654232
|
||||
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
|
||||
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
|
||||
F src/vdbe.c 8ed6f274dff8b9fb961d050a9ab933e7f6509221718bec862e85729d171c1606
|
||||
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
|
||||
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
|
||||
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
|
||||
F src/vdbeaux.c 5387185849ef00062a5e84af731704e4bf5ec156d82cf5e509a442e9c03e089b
|
||||
F src/vdbeaux.c bd3aaf77593a5590f617ce173e8677a21eca18522eadc1c4bc81b53f6d1c7e19
|
||||
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
|
||||
F src/vdbemem.c efacb8f229422d2a4db0ed38e49b7f3897862a98d82b261aa3b43d7a2d98c6da
|
||||
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
|
||||
@@ -816,10 +819,10 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
|
||||
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c bffca5e4ef20d0bfbdc24f1dc13fd3f955284225a8ad25a4454635f6be39aad0
|
||||
F src/where.c 33e4a6558ee69f33d6a4e7069e3a40a55959d14e5653a9a83926e70305d471f3
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
|
||||
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
|
||||
F src/wherecode.c 4d573077652f79780d6b50840ab8cbb72053dbb4eb230780dd2a146ab034475d
|
||||
F src/whereexpr.c d111a5cb6147253a54010d883474b6aecc0b3009d352c087ee5295d74697bfef
|
||||
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
|
||||
@@ -830,15 +833,15 @@ F test/aggnested.test 610b0ce2c3e8f3daee25f9752800ee8d785db10da4aa1fbeea0ea1aaba
|
||||
F test/aggorderby.test 7be65e743f82ee49ba62da1c799e59341d23884a99edfe093df0cdfaac94cbbb
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test cf929f721e20960ca9db89471fa44f9176322ba8f25e97193f91881c223643b3
|
||||
F test/alter.test 3c00eff1e2036b9f93e9cd0f3d3e63750ac87ecb5bc71b9d7bd07cbf2ac4c494
|
||||
F test/alter.test 3acf3819d2cb1f0524a1b64c42b50a6b0d395c4f890f24dde5ec9e0d2e2eacc3
|
||||
F test/alter2.test 7e3d26ab409df52df887b366a63902c3429b935c41cb962fd58ffc25784f2f19
|
||||
F test/alter3.test dcdd5f850f30656a45a0f05e41abfb52b74bbf6ccba165d0f7adf6b0116e4fd6
|
||||
F test/alter4.test 37cafe164067a6590a0ee4cec780bddbbaa33dc50b11542dcfbe0e65626494fd
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
|
||||
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
|
||||
F test/altercons.test ea18def4a0f26b9066da56095c9c480df705df4d02e4ae151708fae76f7e3884
|
||||
F test/altercons2.test 3c1f58312817df43aeada3b1827fdc3ce3fc50c6f49a95ef62cf4cbbae8583a0
|
||||
F test/altercons.test 9b036a956268eccd64761a6af3ab6f7b313c738392c7460b747d8aacd32589a2
|
||||
F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
|
||||
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
|
||||
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
|
||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||
@@ -852,9 +855,9 @@ F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586
|
||||
F test/altertab2.test 0889ba0700cc1cdb7bc7d25975aa61fece34f621de963d0886e2395716b38576
|
||||
F test/altertab3.test 575e771e2f02b13eb98798dc92eabacd187d6dbcf596e70f11d699b0b6b5d0b2
|
||||
F test/altertrig.test b1590647076add5a47aea0f2236c609ca0bc8a7a2462463edd3e5882c7894802
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/amatch1.test 8a9405f497a57705a368f242658e2aea900dd2efbc48a48024263b0df6fc1ea0
|
||||
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
||||
F test/analyze3.test c5156cef33f04b90a6b9e9d5d0bbc273a0fb44147d4508407bf1080811e2c6c8
|
||||
F test/analyze3.test 42adfaedaddca1d93d9f4ac38465791e25a2e4b7a261a5278e92f554ac1e15f1
|
||||
F test/analyze4.test 68bd069f3ac7ac1e652ddd9f04f57d5606ddb4208450f5297005db7aa0dd707d
|
||||
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
|
||||
F test/analyze6.test 028f5bdfc9e5b5294768fa9a7185b8cd1d019aa7aab5b2f8ee42d7271d9a3b28
|
||||
@@ -878,7 +881,7 @@ F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
|
||||
F test/attachmalloc.test 67309af95c6b765c13e7d2279d7fccbef78e6eb0565d75d51cefd5dc88784549
|
||||
F test/auth.test 2a01bf5bf3a0f10adf8ae3a3fd2c05af8a8c1b7a52fae227adb4ccd931915b5c
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth2.test fb34df35ceca8d24e01219e993a3c1d9cb646e83b434627e158343bda1f6e0da
|
||||
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
F test/autoinc.test 9df9930966dbe92c55ef37a4d89112cfd537be0d0596d397177c12db9e581be0
|
||||
@@ -899,7 +902,7 @@ F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf.test cff75b714866a4ffa0cdda252eb8fe8765483f5872c0076223c92d52b4fffd1b
|
||||
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
|
||||
F test/basexx1.test 4ae6ddbd92a7ebcabb5d844664c3e755d29fb69c8ddcf0c8d59bbe4e07c23919
|
||||
F test/bc_common.tcl c70b896d1d4ce72f769d2c7c1fc15b2cb07559eb2093f2736c8ca51664b29ff5
|
||||
@@ -914,7 +917,7 @@ F test/bestindex8.test 4d8b1e8f30a7f405988ce4dbcc2b95c0775f0bed9ec08e0291a07e2f3
|
||||
F test/bestindex9.test 1a4b93db117fd8abe74ae9be982f86aa72f01e60cd4ac541e6ede39673a451a0
|
||||
F test/bestindexA.test e1b5def6b190797cacf008e6815ffb78fb30261999030d60a728d572eef44c7f
|
||||
F test/bestindexB.test 14db2f66ec9cc5064a74996033b74e5eec0fd2f3a327fbe34ff18de67e9d2671
|
||||
F test/bestindexC.test 95b4a527b1a5d07951d731604a6d4cf7e5a806b39cea0e7819d4c9667e11c3fc
|
||||
F test/bestindexC.test f44eb3d77359e9487222a2dde27f8ecf11a8e4932803c0dd9477f75e114f1c55
|
||||
F test/bestindexD.test 6a8f6f84990bcf17dfa59652a1f935beddb7afd96f8302830fbc86b0a13df3c3
|
||||
F test/bestindexE.test 297f3ea8500a8f3c17d6f78e55bdfee089064c6144ee84a110bd005a03338f49
|
||||
F test/bestindexF.test 4e53d606cbde40a2254aa016d500c5b71766a4065b8541202d195a3d9fe11b1c
|
||||
@@ -943,6 +946,8 @@ F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1
|
||||
F test/btreefault.test a82a23b0578bc587afbf9a622c8f54a54f63762f062ba8a35613cfee38ab42f9
|
||||
F test/busy.test caff7164c16ce06a53af51f9e4c2753d4cc64250e00790a5e48b9c4f4be37597
|
||||
F test/busy2.test 20823a5d7c42fb257d9f108c66312d90b1bb4ec3d80ba6b4e371073727560f98
|
||||
F test/c/malloc1.c 2869384011b5dc1f019ddd94e5248a1f2dfd07db06c6ce854793c91da173b811
|
||||
F test/c/snprintf1.c a66a1ce1195bd409740a60ebeea008686ce3fbacb445840fc0a45419823b7f3f
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
|
||||
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
|
||||
@@ -1039,7 +1044,7 @@ F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8b
|
||||
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
|
||||
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
|
||||
F test/dblwidth-a.sql 59dd59aa78ce8fd8ab631a3816516831f4e947b143039257e6fe132c3cea4171
|
||||
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
|
||||
F test/dbpage.test 2e3a50548edea551ef974b8f121f975852de9c5b16cb3284ac4bf2c9f2ed5a62
|
||||
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52
|
||||
@@ -1089,7 +1094,7 @@ F test/enc2.test 872afe58db772e7dfa1ad8e0759f8cc820e9efc8172d460fae83023101c2e43
|
||||
F test/enc3.test 55ef64416d72975c66167310a51dc9fc544ba3ae4858b8d5ab22f4cb6500b087
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 1d653fe8d2612cd6764e5ea2f16dcf5f13a9f50448b9233bb1573804bccd7579
|
||||
F test/eqp2.test 6e8996148de88f0e7670491e92e712a2920a369b4406f21a27c3c9b6a46b68dd
|
||||
F test/eqp2.test 188bc2293b9dab0932b6ac50c3fec62976815df072d7814d5547c821a8630819
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/errofst1.test 6da78363739ba8991f498396ab331b5d64e7ab5c4172c12b5884683ef523ac53
|
||||
F test/eval.test 73969a2d43a511bf44080c44485a8c4d796b6a4f038d19e491867081155692c0
|
||||
@@ -1097,14 +1102,15 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
|
||||
F test/exclusive2.test cd70b1d9c6fffd336f9795b711dcc5d9ceba133ad3f7001da3fda63615bdc91e
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/existsexpr.test 75c1c13cda18b53f68c135fe644afc034d72a6de5b0774b0219ca4a6dc4b96b0
|
||||
F test/existsexpr.test 1ce70ac41fb6d52525774388aa23e982428e883a850f9d56d49776d234865552
|
||||
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
|
||||
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
|
||||
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
|
||||
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
|
||||
F test/exprfault.test da33606d799718e2f8e34efd0e5858884a1ad87f608774c552a7f5517cc27181
|
||||
F test/exprfault.test 7475e363c7221847855722e9dd2459cf60088f6b172c0c808dba75f89e1704b8
|
||||
F test/exprfault2.test c49e84273898969af5dbc4fe6a3f4335f14639799f343590336c9ddf84425965
|
||||
F test/expridx1.test b464520126e1d781a7800f8540621c82e8bbc526f089ff8b0b57ffc51feea6b7
|
||||
F test/expridx2.test 13348ed208a5d18d9cef7d0a70f8e17948d3c0b5b46508c0573b7e983456165f
|
||||
F test/extension01.test 5de412c66276105901c370770175003381fdcb0c4da7054fa43cf4a31e0bfa3a
|
||||
F test/external_reader.test 6fdec43eeca23eb32faad1e95a4d1abc402bc8b3db70df12d6fc08a637f4a2b5
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
@@ -1245,7 +1251,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 207d3d1c1d578928f16dec20df781c5d13c2fd4694b4d70e72242f4dcb799830
|
||||
F test/fuzzcheck.c 5048a2426bd6968a1b9a00cef7f3aa37442a261df3b532c9e44a1f829bddbede
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1308,7 +1314,7 @@ F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 97cfb30b83ca1622b9422a1e4c4831b4cb767cf5d654660945036d1e72067e70
|
||||
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 2bf81535a990c969665d66db51fcf76c23499b39893b5109f413d1de4ad34cd3
|
||||
F test/insert4.test 3186fea9f85a4c88f50a9a9b64d23a064fb765c34505691244952fc51c243382
|
||||
F test/insert5.test 79f6b6efd0d3db5f4e3ff442300b7d9e7185adb345b29aacc3ea5a9c58ab9beb
|
||||
F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
|
||||
F test/instr.test 67ba309e9697c24a304e98a7c8f372456177dd4e32237d2a305e1e05f7bb79c2
|
||||
@@ -1316,7 +1322,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
|
||||
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
|
||||
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
|
||||
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/interrupt2.test 7eaa40a975d950826cd56e6c37f0f0629adfa2d1a8d3333aff0ff7cf86069963
|
||||
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
|
||||
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
|
||||
F test/io.test d267fdc8915444a45e19841489033ebe70bb69f6db605b00df70be16b2a80f59
|
||||
@@ -1343,7 +1349,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
|
||||
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
|
||||
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
|
||||
F test/joinH.test 1d2fc3190be68525fd9ce749b9468c40ba2930181e52fb5ee6f836051b38effb
|
||||
F test/joinI.test a4d37143fcc39e915d9feb08e614a13f88dfe332d77152a3c526a2370ddb9a70
|
||||
F test/joinI.test f5e8613c3262f056c56249cc98255bf5fa1a764d7667b8ceb9fe08b4c965f061
|
||||
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
|
||||
@@ -1420,7 +1426,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memdb1.test c737ac9aa5895092332b1dde24fae7ae494b7fcbcd346d22d600891096a3836d
|
||||
F test/memdb1.test 413f845c0c2d20dc9808d4084de9e57d55759070eed2a4cf23cd30335a96c295
|
||||
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
|
||||
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
|
||||
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
|
||||
@@ -1489,6 +1495,7 @@ F test/orderbyB.test 32576c7b138105bc72f7fbf33bd320ca3a7d303641fc939e0e56af6cba8
|
||||
F test/oserror.test ee3fad06ec8671c4d047c2c92a567fc2e0e8161caaec7edd6d48325c5ac97f30
|
||||
F test/ossfuzz.c b5d232d9717fc999a121c82c4880ae5b9d7fb3ae55d2d87a8da906bc80020906
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/output-redirect-test.txt aeebac99f766f1e54bb2628b13c2d89a3d77de942138a01210c8a814b54c2bc8
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test b083c2d5d89df8e979658d9320bfc0b9d50b4ef8ae1d9e115a692ff0b9768393
|
||||
F test/pager2.test c0ede15952b607f9a38f653acdfa73c19e657958e9104aab1a71950ea7b71831
|
||||
@@ -1513,8 +1520,8 @@ F test/pragma4.test 396ef9bff1fb966d41721545ad4b12bfc26aae315f5fe51d9b917828d49e
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragma6.test c5ec577ba087954b4dfa619a3cbe97b155b60a0af487527abe89b10fc17e6512
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
F test/printf.test bcb093ef5cbd17e2d94d93d62045ee61ed0f465c1ca123f284774e474e73a9ea
|
||||
F test/prefixes.test f2c4f30d5d439ca203ec69d72f5e1cc408916104e5310423542faef8003cf013
|
||||
F test/printf.test 854ddc19b31e83de41142a6b0c8dbb812fcdbbb127cdcafc0c5efef58b790eee
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
@@ -1554,7 +1561,7 @@ F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190c
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
|
||||
F test/rowvalue.test 93474d8e1c496e970bdcc3a7f54ac835adda667d2fd971957b4bce0c0b11707b
|
||||
F test/rowvalue.test ba43ff378f78c81579dd0f9f2b1e92876d29fb767f090acb7d4cbc6ff4a3c42c
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 103e9a224ca0548dd0d67e439f39c5dd16de4200221a333927372408c025324c
|
||||
F test/rowvalue4.test 6e160977d44ee715e142f63ec0e339586c61f12bbbffacee369b1cdc0b7390f0
|
||||
@@ -1563,7 +1570,7 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 06ec0aca725bf683313d03793aa2943bc7f45a901848c7056a9665b769c8fc38
|
||||
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
|
||||
F test/rowvalue9.test 7499a8fd7ca3a3f0e19d94e135355439aa2b596f86b775ca8de79672da2ca378
|
||||
F test/rowvalueA.test 7d28bf6c2f8a2af8adbba2c4eda9136a4dd36250b8966ba05b34c0954f78efd7
|
||||
F test/rowvalueA.test 5849865659f27ec50ba3185b2e18928a92077ceddf121ee6b95bf32300d44c91
|
||||
F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972d511c54fff
|
||||
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
@@ -1606,7 +1613,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
|
||||
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
|
||||
F test/sessionfuzz.c 0ec813258fbfd222c62ba6867c6a5a015f098fcaa6d89e7e0ee623ea91145cf0
|
||||
F test/shared.test 50bd8091735b272732125928c363476a17b5fb264835de7d19e90c72055c888b
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test cb92d083003ddf0f313166e494ec2fcafa55fdebf648628923ded3169dba8850
|
||||
@@ -1619,17 +1626,18 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test eda2e527435f139224dda67db6bbd2466597408d4fe5883d647d67fa32d88f7c
|
||||
F test/shell-prompt.sql 8a320a78812d75349bd5e1a95178f7ff1f2194bb4cceee572865d127c51684b3
|
||||
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
|
||||
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
|
||||
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
|
||||
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
|
||||
F test/shell5.test a9cd2c8b62e125049ef500937674f47dd6787f0157ac0515aa554044a4dc3ea9
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell5.test a0c43d82a811a463a5d07d6418c5a045ab01a072544db8aa31ae394e93845d8d
|
||||
F test/shell6.test 596f2eb385a1097d4e9130b4d4f663a24cba294b35f13b774b8f13553dec307d
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
|
||||
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
F test/shellB.test 31df04230f6062069bb7c5d0e5c5439ca44448fa9da1a55aa461a4b872fe6bd9
|
||||
F test/shellB.test 82622da7783c32ce931138bec3d5016e802d70361b9f9364b5d49c1dfc2f5af9
|
||||
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -1665,11 +1673,11 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest.md ea0c85ebe0ecff8b45ba6cdb26e694871f469009a5a29dcfe634b055f05ab241
|
||||
F test/speedtest.tcl b06f6321ef90bb68f18f7b0e430e25203d9da79b80f8926986a0d5f21ac485fb x
|
||||
F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce85721
|
||||
F test/speedtest1.c f9f30f35431bfc1d3ee9acc561624e0c0b4614071044bc302169dd27206a0fca
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae6a41fb
|
||||
F test/spellfix4.test 7c56a09de68b95051ef0627fe235e514efbba2aa816dc2a9c5c670d98877e632
|
||||
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
|
||||
F test/sqllimits1.test 408131e4975d61868711c83f101a56d4602313cc5cae88d3eee81c1da364fd89
|
||||
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
|
||||
@@ -1687,7 +1695,7 @@ F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e
|
||||
F test/subquery2.test ab96ff3fa9c4e3dce0d699f74e61c50250ed4335bc8f400e127707d552a8999e
|
||||
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
|
||||
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
|
||||
F test/subtype1.test 96fd2a59bfc845c955b5f339d23b37ef4d50de5f8a04acd1450a68605fa2e3e7
|
||||
F test/subtype1.test 1ca002dbda34c342c2dee7cffac220b77d67edfbffd43124978956747f534a96
|
||||
F test/superlock.test 85256830339a6871ce36a2ef591c3f67716a701b5497788fb2068b90159c2442
|
||||
F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e1e8e26
|
||||
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
|
||||
@@ -1699,7 +1707,7 @@ F test/sync.test a619e407ede58a7b6e3e44375328628559fc9695a9c24c47cb5690a866b0031
|
||||
F test/sync2.test 06152269ed73128782c450c355988fe8dd794d305833af75e1a5e79edd4dae47
|
||||
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test cfa96a9a235c39fb0cae69928b989b28bfec108f62d2533486f76e32dcedfdfb
|
||||
F test/tabfunc01.test 7827c2dfd57a094125b059f51a2200eaf04d417af6b1e720c34a8cbf54e8a14f
|
||||
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
|
||||
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
@@ -1714,8 +1722,8 @@ F test/temptrigfault.tes fc5918e64f3867156fefe7cfca9d8e1f495134a5229b2b511b0dc11
|
||||
F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3fb4769d61
|
||||
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
|
||||
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
|
||||
F test/testrunner.tcl 3b6cbceb4d7f0226d51a7fde247cc5592565953568c18155c8c3a454d93bee71 x
|
||||
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
|
||||
F test/testrunner.tcl 8f9cd46fe10f670f7f1f3430323f6031a13690303bd7810042d4bb20c47c5d9b x
|
||||
F test/testrunner_data.tcl 4b3cf036d39c98b83f9289a5c047eb01089c932d4f59a81bf764f6800589b959
|
||||
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
@@ -1884,7 +1892,7 @@ F test/trace3.test 2deeac66359c9f007f0fc9fb6336994a5d68fc1a65129f322a9e9546fd537
|
||||
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test f8ee983600b33d167da1885657f064aec404e1c0d0bc8765fdf163f4c749237a
|
||||
F test/transitive1.test 342b398e4c68deee65a940c5af22a95f44c3090b6539c7a19175afb48ac3fb93
|
||||
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
|
||||
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
@@ -1922,7 +1930,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d2366ef2d3d95249314307861d748924d9ab4f24305541159a08be61ccd4a9ee
|
||||
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
|
||||
F test/update.test 258dcf26d401177d3cb7fdf0beab14d671dbe72e8ff6e0435fd85a08fcd57bd9
|
||||
F test/update.test 93fba5f7505f7a7b25d66135d98d9b055b7f1bd627a7e514dbba1ea6213f0c41
|
||||
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
|
||||
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
|
||||
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
|
||||
@@ -2026,7 +2034,7 @@ F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9
|
||||
F test/walthread.test d562f51a61191ccfab64940df7aa1cef87c902fa5ab742590ef7f859dfe6a44b
|
||||
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
|
||||
F test/where.test 5087c72d26fd075a1644c8512be9fe18de9bf2d2b0754f7fd9b74a1c6540c4fc
|
||||
F test/where2.test 1dbff4ab847068a52b927a0c1a7cf7faed4c8cae081fbcdac9b052a3a209aefa
|
||||
F test/where2.test b73f8ee8f94b850764c429efe2d48171090628737dcc3df64a9f2214da02089f
|
||||
F test/where3.test 4ccb156ae33de86414a52775a6f590a9d60ba2cbc7a93a24fa331b7bcf5b6030
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@@ -2073,10 +2081,10 @@ F test/window8.tcl c57364e64d816f6e26df60437e1202e2c1031c7b818a1a67535d1006862a0
|
||||
F test/window8.test 3d931e58802b8ab8063da00f0cf30aa3351640238a952c0efb5a129e2349a4bb
|
||||
F test/window9.test 7b98a7916dd87763ea35f56ea023e3b29e99744582204ccf2937a3bac411cd4d
|
||||
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
|
||||
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
|
||||
F test/windowB.test bba3bee77c1d3321077ff8951d543161d74f08f78633d84433ced7d6261dc2c2
|
||||
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
|
||||
F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b
|
||||
F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f
|
||||
F test/windowE.test a82a4213c7b923220de5e457cb76c537a5d10d5e94641e3055ba21b79870a7fb
|
||||
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
|
||||
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
|
||||
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
|
||||
@@ -2108,7 +2116,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/build-all-msvc.bat 1ee9dbadcc07fc23268025854e97b392bcbad72376b47aee7b22f3797a4f2c87 x
|
||||
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
|
||||
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
|
||||
F tool/buildtclext.tcl b58df93e772fec8b2ae44ee1a82d13378e13edb1e94c4ab2f7ee3440a9523bff
|
||||
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
|
||||
@@ -2129,7 +2137,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/lemon.c 3fdc16b23f1ea0c91c049b518fc3f75c71843dbfe2b447fcb3cd92d9e4f219f8
|
||||
F tool/lempar.c b57e1780bf8098dd4a9a5bba537f994276ea825a420f6165153e5894dc2dfb07
|
||||
F tool/lempar.c a8de510526f9cbfb45ff0aca9d16f1c828600246f198c1c7d49c8d5492142ffa
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
|
||||
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
|
||||
@@ -2162,6 +2170,7 @@ F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d722
|
||||
F tool/omittest.tcl 436b7072e00e25e9b77145a9f67aa8e0eeabd186168827435fd03f8f981aac32
|
||||
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
|
||||
F tool/pagesig.c f98909b4168d9cac11a2de7f031adea0e2f3131faa7515a72807c03ec58eafeb
|
||||
F tool/renumber-win-thunk.tcl d6320eeba3a1ddfa4624003ad77e96a01819e56b4df58a698c2267ea71b79d39
|
||||
F tool/replace.tcl 511c61acfe563dfb58675efb4628bb158a13d48ff8322123ac447e9d25a82d9a
|
||||
F tool/restore_jrnl.tcl 1079ecba47cc82fa82115b81c1f68097ab1f956f357ee8da5fc4b2589af6bd98
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
@@ -2176,7 +2185,7 @@ F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdadd
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
|
||||
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
|
||||
F tool/sqldiff.c de59a4eecbc802db8ad053889c10e6f8b8427b6f349199ee79938c92c20860dd
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
|
||||
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
|
||||
@@ -2197,8 +2206,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P 6aafb76c74b73aafef74250dae9c8cbe73226c0efb606e8f80ea761b3293cf9d
|
||||
R 10023fb5872b0939880b2eb9aec2ef11
|
||||
U drh
|
||||
Z c3b3ebd71cd1378ad565509dcb2c7b21
|
||||
P c6226d508d6af28fcd42fecd482014c3e284923871d3d8f5177f728cbf3457c5
|
||||
R 1eabf6c03fde51e4f558b57e68078de8
|
||||
U dan
|
||||
Z 7d1f8058359dfe62c0d29a8d06d235a4
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch cli-prompt-redo
|
||||
tag cli-prompt-redo
|
||||
branch session-update-loops
|
||||
tag session-update-loops
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
354325b6f396bda38bbb82e7d38aa50d3d6441e1ebb9b578aed8e0bcf62f9911
|
||||
eba02092bcf1713a646ecf8febd53a83bc803cf1b17e2e4fc590c14d886a8d27
|
||||
|
||||
+19
-5
@@ -2798,7 +2798,9 @@ void sqlite3AlterDropConstraint(
|
||||
if( !pTab ) return;
|
||||
|
||||
if( pCons ){
|
||||
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
|
||||
char *z = sqlite3NameFromToken(db, pCons);
|
||||
zArg = sqlite3MPrintf(db, "%Q", z);
|
||||
sqlite3DbFree(db, z);
|
||||
}else{
|
||||
int iCol;
|
||||
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
|
||||
@@ -2985,19 +2987,31 @@ void sqlite3AlterAddConstraint(
|
||||
SrcList *pSrc, /* Table to add constraint to */
|
||||
Token *pFirst, /* First token of new constraint */
|
||||
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
||||
const char *pExpr, /* Text of CHECK expression */
|
||||
int nExpr /* Size of pExpr in bytes */
|
||||
const char *zExpr, /* Text of CHECK expression */
|
||||
int nExpr, /* Size of pExpr in bytes */
|
||||
Expr *pExpr /* The parsed CHECK expression */
|
||||
){
|
||||
Table *pTab = 0; /* Table identified by pSrc */
|
||||
int iDb = 0; /* Which schema does pTab live in */
|
||||
const char *zDb = 0; /* Name of the schema in which pTab lives */
|
||||
const char *pCons = 0; /* Text of the constraint */
|
||||
int nCons; /* Bytes of text to use from pCons[] */
|
||||
int rc; /* Result from error checking pExpr */
|
||||
|
||||
/* Look up the table being altered. */
|
||||
assert( pSrc->nSrc==1 );
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
|
||||
if( !pTab ) return;
|
||||
if( !pTab ){
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Verify that the new CHECK constraint does not contain any
|
||||
** internal-use-only function. Forum post 2026-05-10T01:11:28Z
|
||||
*/
|
||||
rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
|
||||
sqlite3ExprDelete(pParse->db, pExpr);
|
||||
if( rc ) return;
|
||||
|
||||
/* If this new constraint has a name, check that it is not a duplicate of
|
||||
** an existing constraint. It is an error if it is. */
|
||||
@@ -3018,7 +3032,7 @@ void sqlite3AlterAddConstraint(
|
||||
sqlite3NestedParse(pParse,
|
||||
"SELECT sqlite_fail('constraint failed', %d) "
|
||||
"FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
|
||||
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
|
||||
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
|
||||
);
|
||||
|
||||
/* Edit the SQL for the named table. */
|
||||
|
||||
+11
-2
@@ -106,6 +106,16 @@ static void attachFunc(
|
||||
** from sqlite3_deserialize() to close database db->init.iDb and
|
||||
** reopen it as a MemDB */
|
||||
Btree *pNewBt = 0;
|
||||
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
assert( pNew->pBt!=0 );
|
||||
if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
|
||||
|| sqlite3BtreeIsInBackup(pNew->pBt)
|
||||
){
|
||||
rc = SQLITE_BUSY;
|
||||
goto attach_error;
|
||||
}
|
||||
|
||||
pVfs = sqlite3_vfs_find("memdb");
|
||||
if( pVfs==0 ) return;
|
||||
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
|
||||
@@ -115,8 +125,7 @@ static void attachFunc(
|
||||
/* Both the Btree and the new Schema were allocated successfully.
|
||||
** Close the old db and update the aDb[] slot with the new memdb
|
||||
** values. */
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
|
||||
sqlite3BtreeClose(pNew->pBt);
|
||||
pNew->pBt = pNewBt;
|
||||
pNew->pSchema = pNewSchema;
|
||||
}else{
|
||||
|
||||
+21
-2
@@ -189,8 +189,14 @@ void sqlite3AuthRead(
|
||||
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
|
||||
** is returned, then the error count and error message in pParse are
|
||||
** modified appropriately.
|
||||
**
|
||||
** Divided into two routines. realAuthCheck() does the work. The
|
||||
** sqlite3AuthCheck() routine is usually a fast no-op but invokes
|
||||
** realAuthCheck() (and spends time doing some stack pushes and pops
|
||||
** as a result) in the uncommon case where an authorization check is
|
||||
** actually needed.
|
||||
*/
|
||||
int sqlite3AuthCheck(
|
||||
static int SQLITE_NOINLINE realAuthCheck(
|
||||
Parse *pParse,
|
||||
int code,
|
||||
const char *zArg1,
|
||||
@@ -204,7 +210,7 @@ int sqlite3AuthCheck(
|
||||
** or if the parser is being invoked from within sqlite3_declare_vtab.
|
||||
*/
|
||||
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
|
||||
if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
|
||||
if( IN_SPECIAL_PARSE ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -229,6 +235,19 @@ int sqlite3AuthCheck(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3AuthCheck(
|
||||
Parse *pParse,
|
||||
int code,
|
||||
const char *zArg1,
|
||||
const char *zArg2,
|
||||
const char *zArg3
|
||||
){
|
||||
if( pParse->db->xAuth!=0 && pParse->db->init.busy==0 ){
|
||||
return realAuthCheck(pParse,code,zArg1,zArg2,zArg3);
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Push an authorization context. After this routine is called, the
|
||||
|
||||
+66
-54
@@ -20,13 +20,13 @@
|
||||
*/
|
||||
struct sqlite3_backup {
|
||||
sqlite3* pDestDb; /* Destination database handle */
|
||||
Btree *pDest; /* Destination b-tree file */
|
||||
Db *pDest; /* Destination db file */
|
||||
u32 iDestSchema; /* Original schema cookie in destination */
|
||||
int bDestLocked; /* True once a write-transaction is open on pDest */
|
||||
|
||||
Pgno iNext; /* Page number of the next source page to copy */
|
||||
sqlite3* pSrcDb; /* Source database handle */
|
||||
Btree *pSrc; /* Source b-tree file */
|
||||
Db *pSrc; /* Source db file */
|
||||
|
||||
int rc; /* Backup process error code */
|
||||
|
||||
@@ -79,7 +79,7 @@ struct sqlite3_backup {
|
||||
** function. If an error occurs while doing so, return 0 and write an
|
||||
** error message to pErrorDb.
|
||||
*/
|
||||
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
static Db *findDatabase(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
int i = sqlite3FindDbName(pDb, zDb);
|
||||
|
||||
if( i==1 ){
|
||||
@@ -102,7 +102,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDb->aDb[i].pBt;
|
||||
return &pDb->aDb[i];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -110,9 +110,9 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
** of the source.
|
||||
*/
|
||||
static int setDestPgsz(sqlite3_backup *p){
|
||||
int rc;
|
||||
rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
|
||||
return rc;
|
||||
return sqlite3BtreeSetPageSize(p->pDest->pBt,
|
||||
sqlite3BtreeGetPageSize(p->pSrc->pBt), 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,15 +181,15 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
|
||||
/* If the allocation succeeded, populate the new object. */
|
||||
if( p ){
|
||||
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
|
||||
p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
|
||||
p->pSrc = findDatabase(pDestDb, pSrcDb, zSrcDb);
|
||||
p->pDest = findDatabase(pDestDb, pDestDb, zDestDb);
|
||||
p->pDestDb = pDestDb;
|
||||
p->pSrcDb = pSrcDb;
|
||||
p->iNext = 1;
|
||||
p->isAttached = 0;
|
||||
|
||||
if( 0==p->pSrc || 0==p->pDest
|
||||
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
|
||||
|| checkReadTransaction(pDestDb, p->pDest->pBt)!=SQLITE_OK
|
||||
){
|
||||
/* One (or both) of the named databases did not exist or an OOM
|
||||
** error was hit. Or there is a transaction open on the destination
|
||||
@@ -201,7 +201,7 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
}
|
||||
}
|
||||
if( p ){
|
||||
p->pSrc->nBackup++;
|
||||
p->pSrc->pBt->nBackup++;
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(pDestDb->mutex);
|
||||
@@ -229,18 +229,18 @@ static int backupOnePage(
|
||||
const u8 *zSrcData, /* Source database page data */
|
||||
int bUpdate /* True for an update, false otherwise */
|
||||
){
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
|
||||
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
|
||||
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest->pBt);
|
||||
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc->pBt);
|
||||
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest->pBt);
|
||||
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
|
||||
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
|
||||
int rc = SQLITE_OK;
|
||||
i64 iOff;
|
||||
|
||||
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
|
||||
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc->pBt)>=0 );
|
||||
assert( p->bDestLocked );
|
||||
assert( !isFatalError(p->rc) );
|
||||
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
|
||||
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt->pBt) );
|
||||
assert( zSrcData );
|
||||
assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 );
|
||||
|
||||
@@ -251,7 +251,7 @@ static int backupOnePage(
|
||||
for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
|
||||
DbPage *pDestPg = 0;
|
||||
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
|
||||
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
|
||||
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt->pBt) ) continue;
|
||||
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
|
||||
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
|
||||
){
|
||||
@@ -269,7 +269,7 @@ static int backupOnePage(
|
||||
memcpy(zOut, zIn, nCopy);
|
||||
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
|
||||
if( iOff==0 && bUpdate==0 ){
|
||||
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
|
||||
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc->pBt));
|
||||
}
|
||||
}
|
||||
sqlite3PagerUnref(pDestPg);
|
||||
@@ -301,8 +301,8 @@ static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
|
||||
*/
|
||||
static void attachBackupObject(sqlite3_backup *p){
|
||||
sqlite3_backup **pp;
|
||||
assert( sqlite3BtreeHoldsMutex(p->pSrc) );
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
|
||||
assert( sqlite3BtreeHoldsMutex(p->pSrc->pBt) );
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
|
||||
p->pNext = *pp;
|
||||
*pp = p;
|
||||
p->isAttached = 1;
|
||||
@@ -316,20 +316,26 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
int destMode; /* Destination journal mode */
|
||||
int pgszSrc = 0; /* Source page size */
|
||||
int pgszDest = 0; /* Destination page size */
|
||||
Btree *pDest;
|
||||
Btree *pSrc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( p->pDest );
|
||||
assert( p->pSrc );
|
||||
pDest = p->pDest->pBt;
|
||||
pSrc = p->pSrc->pBt;
|
||||
sqlite3_mutex_enter(p->pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
sqlite3BtreeEnter(pSrc);
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_enter(p->pDestDb->mutex);
|
||||
}
|
||||
|
||||
rc = p->rc;
|
||||
if( !isFatalError(rc) ){
|
||||
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
|
||||
Pager * const pSrcPager = sqlite3BtreePager(pSrc); /* Source pager */
|
||||
Pager * const pDestPager = sqlite3BtreePager(pDest); /* Dest pager */
|
||||
int ii; /* Iterator variable */
|
||||
int nSrcPage = -1; /* Size of source db in pages */
|
||||
int bCloseTrans = 0; /* True if src db requires unlocking */
|
||||
@@ -337,7 +343,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
/* If the source pager is currently in a write-transaction, return
|
||||
** SQLITE_BUSY immediately.
|
||||
*/
|
||||
if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
|
||||
if( p->pDestDb && pSrc->pBt->inTransaction==TRANS_WRITE ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
@@ -347,8 +353,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** one now. If a transaction is opened here, then it will be closed
|
||||
** before this function exits.
|
||||
*/
|
||||
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
|
||||
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
|
||||
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(pSrc) ){
|
||||
rc = sqlite3BtreeBeginTrans(pSrc, 0, 0);
|
||||
bCloseTrans = 1;
|
||||
}
|
||||
|
||||
@@ -364,7 +370,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Lock the destination database, if it is not locked already. */
|
||||
if( SQLITE_OK==rc && p->bDestLocked==0
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2,
|
||||
(int*)&p->iDestSchema))
|
||||
){
|
||||
p->bDestLocked = 1;
|
||||
@@ -372,9 +378,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Do not allow backup if the destination database is in WAL mode
|
||||
** and the page sizes are different between source and destination */
|
||||
pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
|
||||
pgszDest = sqlite3BtreeGetPageSize(p->pDest);
|
||||
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
|
||||
pgszSrc = sqlite3BtreeGetPageSize(pSrc);
|
||||
pgszDest = sqlite3BtreeGetPageSize(pDest);
|
||||
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(pDest));
|
||||
if( SQLITE_OK==rc
|
||||
&& (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
|
||||
&& pgszSrc!=pgszDest
|
||||
@@ -385,11 +391,11 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
/* Now that there is a read-lock on the source database, query the
|
||||
** source pager for the number of pages in the database.
|
||||
*/
|
||||
nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
|
||||
nSrcPage = (int)sqlite3BtreeLastPage(pSrc);
|
||||
assert( nSrcPage>=0 );
|
||||
for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
|
||||
const Pgno iSrcPg = p->iNext; /* Source page number */
|
||||
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
|
||||
if( iSrcPg!=PENDING_BYTE_PAGE(pSrc->pBt) ){
|
||||
DbPage *pSrcPg; /* Source page object */
|
||||
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -416,18 +422,18 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
if( rc==SQLITE_DONE ){
|
||||
if( nSrcPage==0 ){
|
||||
rc = sqlite3BtreeNewDb(p->pDest);
|
||||
rc = sqlite3BtreeNewDb(pDest);
|
||||
nSrcPage = 1;
|
||||
}
|
||||
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
|
||||
rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
|
||||
rc = sqlite3BtreeUpdateMeta(pDest,1,p->iDestSchema+1);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p->pDestDb ){
|
||||
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
|
||||
}
|
||||
if( destMode==PAGER_JOURNALMODE_WAL ){
|
||||
rc = sqlite3BtreeSetVersion(p->pDest, 2);
|
||||
rc = sqlite3BtreeSetVersion(pDest, 2);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -444,12 +450,12 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** journalled by PagerCommitPhaseOne() before they are destroyed
|
||||
** by the file truncation.
|
||||
*/
|
||||
assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
|
||||
assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
|
||||
assert( pgszSrc==sqlite3BtreeGetPageSize(pSrc) );
|
||||
assert( pgszDest==sqlite3BtreeGetPageSize(pDest) );
|
||||
if( pgszSrc<pgszDest ){
|
||||
int ratio = pgszDest/pgszSrc;
|
||||
nDestTruncate = (nSrcPage+ratio-1)/ratio;
|
||||
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
|
||||
if( nDestTruncate==(int)PENDING_BYTE_PAGE(pDest->pBt) ){
|
||||
nDestTruncate--;
|
||||
}
|
||||
}else{
|
||||
@@ -477,7 +483,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
assert( pFile );
|
||||
assert( nDestTruncate==0
|
||||
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
|
||||
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
|
||||
nDestTruncate==(int)(PENDING_BYTE_PAGE(pDest->pBt)-1)
|
||||
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
|
||||
));
|
||||
|
||||
@@ -489,7 +495,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** journal file. */
|
||||
sqlite3PagerPagecount(pDestPager, &nDstPage);
|
||||
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
|
||||
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
|
||||
if( iPg!=PENDING_BYTE_PAGE(pDest->pBt) ){
|
||||
DbPage *pPg;
|
||||
rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -533,7 +539,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Finish committing the transaction to the destination database. */
|
||||
if( SQLITE_OK==rc
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(pDest, 0))
|
||||
){
|
||||
rc = SQLITE_DONE;
|
||||
}
|
||||
@@ -547,8 +553,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
if( bCloseTrans ){
|
||||
TESTONLY( int rc2 );
|
||||
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
|
||||
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
|
||||
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(pSrc, 0);
|
||||
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(pSrc, 0);
|
||||
assert( rc2==SQLITE_OK );
|
||||
}
|
||||
|
||||
@@ -560,7 +566,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_leave(p->pDestDb->mutex);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
sqlite3BtreeLeave(pSrc);
|
||||
sqlite3_mutex_leave(p->pSrcDb->mutex);
|
||||
return rc;
|
||||
}
|
||||
@@ -577,17 +583,17 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
pSrcDb = p->pSrcDb;
|
||||
sqlite3_mutex_enter(pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
sqlite3BtreeEnter(p->pSrc->pBt);
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_enter(p->pDestDb->mutex);
|
||||
}
|
||||
|
||||
/* Detach this backup from the source pager. */
|
||||
if( p->pDestDb ){
|
||||
p->pSrc->nBackup--;
|
||||
p->pSrc->pBt->nBackup--;
|
||||
}
|
||||
if( p->isAttached ){
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
|
||||
assert( pp!=0 );
|
||||
while( *pp!=p ){
|
||||
pp = &(*pp)->pNext;
|
||||
@@ -597,7 +603,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
}
|
||||
|
||||
/* If a transaction is still open on the Btree, roll it back. */
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
|
||||
sqlite3BtreeRollback(p->pDest->pBt, SQLITE_OK, 0);
|
||||
|
||||
/* Set the error code of the destination database handle. */
|
||||
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
|
||||
@@ -607,7 +613,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
sqlite3BtreeLeave(p->pSrc->pBt);
|
||||
if( p->pDestDb ){
|
||||
/* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
|
||||
** call to sqlite3_backup_init() and is destroyed by a call to
|
||||
@@ -665,7 +671,7 @@ static SQLITE_NOINLINE void backupUpdate(
|
||||
){
|
||||
assert( p!=0 );
|
||||
do{
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
|
||||
if( !isFatalError(p->rc) && iPage<p->iNext ){
|
||||
/* The backup process p has already copied page iPage. But now it
|
||||
** has been modified by a transaction on the source pager. Copy
|
||||
@@ -701,7 +707,7 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
|
||||
void sqlite3BackupRestart(sqlite3_backup *pBackup){
|
||||
sqlite3_backup *p; /* Iterator variable */
|
||||
for(p=pBackup; p; p=p->pNext){
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
|
||||
p->iNext = 1;
|
||||
}
|
||||
}
|
||||
@@ -719,6 +725,8 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
int rc;
|
||||
sqlite3_file *pFd; /* File descriptor for database pTo */
|
||||
sqlite3_backup b;
|
||||
Db dbDest;
|
||||
Db dbSrc;
|
||||
sqlite3BtreeEnter(pTo);
|
||||
sqlite3BtreeEnter(pFrom);
|
||||
|
||||
@@ -737,9 +745,13 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
** from this function, not directly by the user.
|
||||
*/
|
||||
memset(&b, 0, sizeof(b));
|
||||
memset(&dbDest, 0, sizeof(dbDest));
|
||||
memset(&dbSrc, 0, sizeof(dbSrc));
|
||||
dbDest.pBt = pTo;
|
||||
dbSrc.pBt = pFrom;
|
||||
b.pSrcDb = pFrom->db;
|
||||
b.pSrc = pFrom;
|
||||
b.pDest = pTo;
|
||||
b.pSrc = &dbSrc;
|
||||
b.pDest = &dbDest;
|
||||
b.iNext = 1;
|
||||
|
||||
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
|
||||
@@ -755,7 +767,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
if( rc==SQLITE_OK ){
|
||||
pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
|
||||
}else{
|
||||
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
|
||||
sqlite3PagerClearCache(sqlite3BtreePager(pTo));
|
||||
}
|
||||
|
||||
assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
|
||||
|
||||
+28
-3
@@ -15,6 +15,16 @@
|
||||
*/
|
||||
#include "btreeInt.h"
|
||||
|
||||
/*
|
||||
** Suppress false-positive compiler warnings from GCC. Warnings are
|
||||
** re-enabled at the bottom of this source file.
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||
# pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The header string that appears at the beginning of every
|
||||
** SQLite database.
|
||||
@@ -5290,6 +5300,14 @@ static int accessPayload(
|
||||
(eOp==0 ? PAGER_GET_READONLY : 0)
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( eOp!=0
|
||||
&& (sqlite3PagerPageRefcount(pDbPage)!=1
|
||||
|| NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit))
|
||||
&& sqlite3FaultSim(411)==SQLITE_OK
|
||||
){
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
aPayload = sqlite3PagerGetData(pDbPage);
|
||||
nextPage = get4byte(aPayload);
|
||||
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
|
||||
@@ -5939,12 +5957,12 @@ moveto_table_finish:
|
||||
** zero if the cell is less than or equal pIdxKey. Return positive
|
||||
** if unknown.
|
||||
**
|
||||
** Return value negative: Cell at pCur[idx] less than pIdxKey
|
||||
** Return value negative: Cell at pPage[idx] less than pIdxKey
|
||||
**
|
||||
** Return value is zero: Cell at pCur[idx] equals pIdxKey
|
||||
** Return value is zero: Cell at pPage[idx] equals pIdxKey
|
||||
**
|
||||
** Return value positive: Nothing is known about the relationship
|
||||
** of the cell at pCur[idx] and pIdxKey.
|
||||
** of the cell at pPage[idx] and pIdxKey.
|
||||
**
|
||||
** This routine is part of an optimization. It is always safe to return
|
||||
** a positive value as that will cause the optimization to be skipped.
|
||||
@@ -11566,3 +11584,10 @@ int sqlite3BtreeConnectionCount(Btree *p){
|
||||
return p->pBt->nRef;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Re-enable GCC compiler warnings that were suppressed at the top
|
||||
** of this source file to prevent annoying false-positives.
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
+18
@@ -714,6 +714,19 @@ Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
|
||||
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Suppress false-positive warning message generated with -O3 in GCC
|
||||
** on the second call to sqlite3Strlen30() in the sqlite3ColumnSetColl()
|
||||
** function below. See the forum thread beginning on 2026-05-10T01:11:22Z.
|
||||
**
|
||||
** See also the "pop" pragma to undo this warning suppression immediately
|
||||
** after the function.
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Set the collating sequence name for a column.
|
||||
*/
|
||||
@@ -739,6 +752,11 @@ void sqlite3ColumnSetColl(
|
||||
}
|
||||
}
|
||||
|
||||
/* Undo the false-positive warning suppression above. */
|
||||
#if defined(__GNUC__) && __GNUC__>=11
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the collating sequence name for a column
|
||||
*/
|
||||
|
||||
+4
-4
@@ -332,10 +332,10 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
}
|
||||
incomplete_finish:
|
||||
if( state==1 ) nParen = 0;
|
||||
return (((i64)nParen)<<32) |
|
||||
((i64)pending<<16) |
|
||||
((i64)statemap[state]<<8) |
|
||||
(state!=1);
|
||||
return (i64)((((u64)nParen)<<32) |
|
||||
((u64)pending<<16) |
|
||||
((u64)statemap[state]<<8) |
|
||||
(state!=1));
|
||||
}
|
||||
int sqlite3_complete(const char *zSql){
|
||||
return sqlite3_incomplete(zSql)==0;
|
||||
|
||||
+9
-6
@@ -259,12 +259,13 @@ static int dbpageFilter(
|
||||
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
|
||||
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
|
||||
if( idxNum & 1 ){
|
||||
i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
|
||||
assert( argc>(idxNum>>1) );
|
||||
pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
|
||||
if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
|
||||
if( iPg<1 || iPg>pCsr->mxPgno ){
|
||||
pCsr->pgno = 1;
|
||||
pCsr->mxPgno = 0;
|
||||
}else{
|
||||
pCsr->pgno = (Pgno)iPg;
|
||||
pCsr->mxPgno = pCsr->pgno;
|
||||
}
|
||||
}else{
|
||||
@@ -344,6 +345,7 @@ static int dbpageUpdate(
|
||||
){
|
||||
DbpageTable *pTab = (DbpageTable *)pVtab;
|
||||
Pgno pgno;
|
||||
sqlite3_int64 pgno64;
|
||||
DbPage *pDbPage = 0;
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
@@ -363,11 +365,11 @@ static int dbpageUpdate(
|
||||
goto update_fail;
|
||||
}
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
|
||||
pgno = (Pgno)sqlite3_value_int64(argv[2]);
|
||||
pgno64 = sqlite3_value_int64(argv[2]);
|
||||
isInsert = 1;
|
||||
}else{
|
||||
pgno = (Pgno)sqlite3_value_int64(argv[0]);
|
||||
if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
|
||||
pgno64 = (Pgno)sqlite3_value_int64(argv[0]);
|
||||
if( sqlite3_value_int64(argv[1])!=pgno64 ){
|
||||
zErr = "cannot insert";
|
||||
goto update_fail;
|
||||
}
|
||||
@@ -384,10 +386,11 @@ static int dbpageUpdate(
|
||||
}
|
||||
}
|
||||
pBt = pTab->db->aDb[iDb].pBt;
|
||||
if( pgno<1 || NEVER(pBt==0) ){
|
||||
if( pgno64<1 || pgno64>4294967294 || NEVER(pBt==0) ){
|
||||
zErr = "bad page number";
|
||||
goto update_fail;
|
||||
}
|
||||
pgno = (Pgno)pgno64;
|
||||
szPage = sqlite3BtreeGetPageSize(pBt);
|
||||
if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(argv[3])!=szPage
|
||||
|
||||
+6
-3
@@ -915,6 +915,7 @@ void sqlite3GenerateRowIndexDelete(
|
||||
v = pParse->pVdbe;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||
int p3 = 0;
|
||||
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
|
||||
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
|
||||
if( pIdx==pPk ) continue;
|
||||
@@ -922,10 +923,12 @@ void sqlite3GenerateRowIndexDelete(
|
||||
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
|
||||
&iPartIdxLabel, pPrior, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
|
||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
|
||||
);
|
||||
if( pIdx->bHasExpr && aRegIdx ){
|
||||
p3 = aRegIdx[i];
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
|
||||
sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
|
||||
sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
|
||||
pPrior = pIdx;
|
||||
}
|
||||
|
||||
+28
-15
@@ -331,7 +331,9 @@ CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
|
||||
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
|
||||
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
|
||||
return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
|
||||
assert( (pColl1==pColl2) ==
|
||||
(sqlite3_stricmp(pColl1->zName,pColl2->zName)==0) );
|
||||
return pColl1==pColl2;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2650,7 +2652,7 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||
** Walk an expression tree. Return non-zero if
|
||||
**
|
||||
** (1) the expression is constant, and
|
||||
** (2) the expression does originate in the ON or USING clause
|
||||
** (2) the expression does not originate in the ON or USING clause
|
||||
** of a LEFT JOIN, and
|
||||
** (3) the expression does not contain any EP_FixedCol TK_COLUMN
|
||||
** operands created by the constant propagation optimization.
|
||||
@@ -4685,26 +4687,37 @@ static int exprCodeInlineFunction(
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression Node callback for sqlite3ExprCanReturnSubtype().
|
||||
** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
|
||||
** pExpr is able to return a subtype, set pWalker->eCode and abort
|
||||
** the search. If pExpr can never return a subtype, prune search.
|
||||
**
|
||||
** Only a function call is able to return a subtype. So if the node
|
||||
** is not a function call, return WRC_Prune immediately.
|
||||
** The only expressions that can return a subtype are:
|
||||
**
|
||||
** A function call is able to return a subtype if it has the
|
||||
** SQLITE_RESULT_SUBTYPE property.
|
||||
** 1. A function
|
||||
** 2. The no-op "+" operator
|
||||
** 3. A CASE...END expression
|
||||
** 4. A CAST() expression
|
||||
** 5. A "expr COLLATE colseq" expression.
|
||||
**
|
||||
** Assume that every function is able to pass-through a subtype from
|
||||
** one of its argument (using sqlite3_result_value()). Most functions
|
||||
** are not this way, but we don't have a mechanism to distinguish those
|
||||
** that are from those that are not, so assume they all work this way.
|
||||
** That means that if one of its arguments is another function and that
|
||||
** other function is able to return a subtype, then this function is
|
||||
** able to return a subtype.
|
||||
** For any other kind of expression, prune the search.
|
||||
**
|
||||
** For case 1, the expression can yield a subtype if the function has
|
||||
** the SQLITE_RESULT_SUBTYPE property. Functions can also return
|
||||
** a subtype (via sqlite3_result_value()) if any of the arguments can
|
||||
** return a subtype.
|
||||
**
|
||||
** In all cases 1 through 5, the expression might also return a subtype
|
||||
** if any operand can return a subtype.
|
||||
*/
|
||||
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
||||
int n;
|
||||
FuncDef *pDef;
|
||||
sqlite3 *db;
|
||||
if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
|
||||
|| pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
|
||||
){
|
||||
return WRC_Continue;
|
||||
}
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return WRC_Prune;
|
||||
}
|
||||
@@ -4714,7 +4727,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
||||
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
||||
pWalker->eCode = 1;
|
||||
return WRC_Prune;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
+38
-16
@@ -130,13 +130,17 @@ static void lengthFunc(
|
||||
case SQLITE_TEXT: {
|
||||
const unsigned char *z = sqlite3_value_text(argv[0]);
|
||||
const unsigned char *z0;
|
||||
unsigned char c;
|
||||
if( z==0 ) return;
|
||||
z0 = z;
|
||||
while( (c = *z)!=0 ){
|
||||
z++;
|
||||
if( c>=0xc0 ){
|
||||
while( (*z & 0xc0)==0x80 ){ z++; z0++; }
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
z++;
|
||||
}else if( z[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
z++;
|
||||
while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
|
||||
}
|
||||
}
|
||||
sqlite3_result_int(context, (int)(z-z0));
|
||||
@@ -415,12 +419,25 @@ static void substrFunc(
|
||||
}
|
||||
assert( p1>=0 && p2>=0 );
|
||||
if( p0type!=SQLITE_BLOB ){
|
||||
while( *z && p1 ){
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
p1--;
|
||||
for( ; p1>0; p1--){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
z++;
|
||||
}else if( z[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
do{ z++; }while( (z[0]&0xc0)==0x80 );
|
||||
}
|
||||
}
|
||||
for(z2=z; *z2 && p2; p2--){
|
||||
SQLITE_SKIP_UTF8(z2);
|
||||
for(z2=z; p2>0; p2--){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z2[0]-1)<(0x80-1) ){
|
||||
z2++;
|
||||
}else if( z2[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
do{ z2++; }while( (z2[0]&0xc0)==0x80 );
|
||||
}
|
||||
}
|
||||
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
|
||||
SQLITE_UTF8);
|
||||
@@ -1966,11 +1983,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
assert( p->cnt>0 );
|
||||
p->cnt--;
|
||||
if( !p->approx ){
|
||||
if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
|
||||
p->ovrfl = 1;
|
||||
p->approx = 1;
|
||||
i64 x = p->iSum;
|
||||
if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
|
||||
p->iSum = x;
|
||||
return;
|
||||
}
|
||||
}else if( type==SQLITE_INTEGER ){
|
||||
p->ovrfl = 1;
|
||||
p->approx = 1;
|
||||
kahanBabuskaNeumaierInit(p, p->iSum);
|
||||
}
|
||||
if( type==SQLITE_INTEGER ){
|
||||
i64 iVal = sqlite3_value_int64(argv[0]);
|
||||
if( iVal!=SMALLEST_INT64 ){
|
||||
kahanBabuskaNeumaierStepInt64(p, -iVal);
|
||||
@@ -3106,7 +3128,7 @@ static void filestatFunc(
|
||||
assert( pPager!=0 );
|
||||
fd = sqlite3PagerFile(pPager);
|
||||
pStr = sqlite3_str_new(db);
|
||||
if( pStr==0 ){
|
||||
if( sqlite3_str_errcode(pStr) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_str_append(pStr, "{\"db\":", 6);
|
||||
@@ -3209,7 +3231,7 @@ static void parseuriFunc(
|
||||
flgs = (unsigned int)sqlite3_value_int(argv[1]);
|
||||
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
|
||||
pResult = sqlite3_str_new(0);
|
||||
if( pResult ){
|
||||
if( !sqlite3_str_errcode(pResult) ){
|
||||
int i;
|
||||
sqlite3_str_appendf(pResult, "rc=%d", rc);
|
||||
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
|
||||
|
||||
+68
-4
@@ -2809,7 +2809,10 @@ void sqlite3CompleteInsertion(
|
||||
|| pIdx->pNext==0
|
||||
|| pIdx->pNext->onError==OE_Replace );
|
||||
if( aRegIdx[i]==0 ) continue;
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
|
||||
/* If this is a partial index, or an UPDATE of an index on an
|
||||
** expression, then the record register may be set to NULL to indicate
|
||||
** that no record should be inserted into this index. */
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
@@ -2984,6 +2987,44 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Examine an expression node and abort if it references the ROWID.
|
||||
** This is a Walker callback used by xferCompatibleCheck()
|
||||
*/
|
||||
static int xferCheckRowid(Walker *pWalk, Expr *pExpr){
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iColumn<0 ){
|
||||
pWalk->eCode = 1;
|
||||
return WRC_Abort;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Analyze CHECK constraints on the source and destination tables and
|
||||
** return true if those CHECK constraints are compatible with the
|
||||
** xfer-optimization.
|
||||
**
|
||||
** * The pDest and pSrc tables must have identical CHECK constraints.
|
||||
**
|
||||
** * If the destination table, pDest, does not have an
|
||||
** INTEGER PRIMARY KEY column, then no CHECK constraint may
|
||||
** referenced the ROWID. (See forum post 2026-05-11T13:15:57Z)
|
||||
*/
|
||||
static int xferCompatibleCheck(Table *pDest, Table *pSrc){
|
||||
if( sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
|
||||
return 0;
|
||||
}
|
||||
if( pDest->iPKey<0 ){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = xferCheckRowid;
|
||||
sqlite3WalkExprList(&w,pDest->pCheck);
|
||||
if( w.eCode ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt the transfer optimization on INSERTs of the form
|
||||
**
|
||||
@@ -3110,8 +3151,19 @@ static int xferOptimization(
|
||||
if( pDest->iPKey!=pSrc->iPKey ){
|
||||
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
|
||||
}
|
||||
if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
|
||||
return 0; /* Cannot feed from a non-strict into a strict table */
|
||||
if( (pDest->tabFlags & TF_Strict)!=0 ){
|
||||
if( (pSrc->tabFlags & TF_Strict)==0 ){
|
||||
return 0; /* Cannot feed from a non-strict into a strict table */
|
||||
}
|
||||
for(i=0; i<pDest->nCol; i++){
|
||||
unsigned eDestType = pDest->aCol[i].eCType;
|
||||
unsigned eSrcType = pSrc->aCol[i].eCType;
|
||||
if( eDestType==COLTYPE_ANY ) continue;
|
||||
if( eDestType==eSrcType ) continue;
|
||||
if( eDestType==COLTYPE_INT && eSrcType==COLTYPE_INTEGER ) continue;
|
||||
if( eDestType==COLTYPE_INTEGER && eSrcType==COLTYPE_INT ) continue;
|
||||
return 0; /* Incompatible types in source and destination */
|
||||
}
|
||||
}
|
||||
for(i=0; i<pDest->nCol; i++){
|
||||
Column *pDestCol = &pDest->aCol[i];
|
||||
@@ -3205,7 +3257,7 @@ static int xferOptimization(
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
if( pDest->pCheck
|
||||
&& (db->mDbFlags & DBFLAG_Vacuum)==0
|
||||
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
|
||||
&& !xferCompatibleCheck(pDest,pSrc)
|
||||
){
|
||||
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
||||
}
|
||||
@@ -3226,6 +3278,18 @@ static int xferOptimization(
|
||||
if( (db->flags & SQLITE_CountRows)!=0 ){
|
||||
return 0; /* xfer opt does not play well with PRAGMA count_changes */
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( db->xAuth ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pSrc->pSchema);
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 0;
|
||||
for(i=0; i<pSrc->nCol; i++){
|
||||
Column *pSrcCol = &pSrc->aCol[i];
|
||||
if( sqlite3AuthReadCol(pParse, pSrc->zName, pSrcCol->zCnName, iDb) ){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we get this far, it means that the xfer optimization is at
|
||||
** least a possibility, though it might only work if the destination
|
||||
|
||||
+63
-10
@@ -2340,7 +2340,7 @@ static u32 jsonTranslateBlobToText(
|
||||
break;
|
||||
case 0xe2:
|
||||
/* '\' followed by either U+2028 or U+2029 is ignored as
|
||||
** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29.
|
||||
** whitespace. Note that in UTF8, U+2028 is 0xe2 0x80 0x29.
|
||||
** U+2029 is the same except for the last byte */
|
||||
if( sz2<4
|
||||
|| 0x80!=(u8)zIn[2]
|
||||
@@ -4909,11 +4909,9 @@ static void jsonGroupInverse(
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
#ifdef NEVER
|
||||
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
||||
** always have been called to initialize it */
|
||||
if( NEVER(!pStr) ) return;
|
||||
#endif
|
||||
z = pStr->zBuf;
|
||||
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
|
||||
if( c=='"' ){
|
||||
@@ -4942,6 +4940,13 @@ static void jsonGroupInverse(
|
||||
** json_group_obj(NAME,VALUE)
|
||||
**
|
||||
** Return a JSON object composed of all names and values in the aggregate.
|
||||
**
|
||||
** Rows for which NAME is NULL do not result in a new entry. However, we
|
||||
** do initially insert a "@" entry into the growing string for each null entry
|
||||
** and change the first character of the string to "@" to signal that the
|
||||
** string contains null entries. The "@" markers are needed in order to
|
||||
** correctly process xInverse() requests. The initial "@" is converted
|
||||
** back into "{" and the "@" null values are removed by jsonObjectCompute().
|
||||
*/
|
||||
static void jsonObjectStep(
|
||||
sqlite3_context *ctx,
|
||||
@@ -4959,7 +4964,7 @@ static void jsonObjectStep(
|
||||
if( pStr->zBuf==0 ){
|
||||
jsonStringInit(pStr, ctx);
|
||||
jsonAppendChar(pStr, '{');
|
||||
}else if( pStr->nUsed>1 && z!=0 ){
|
||||
}else if( pStr->nUsed>1 ){
|
||||
jsonAppendChar(pStr, ',');
|
||||
}
|
||||
pStr->pCtx = ctx;
|
||||
@@ -4967,6 +4972,9 @@ static void jsonObjectStep(
|
||||
jsonAppendString(pStr, z, n);
|
||||
jsonAppendChar(pStr, ':');
|
||||
jsonAppendSqlValue(pStr, argv[1]);
|
||||
}else{
|
||||
pStr->zBuf[0] = '@';
|
||||
jsonAppendRawNZ(pStr, "@", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4975,20 +4983,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
||||
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
if( pStr ){
|
||||
jsonAppendRawNZ(pStr, "}", 2);
|
||||
jsonStringTrimOneChar(pStr);
|
||||
JsonString *pOgStr = pStr;
|
||||
JsonString tmpStr;
|
||||
jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
|
||||
jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
|
||||
pStr->pCtx = ctx;
|
||||
if( pStr->eErr ){
|
||||
jsonReturnString(pStr, 0, 0);
|
||||
return;
|
||||
}else if( flags & JSON_BLOB ){
|
||||
}
|
||||
if( pStr->zBuf[0]!='{' ){
|
||||
/* The string contains null entries that need to be removed */
|
||||
u64 i, j;
|
||||
int inStr = 0;
|
||||
if( !isFinal ){
|
||||
/* Work with a temporary copy of the string if this is not the
|
||||
** final result */
|
||||
jsonStringInit(&tmpStr, ctx);
|
||||
jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
|
||||
pStr = &tmpStr;
|
||||
if( pStr->eErr ){
|
||||
jsonReturnString(pStr, 0, 0);
|
||||
return;
|
||||
}
|
||||
jsonStringTrimOneChar(pStr); /* Remove zero terminator */
|
||||
}
|
||||
/* Fix up the string by changing the initial "@" flag back to
|
||||
** to "{" and removing all subsequence "@" entries, with their
|
||||
** associated comma delimeters. */
|
||||
pStr->zBuf[0] = '{';
|
||||
for(i=j=1; i<pStr->nUsed; i++){
|
||||
char c = pStr->zBuf[i];
|
||||
if( c=='"' ){
|
||||
inStr = !inStr;
|
||||
pStr->zBuf[j++] = '"';
|
||||
}else if( c=='\\' ){
|
||||
pStr->zBuf[j++] = '\\';
|
||||
pStr->zBuf[j++] = pStr->zBuf[++i];
|
||||
}else if( c=='@' && !inStr ){
|
||||
assert( i+1<pStr->nUsed );
|
||||
if( pStr->zBuf[i+1]==',' ){
|
||||
i++;
|
||||
}else if( pStr->zBuf[j-1]==',' ){
|
||||
j--;
|
||||
}
|
||||
}else{
|
||||
pStr->zBuf[j++] = c;
|
||||
}
|
||||
}
|
||||
pStr->zBuf[j] = 0; /* Restore zero terminator */
|
||||
pStr->nUsed = j; /* Truncate the string */
|
||||
}
|
||||
if( flags & JSON_BLOB ){
|
||||
jsonReturnStringAsBlob(pStr);
|
||||
if( isFinal ){
|
||||
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
|
||||
}else{
|
||||
jsonStringTrimOneChar(pStr);
|
||||
jsonStringTrimOneChar(pOgStr);
|
||||
}
|
||||
return;
|
||||
}else if( isFinal ){
|
||||
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
|
||||
pStr->bStatic ? SQLITE_TRANSIENT :
|
||||
@@ -4996,8 +5048,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
||||
pStr->bStatic = 1;
|
||||
}else{
|
||||
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
||||
jsonStringTrimOneChar(pStr);
|
||||
jsonStringTrimOneChar(pOgStr);
|
||||
}
|
||||
if( pStr!=pOgStr ) jsonStringReset(pStr);
|
||||
}else if( flags & JSON_BLOB ){
|
||||
static const unsigned char emptyObject = 0x0c;
|
||||
sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
|
||||
|
||||
+3
-2
@@ -528,11 +528,12 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_str_free,
|
||||
#ifdef SQLITE_ENABLE_CARRAY
|
||||
sqlite3_carray_bind,
|
||||
sqlite3_carray_bind_v2
|
||||
sqlite3_carray_bind_v2,
|
||||
#else
|
||||
0,
|
||||
0
|
||||
0,
|
||||
#endif
|
||||
sqlite3_incomplete
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
+2
-1
@@ -1136,7 +1136,8 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of changes in the most recent call to sqlite3_exec().
|
||||
** Return the number of changes in the most recently executed DML
|
||||
** statement.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
|
||||
+3
-4
@@ -876,10 +876,10 @@ int sqlite3_deserialize(
|
||||
if( rc ) goto end_deserialize;
|
||||
db->init.iDb = (u8)iDb;
|
||||
db->init.reopenMemdb = 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
sqlite3_step(pStmt);
|
||||
db->init.reopenMemdb = 0;
|
||||
if( rc!=SQLITE_DONE ){
|
||||
rc = SQLITE_ERROR;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_deserialize;
|
||||
}
|
||||
p = memdbFromDbSchema(db, zSchema);
|
||||
@@ -900,7 +900,6 @@ int sqlite3_deserialize(
|
||||
}
|
||||
|
||||
end_deserialize:
|
||||
sqlite3_finalize(pStmt);
|
||||
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
|
||||
+35
-16
@@ -35,8 +35,15 @@
|
||||
# define SQLITE_MUTEX_NREF 0
|
||||
#endif
|
||||
|
||||
#if GCC_VERSION>0
|
||||
# define ALIGN128 __attribute__((aligned(128)))
|
||||
#else
|
||||
# define ALIGN128
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Each recursive mutex is an instance of the following structure.
|
||||
** Each SQLite mutex is an instance of the following structure.
|
||||
**
|
||||
*/
|
||||
struct sqlite3_mutex {
|
||||
pthread_mutex_t mutex; /* Mutex controlling the lock */
|
||||
@@ -151,19 +158,31 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
|
||||
** the same type number.
|
||||
*/
|
||||
static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
static sqlite3_mutex staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
/* Static mutexes - those with IDs of 2 or more...
|
||||
**
|
||||
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
|
||||
** so that adjacent mutex objects are always on different cache lines
|
||||
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
|
||||
** seems to work well for all contemporary processors. Experiments show
|
||||
** that 64 works just as well most of the time, but the internet says
|
||||
** that 128-byte alignment works better.
|
||||
*/
|
||||
static ALIGN128 union staticMutex {
|
||||
sqlite3_mutex m;
|
||||
char aSpacer[128];
|
||||
} aMutex[] = {
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(2) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(3) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(4) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(5) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(6) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(7) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(8) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(9) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(10) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(11) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(12) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(13) },
|
||||
};
|
||||
sqlite3_mutex *p;
|
||||
switch( iType ){
|
||||
@@ -200,12 +219,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
|
||||
if( iType-2<0 || iType-2>=ArraySize(aMutex) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &staticMutexes[iType-2];
|
||||
p = &aMutex[iType-2].m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+87
-94
@@ -31,11 +31,29 @@
|
||||
*/
|
||||
#ifdef SQLITE_MUTEX_W32
|
||||
|
||||
#if MSVC_VERSION>0
|
||||
# define ALIGN128 __declspec(align(128))
|
||||
#else
|
||||
# define ALIGN128
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4324)
|
||||
/*
|
||||
** Each recursive mutex is an instance of the following structure.
|
||||
** Each SQLite mutex is an instance of the following structure.
|
||||
**
|
||||
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
|
||||
** so that adjacent mutex objects are always on different cache lines
|
||||
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
|
||||
** seems to work well for all contemporary processors. Experiments show
|
||||
** that 64 works just as well most of the time, but the internet says
|
||||
** that 128-byte alignment works better.
|
||||
*/
|
||||
struct sqlite3_mutex {
|
||||
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
|
||||
struct sqlite3_mutex {
|
||||
union {
|
||||
CRITICAL_SECTION cs; /* The CRITICAL_SECTION mutex. id==1 */
|
||||
SRWLOCK srwl; /* The Slim reader/writer lock. id!=1 */
|
||||
} u;
|
||||
int id; /* Mutex type */
|
||||
#ifdef SQLITE_DEBUG
|
||||
volatile int nRef; /* Number of entrances */
|
||||
@@ -43,20 +61,7 @@ struct sqlite3_mutex {
|
||||
volatile LONG trace; /* True to trace changes */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** These are the initializer values used when declaring a "static" mutex
|
||||
** on Win32. It should be noted that all mutexes require initialization
|
||||
** on the Win32 platform.
|
||||
*/
|
||||
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
|
||||
0L, (DWORD)0, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
|
||||
#endif
|
||||
#pragma warning(pop)
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
@@ -67,13 +72,8 @@ static int winMutexHeld(sqlite3_mutex *p){
|
||||
return p->nRef!=0 && p->owner==GetCurrentThreadId();
|
||||
}
|
||||
|
||||
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
|
||||
return p->nRef==0 || p->owner!=tid;
|
||||
}
|
||||
|
||||
static int winMutexNotheld(sqlite3_mutex *p){
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
return winMutexNotheld2(p, tid);
|
||||
return p->nRef==0 || p->owner!=GetCurrentThreadId();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -95,41 +95,42 @@ void sqlite3MemoryBarrier(void){
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
** Static mutexes.
|
||||
**
|
||||
** The ALIGN128 macro on the static mutex array forces 128-byte alignment
|
||||
** on the mutexes so that adjacent mutex objects are always on different
|
||||
** cache lines in the CPU. This is CPU-dependent, of course, but 128-byte
|
||||
** alignment seems to work well for all contemporary processors.
|
||||
** Experiments show that 64 works just as well most of the time, but
|
||||
** the internet says that 128-byte alignment works better.
|
||||
*/
|
||||
static sqlite3_mutex winMutex_staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
};
|
||||
|
||||
static ALIGN128 union staticMutexes {
|
||||
sqlite3_mutex m;
|
||||
char spacer[128];
|
||||
} aWindowsMutex[12];
|
||||
static int winMutex_isInit = 0;
|
||||
static int winMutex_isNt = -1; /* <0 means "need to query" */
|
||||
|
||||
/* As the winMutexInit() and winMutexEnd() functions are called as part
|
||||
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
|
||||
** "interlocked" magic used here is probably not strictly necessary.
|
||||
*/
|
||||
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
|
||||
static LONG volatile winMutex_lock = 0;
|
||||
|
||||
int sqlite3_win32_is_nt(void); /* os_win.c */
|
||||
void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
|
||||
static int winMutexInit(void){
|
||||
/* The first to increment to 1 does actual initialization */
|
||||
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
||||
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
|
||||
for(i=0; i<ArraySize(aWindowsMutex); i++){
|
||||
sqlite3_mutex *p = &aWindowsMutex[i].m;
|
||||
p->id = i+2;
|
||||
InitializeSRWLock(&p->u.srwl);
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->nRef = 0;
|
||||
p->owner = 0;
|
||||
p->trace = 0;
|
||||
#endif
|
||||
}
|
||||
winMutex_isInit = 1;
|
||||
}else{
|
||||
@@ -147,10 +148,6 @@ static int winMutexEnd(void){
|
||||
** (which should be the last to shutdown.) */
|
||||
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
|
||||
if( winMutex_isInit==1 ){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
||||
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
|
||||
}
|
||||
winMutex_isInit = 0;
|
||||
}
|
||||
}
|
||||
@@ -219,18 +216,22 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
p->trace = 1;
|
||||
#endif
|
||||
#endif
|
||||
InitializeCriticalSection(&p->mutex);
|
||||
if( iType==SQLITE_MUTEX_RECURSIVE ){
|
||||
InitializeCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
InitializeSRWLock(&p->u.srwl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
|
||||
if( iType-2<0 || iType-2>=ArraySize(aWindowsMutex) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &winMutex_staticMutexes[iType-2];
|
||||
p = &aWindowsMutex[iType-2].m;
|
||||
#ifdef SQLITE_DEBUG
|
||||
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
|
||||
InterlockedCompareExchange(&p->trace, 1, 0);
|
||||
@@ -252,8 +253,10 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
static void winMutexFree(sqlite3_mutex *p){
|
||||
assert( p );
|
||||
assert( p->nRef==0 && p->owner==0 );
|
||||
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
DeleteCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_FAST ){
|
||||
sqlite3_free(p);
|
||||
}else if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
DeleteCriticalSection(&p->u.cs);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
@@ -274,67 +277,56 @@ static void winMutexFree(sqlite3_mutex *p){
|
||||
** more than once, the behavior is undefined.
|
||||
*/
|
||||
static void winMutexEnter(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
assert( p );
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
#else
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
#endif
|
||||
assert( winMutex_isInit==1 );
|
||||
EnterCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
EnterCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
AcquireSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p->nRef>0 || p->owner==0 );
|
||||
p->owner = tid;
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->nRef++;
|
||||
if( p->trace ){
|
||||
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
||||
tid, p->id, p, p->trace, p->nRef));
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int winMutexTry(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
int rc = SQLITE_BUSY;
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
/*
|
||||
** The sqlite3_mutex_try() routine is very rarely used, and when it
|
||||
** is used it is merely an optimization. So it is OK for it to always
|
||||
** The sqlite3_mutex_try() routine is seldom used, and when it is
|
||||
** used it is merely an optimization. So it is OK for it to always
|
||||
** fail.
|
||||
**
|
||||
** The TryEnterCriticalSection() interface is only available on WinNT.
|
||||
** And some windows compilers complain if you try to use it without
|
||||
** first doing some #defines that prevent SQLite from building on Win98.
|
||||
** For that reason, we will omit this optimization for now. See
|
||||
** ticket #2685.
|
||||
*/
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
|
||||
assert( winMutex_isInit==1 );
|
||||
assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
|
||||
if( winMutex_isNt<0 ){
|
||||
winMutex_isNt = sqlite3_win32_is_nt();
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
rc = TryEnterCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
rc = TryAcquireSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
assert( winMutex_isNt==0 || winMutex_isNt==1 );
|
||||
if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
|
||||
if( rc ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->owner = tid;
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->nRef++;
|
||||
#endif
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER(p);
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
|
||||
tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
|
||||
OSTRACE((
|
||||
"TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->owner, p->nRef,
|
||||
sqlite3ErrName(rc)));
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
@@ -347,23 +339,24 @@ static int winMutexTry(sqlite3_mutex *p){
|
||||
** is not currently allocated. SQLite will never do either.
|
||||
*/
|
||||
static void winMutexLeave(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
assert( p );
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p->nRef>0 );
|
||||
assert( p->owner==tid );
|
||||
assert( p->owner==GetCurrentThreadId() );
|
||||
p->nRef--;
|
||||
if( p->nRef==0 ) p->owner = 0;
|
||||
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
|
||||
#endif
|
||||
assert( winMutex_isInit==1 );
|
||||
LeaveCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
LeaveCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
ReleaseSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
||||
tid, p->id, p, p->trace, p->nRef));
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+428
-1601
File diff suppressed because it is too large
Load Diff
+1
-43
@@ -27,53 +27,11 @@
|
||||
# include <errno.h> /* amalgamator: dontcache */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
** We ought to be able to determine if we are compiling for Windows 9x or
|
||||
** Windows NT using the _WIN32_WINNT macro as follows:
|
||||
**
|
||||
** #if defined(_WIN32_WINNT)
|
||||
** # define SQLITE_OS_WINNT 1
|
||||
** #else
|
||||
** # define SQLITE_OS_WINNT 0
|
||||
** #endif
|
||||
**
|
||||
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
|
||||
** it ought to, so the above test does not work. We'll just assume that
|
||||
** everything is Windows NT unless the programmer explicitly says otherwise
|
||||
** by setting SQLITE_OS_WINNT to 0.
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
||||
# define SQLITE_OS_WINNT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows CE - which has a much reduced
|
||||
** API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
# define SQLITE_OS_WINCE 1
|
||||
#else
|
||||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For WinCE, some API function parameters do not appear to be declared as
|
||||
** volatile.
|
||||
*/
|
||||
#if SQLITE_OS_WINCE
|
||||
# define SQLITE_WIN32_VOLATILE
|
||||
#else
|
||||
# define SQLITE_WIN32_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
|
||||
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \
|
||||
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
|
||||
#if SQLITE_OS_WIN && SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
|
||||
# define SQLITE_OS_WIN_THREADS 1
|
||||
#else
|
||||
# define SQLITE_OS_WIN_THREADS 0
|
||||
|
||||
+4
-4
@@ -1993,7 +1993,7 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
|
||||
** database transaction.
|
||||
**
|
||||
** This routine is never called in PAGER_ERROR state. If it is called
|
||||
** in PAGER_NONE or PAGER_SHARED state and the lock held is less
|
||||
** in PAGER_OPEN or PAGER_READER state and the lock held is less
|
||||
** exclusive than a RESERVED lock, it is a no-op.
|
||||
**
|
||||
** Otherwise, any active savepoints are released.
|
||||
@@ -3754,7 +3754,7 @@ void sqlite3PagerSetBusyHandler(
|
||||
**
|
||||
** then the pager object page size is set to *pPageSize.
|
||||
**
|
||||
** If the page size is changed, then this function uses sqlite3PagerMalloc()
|
||||
** If the page size is changed, then this function uses sqlite3PageMalloc()
|
||||
** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
|
||||
** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
|
||||
** In all other cases, SQLITE_OK is returned.
|
||||
@@ -5101,8 +5101,8 @@ sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
|
||||
|
||||
/*
|
||||
** This function is called after transitioning from PAGER_UNLOCK to
|
||||
** PAGER_SHARED state. It tests if there is a hot journal present in
|
||||
** This function is called while transitioning from PAGER_OPEN to a
|
||||
** higher state. It tests if there is a hot journal present in
|
||||
** the file-system for the given pager. A hot journal is one that
|
||||
** needs to be played back. According to this function, a hot-journal
|
||||
** file exists if the following criteria are met:
|
||||
|
||||
+9
-6
@@ -1334,9 +1334,11 @@ expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
|
||||
ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
|
||||
A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
||||
if( A ){
|
||||
int i;
|
||||
A->x.pList = pList;
|
||||
if( ALWAYS(pList->nExpr) ){
|
||||
A->flags |= pList->a[0].pExpr->flags & EP_Propagate;
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
assert( pList->a[i].pExpr!=0 );
|
||||
A->flags |= pList->a[i].pExpr->flags & EP_Propagate;
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
@@ -1476,6 +1478,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
|
||||
if( A ){
|
||||
A->x.pList = pList;
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
@@ -1909,11 +1912,11 @@ cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) DROP NOT NULL. {
|
||||
cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) SET NOT(Z) NULL onconf. {
|
||||
sqlite3AlterSetNotNull(pParse, X, &Y, &Z);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1));
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr(E) RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1), E);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1));
|
||||
cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr(E) RP(B) onconf. {
|
||||
sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1), E);
|
||||
}
|
||||
|
||||
kwcolumn_opt ::= .
|
||||
|
||||
+7
-1
@@ -216,7 +216,13 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
||||
|
||||
db->init.busy = 1;
|
||||
db->init.busy = 1 + ((mFlags & INITFLAG_AlterAdd)!=0);
|
||||
/* ^--- Any non-zero value for init.busy means that we are scanning
|
||||
** the sqlite_schema table to build the internal schema representation,
|
||||
** rather than running actual CREATE statements. init.busy==2 has the
|
||||
** additional meaning that the scan is happening as part of
|
||||
** ALTER TABLE ADD COLUMN, which is stricter in its enforcement of
|
||||
** function name resolution. */
|
||||
|
||||
/* Construct the in-memory representation schema tables (sqlite_schema or
|
||||
** sqlite_temp_schema) by invoking the parser directly. The appropriate
|
||||
|
||||
+115
-33
@@ -34,8 +34,10 @@
|
||||
#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
|
||||
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
|
||||
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
|
||||
#define etESCAPE_j 17 /* %j -> JSON string literal w/o "..." */
|
||||
#define etESCAPE_J 18 /* %J -> JSON string literal with "..." */
|
||||
|
||||
#define etINVALID 17 /* Any unrecognized conversion type */
|
||||
#define etINVALID 19 /* Any unrecognized conversion type */
|
||||
|
||||
|
||||
/*
|
||||
@@ -65,20 +67,20 @@ typedef struct et_info { /* Information about each format field */
|
||||
|
||||
/*
|
||||
** The table is searched by hash. In the case of %C where C is the character
|
||||
** and that character has ASCII value j, then the hash is j%23.
|
||||
** and that character has ASCII value j, then the hash is j%25.
|
||||
**
|
||||
** The order of the entries in fmtinfo[] and the hash chain was entered
|
||||
** manually, but based on the output of the following TCL script:
|
||||
*/
|
||||
#if 0 /***** Beginning of script ******/
|
||||
foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {
|
||||
foreach c {d s g z q Q w c o u x X f e E G i n % p T S r J j} {
|
||||
scan $c %c x
|
||||
set n($c) $x
|
||||
}
|
||||
set mx [llength [array names n]]
|
||||
puts "count: $mx"
|
||||
|
||||
set mx 27
|
||||
set mx 25
|
||||
puts "*********** mx=$mx ************"
|
||||
for {set r 0} {$r<$mx} {incr r} {
|
||||
puts -nonewline [format %2d: $r]
|
||||
@@ -90,31 +92,34 @@ for {set r 0} {$r<$mx} {incr r} {
|
||||
#endif /***** End of script ********/
|
||||
|
||||
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
|
||||
static const char aHex[] = "0123456789abcdef";
|
||||
static const char aPrefix[] = "-x0\000X0";
|
||||
static const et_info fmtinfo[23] = {
|
||||
/* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },
|
||||
/* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */
|
||||
/* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },
|
||||
/* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */
|
||||
/* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },
|
||||
/* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
|
||||
/* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */
|
||||
/* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },
|
||||
/* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
|
||||
/* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
|
||||
/* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
|
||||
/* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
|
||||
/* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },
|
||||
/* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
|
||||
/* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },
|
||||
/* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
|
||||
/* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */
|
||||
/* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */
|
||||
/* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
|
||||
/* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },
|
||||
/* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },
|
||||
/* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },
|
||||
/* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }
|
||||
static const et_info fmtinfo[25] = {
|
||||
/* 0 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
|
||||
/* 1 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
|
||||
/* 2 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
|
||||
/* 3 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
|
||||
/* 4 */ { 'j', 0, 0, etESCAPE_j, 0, 0, 0 }, /* Hash: 6 */
|
||||
/* 5 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
|
||||
/* 6 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 4 },
|
||||
/* 7 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 }, /* Hash: 12 */
|
||||
/* 8 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 },
|
||||
/* 9 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
|
||||
/* 10 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
|
||||
/* 11 */ { 'o', 8, 0, etRADIX, 0, 2, 0 },
|
||||
/* 12 */ { '%', 0, 0, etPERCENT, 0, 0, 7 },
|
||||
/* 13 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 16 },
|
||||
/* 14 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 },
|
||||
/* 15 */ { 's', 0, 4, etSTRING, 0, 0, 0 },
|
||||
/* 16 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 13 */
|
||||
/* 17 */ { 'u', 10, 0, etDECIMAL, 0, 0, 0 },
|
||||
/* 18 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 }, /* Hash: 19 */
|
||||
/* 19 */ { 'E', 0, 1, etEXP, 14, 0, 18 },
|
||||
/* 20 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
|
||||
/* 21 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 },
|
||||
/* 22 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 0 },
|
||||
/* 23 */ { 'J', 0, 0, etESCAPE_J, 0, 0, 0 }, /* Hash: 24 */
|
||||
/* 24 */ { 'c', 0, 0, etCHARX, 0, 0, 23 }
|
||||
};
|
||||
|
||||
/* Additional Notes:
|
||||
@@ -375,8 +380,8 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
#else
|
||||
/* Fast hash-table lookup */
|
||||
assert( ArraySize(fmtinfo)==23 );
|
||||
idx = ((unsigned)c) % 23;
|
||||
assert( ArraySize(fmtinfo)==25 );
|
||||
idx = ((unsigned)c) % 25;
|
||||
if( fmtinfo[idx].fmttype==c
|
||||
|| fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c
|
||||
){
|
||||
@@ -747,7 +752,7 @@ void sqlite3_str_vappendf(
|
||||
|
||||
if( zExtra==0 ){
|
||||
/* The result is being rendered directory into pAccum. This
|
||||
** is the command and fast case */
|
||||
** is the common and fast case */
|
||||
pAccum->nChar += length;
|
||||
zOut[length] = 0;
|
||||
continue;
|
||||
@@ -867,6 +872,83 @@ void sqlite3_str_vappendf(
|
||||
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
|
||||
}
|
||||
break;
|
||||
case etESCAPE_j: /* %j: JSON string literal w/o "..." */
|
||||
case etESCAPE_J: { /* %J: Generate a JSON string literal */
|
||||
char *escarg;
|
||||
i64 i, j, px, iStart;
|
||||
unsigned char ch;
|
||||
|
||||
if( bArgList ){
|
||||
escarg = getTextArg(pArgList);
|
||||
}else{
|
||||
escarg = va_arg(ap,char*);
|
||||
}
|
||||
iStart = sqlite3_str_length(pAccum);
|
||||
if( escarg==0 ){
|
||||
if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "null", 4);
|
||||
}else{
|
||||
if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
|
||||
px = precision;
|
||||
testcase( px==0 );
|
||||
if( px<0 ){
|
||||
px = 0x7fffffff;
|
||||
}else if( flag_altform2 ){
|
||||
/* Convert precision from code-points to bytes */
|
||||
for(i=0; i<px && escarg[i]; i++){
|
||||
if( (escarg[i]&0xc0)==0x80 ) px++;
|
||||
}
|
||||
if( i==px ){
|
||||
while( (escarg[px]&0xc0)==0x80 ) px++;
|
||||
}
|
||||
}
|
||||
for(i=j=0; i<px; i++){
|
||||
if( (ch = ((u8*)escarg)[i])<=0x1f || ch=='"' || ch=='\\' ){
|
||||
if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
|
||||
j = i+1;
|
||||
if( ch==0 ) break;
|
||||
sqlite3_str_appendchar(pAccum, 1, '\\');
|
||||
if( ch>0x1f ){
|
||||
sqlite3_str_appendchar(pAccum, 1, ch);
|
||||
}else if( ((1u<<ch)&0x3700)!=0 ){
|
||||
ch = "btn?fr"[ch-8];
|
||||
sqlite3_str_appendchar(pAccum, 1, ch);
|
||||
}else{
|
||||
sqlite3_str_append(pAccum, "u00", 3);
|
||||
sqlite3_str_appendchar(pAccum, 1, aHex[ch>>4]);
|
||||
sqlite3_str_appendchar(pAccum, 1, aHex[ch&0xf]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
|
||||
if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
|
||||
}
|
||||
if( width>0 && sqlite3_str_errcode(pAccum)==SQLITE_OK ){
|
||||
sqlite3_int64 n = sqlite3_str_length(pAccum) - iStart;
|
||||
sqlite3_int64 len = n;
|
||||
char *zz;
|
||||
if( flag_altform2 && n>0 ){
|
||||
zz = sqlite3_str_value(pAccum);
|
||||
for(i=iStart; zz[i]; i++){
|
||||
if( (zz[i]&0xc0)==0x80 ) len--;
|
||||
}
|
||||
}
|
||||
if( width>len ){
|
||||
sqlite3_int64 sp = width-len;
|
||||
assert( sp>0 && sp<0x7fffffff );
|
||||
sqlite3_str_appendchar(pAccum, (int)sp, ' ');
|
||||
if( !flag_leftjustify
|
||||
&& n>0
|
||||
&& sqlite3_str_errcode(pAccum)==0
|
||||
){
|
||||
zz = sqlite3_str_value(pAccum);
|
||||
zz += iStart;
|
||||
memmove(zz+sp, zz, n);
|
||||
memset(zz, ' ', sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case etESCAPE_q: /* %q: Escape ' characters */
|
||||
case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
|
||||
case etESCAPE_w: { /* %w: Escape " characters */
|
||||
@@ -958,7 +1040,7 @@ void sqlite3_str_vappendf(
|
||||
bufpt[j++] = '0';
|
||||
bufpt[j++] = '0';
|
||||
bufpt[j++] = ch>=0x10 ? '1' : '0';
|
||||
bufpt[j++] = "0123456789abcdef"[ch&0xf];
|
||||
bufpt[j++] = aHex[ch&0xf];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@@ -1322,7 +1404,7 @@ void sqlite3_str_reset(StrAccum *p){
|
||||
** of its content, all in one call.
|
||||
*/
|
||||
void sqlite3_str_free(sqlite3_str *p){
|
||||
if( p ){
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
sqlite3_str_reset(p);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
+39
-11
@@ -774,6 +774,7 @@ static int lookupName(
|
||||
pExpr->op = TK_FUNCTION;
|
||||
pExpr->u.zToken = "coalesce";
|
||||
pExpr->x.pList = pFJMatch;
|
||||
pExpr->affExpr = SQLITE_AFF_DEFER;
|
||||
cnt = 1;
|
||||
goto lookupname_end;
|
||||
}else{
|
||||
@@ -836,9 +837,7 @@ lookupname_end:
|
||||
if( cnt==1 ){
|
||||
assert( pNC!=0 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pParse->db->xAuth
|
||||
&& (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
|
||||
){
|
||||
if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
|
||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||
}
|
||||
#endif
|
||||
@@ -942,6 +941,26 @@ static int exprProbability(Expr *p){
|
||||
return (int)(r*134217728.0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the EP_SubtArg property on every expression inside of
|
||||
** pList. If any subexpression is actually a subquery, then
|
||||
** also set the EP_SubtArg property on the first result-set
|
||||
** column of that subquery.
|
||||
*/
|
||||
static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
|
||||
int nn, ii;
|
||||
nn = pList ? pList->nExpr : 0;
|
||||
for(ii=0; ii<nn; ii++){
|
||||
Expr *pExpr = pList->a[ii].pExpr;
|
||||
ExprSetProperty(pExpr, EP_SubtArg);
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
assert( pExpr->x.pSelect!=0 );
|
||||
resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is callback for sqlite3WalkExpr().
|
||||
**
|
||||
@@ -1186,10 +1205,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|
||||
|| ExprHasProperty(pExpr, EP_SubtArg)
|
||||
){
|
||||
int ii;
|
||||
for(ii=0; ii<n; ii++){
|
||||
ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
|
||||
}
|
||||
resolveSetExprSubtypeArg(pList);
|
||||
}
|
||||
|
||||
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
||||
@@ -1219,8 +1235,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* Internal-use-only functions are disallowed unless the
|
||||
** SQL is being compiled using sqlite3NestedParse() or
|
||||
** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
|
||||
** used to activate internal functions for testing purposes */
|
||||
no_such_func = 1;
|
||||
** used to activate internal functions for testing purposes.
|
||||
**
|
||||
** The 2 value for no_such_func means that the function is
|
||||
** an internal-use-only function which should be treated as a
|
||||
** non-existant function for name resolution purposes.
|
||||
*/
|
||||
no_such_func = 2;
|
||||
pDef = 0;
|
||||
}else
|
||||
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
|
||||
@@ -1264,9 +1285,16 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
is_agg = 0;
|
||||
}
|
||||
#endif
|
||||
else if( no_such_func && pParse->db->init.busy==0
|
||||
else if( no_such_func
|
||||
&& (pParse->db->init.busy==0 ||
|
||||
(no_such_func==2 && pParse->db->init.busy==2))
|
||||
/* Suppress "no such function" errors when reading
|
||||
** the sqlite_schema table. Except, do raise the error
|
||||
** if init.busy is 2, meaning the schema parse is due
|
||||
** to an ALTER TABLE ADD COLUMN statement, and the function
|
||||
** is an internal-use-only function (no_such_func==2). */
|
||||
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
&& pParse->explain==0
|
||||
&& pParse->explain==0
|
||||
#endif
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
|
||||
|
||||
+1
-1
@@ -7324,6 +7324,7 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
|
||||
&& ALWAYS(p->pSrc!=0)
|
||||
&& p->pSrc->nSrc<BMS
|
||||
&& (p->pLimit==0 || p->pLimit->pRight==0)
|
||||
){
|
||||
if( pWhere->op==TK_AND ){
|
||||
Expr *pRight = pWhere->pRight;
|
||||
@@ -7371,7 +7372,6 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
existsToJoin(pParse, p, pSubWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+838
-197
File diff suppressed because it is too large
Load Diff
+2
-3
@@ -2992,7 +2992,7 @@ int sqlite3_is_interrupted(sqlite3*);
|
||||
** then the return value from sqlite3_complete16() will be non-zero
|
||||
** regardless of whether or not the input SQL is complete.)^
|
||||
**
|
||||
** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)
|
||||
** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
|
||||
** must be a zero-terminated UTF-8 string.
|
||||
**
|
||||
** The input to [sqlite3_complete16()] must be a zero-terminated
|
||||
@@ -4054,8 +4054,7 @@ int sqlite3_open_v2(
|
||||
**
|
||||
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
|
||||
** 64-bit signed integer and returns that integer, or D if P does not
|
||||
** exist. If the value of P is something other than an integer, then
|
||||
** zero is returned.
|
||||
** exist or ff the value of P is something other than an integer.
|
||||
**
|
||||
** The sqlite3_uri_key(F,N) returns a pointer to the name (not
|
||||
** the value) of the N-th query parameter for filename F, or a NULL
|
||||
|
||||
@@ -376,6 +376,8 @@ struct sqlite3_api_routines {
|
||||
void (*str_free)(sqlite3_str*);
|
||||
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
|
||||
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
|
||||
/* Version 3.54.0 and later */
|
||||
sqlite3_int64 (*incomplete)(const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -719,6 +721,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_str_free sqlite3_api->str_free
|
||||
#define sqlite3_carray_bind sqlite3_api->carray_bind
|
||||
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
|
||||
/* Version 3.54.0 and later */
|
||||
#define sqlite3_incomplete sqlite3_api->incomplete
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+63
-4
@@ -202,7 +202,7 @@
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
|
||||
** Reuse the STATIC_VFS1 for mutex access to sqlite3_temp_directory.
|
||||
*/
|
||||
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
|
||||
|
||||
@@ -1700,7 +1700,7 @@ struct sqlite3 {
|
||||
struct sqlite3InitInfo { /* Information used during initialization */
|
||||
Pgno newTnum; /* Rootpage of table being initialized */
|
||||
u8 iDb; /* Which db file is being initialized */
|
||||
u8 busy; /* TRUE if currently initializing */
|
||||
u8 busy; /* TRUE if initing. 2 if due to ADD COLUMN */
|
||||
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
||||
unsigned imposterTable : 2; /* Building an imposter table */
|
||||
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
||||
@@ -4251,7 +4251,7 @@ typedef struct {
|
||||
#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
|
||||
#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
|
||||
#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
|
||||
#define INITFLAG_AlterDropCons 0x0004 /* Reparse after an ADD COLUMN */
|
||||
#define INITFLAG_AlterDropCons 0x0004 /* Reparse after a DROP CONSTRAINT */
|
||||
|
||||
/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
|
||||
** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
|
||||
@@ -4612,6 +4612,57 @@ Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
** advance zIn to point to the first byte of the next UTF-8 character.
|
||||
**
|
||||
** # Dividing malformed UTF-8 into characters (tag-20260418-01)
|
||||
**
|
||||
** If a text input is malformed UTF-8, SQLite does not make any guarantees
|
||||
** about how the bytes are divided up into characters. The system promises
|
||||
** to not overflow an array or cause other memory errors when presented
|
||||
** with malformed UTF-8. And it promises to preserve the specific
|
||||
** sequence of bytes as long as no conversion occur. But beyond that,
|
||||
** there are no guarantees. Results can vary from one version to the
|
||||
** next.
|
||||
**
|
||||
** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
|
||||
** into characters. The length() and substr() SQL functions use a
|
||||
** different technique when searching across multiple characters, a
|
||||
** technique that exchanges a subtraction for comparison of z and results
|
||||
** in faster machine code on some compilers and architectures. The code
|
||||
** in substr() to skip over p1 characters goes something like this:
|
||||
**
|
||||
** for( ; p1>0; p1--){
|
||||
** // vvvv--- tag-20260418-01
|
||||
** if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
** z++;
|
||||
** }else if( z[0]==0 ){
|
||||
** break;
|
||||
** }else{
|
||||
** do{ z++; }while( (z[0]&0xc0)==0x80 );
|
||||
** }
|
||||
** }
|
||||
**
|
||||
** In valid UTF-8, multibyte characters always begin with a byte with the
|
||||
** two most significant bits set and that is followed by one or more bytes
|
||||
** for which the two most significant bits are 10. In other words:
|
||||
**
|
||||
** First byte: (BYTE & 0xc0)==0xc0
|
||||
** Following bytes: (BYTE & 0xc0)==0x80
|
||||
**
|
||||
** What to do if the input byte sequence contain a "following byte" that
|
||||
** is not preceded by a "first byte"? How many characters are in the
|
||||
** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
|
||||
**
|
||||
** If you use the macro below, the answer will be 4. If you use the code
|
||||
** snippet demonstrated at tag-20260418-01, then answer is 3. If you
|
||||
** use a variant of tag-20260418-01 where the constant of comparison is
|
||||
** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
|
||||
** that because the input is malformed UTF-8, so is no "correct" answer.
|
||||
** SQLite is free to use either value.
|
||||
**
|
||||
** It turns out that GCC 13.3.0 is able to generate faster code (at least
|
||||
** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
|
||||
** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
|
||||
** So the (0x80-1) constant is used for substr() and length().
|
||||
*/
|
||||
#define SQLITE_SKIP_UTF8(zIn) { \
|
||||
if( (*(zIn++))>=0xc0 ){ \
|
||||
@@ -5453,7 +5504,15 @@ void sqlite3AlterFunctions(void);
|
||||
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
||||
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
||||
void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
|
||||
void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
|
||||
void sqlite3AlterAddConstraint(
|
||||
Parse *pParse, /* Parse context */
|
||||
SrcList *pSrc, /* Table to add constraint to */
|
||||
Token *pFirst, /* First token of new constraint */
|
||||
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
||||
const char *zExpr, /* Text of CHECK expression */
|
||||
int nExpr, /* Size of pExpr in bytes */
|
||||
Expr *pExpr /* The parsed CHECK expression */
|
||||
);
|
||||
void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
|
||||
i64 sqlite3GetToken(const unsigned char *, int *);
|
||||
void sqlite3NestedParse(Parse*, const char*, ...);
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ static int SQLITE_TCLAPI test_exec_hex(
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
zHex = argv[2];
|
||||
for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
|
||||
if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
|
||||
if( zHex[j]=='%' && zHex[j+1] && zHex[j+2] ){
|
||||
zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
|
||||
j += 2;
|
||||
}else{
|
||||
|
||||
+13
-8
@@ -465,15 +465,20 @@ u8 sqlite3StrIHash(const char *z){
|
||||
return h;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_DISABLE_INTRINSIC) \
|
||||
&& (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || \
|
||||
(defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
|
||||
#define SQLITE_USE_UINT128
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Two inputs are multiplied to get a 128-bit result. Write the
|
||||
** lower 64-bits of the result into *pLo, and return the high-order
|
||||
** 64 bits.
|
||||
*/
|
||||
static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
*pLo = (u64)r;
|
||||
return (u64)(r>>64);
|
||||
@@ -507,9 +512,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
** The lower 64 bits of A*B are discarded.
|
||||
*/
|
||||
static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
r += ((__uint128_t)aLo * b) >> 32;
|
||||
*pLo = (r>>32)&0xffffffff;
|
||||
@@ -547,6 +550,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SQLITE_USE_UINT128
|
||||
|
||||
/*
|
||||
** Return a u64 with the N-th bit set.
|
||||
*/
|
||||
@@ -785,7 +790,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
u64 pwr10h, x, hi, lo, sticky, u, m;
|
||||
double r;
|
||||
if( p<POWERSOF10_FIRST ) return 0.0;
|
||||
if( p>POWERSOF10_LAST ) return INFINITY;
|
||||
if( p>POWERSOF10_LAST ) return (double)INFINITY;
|
||||
b = 64 - countLeadingZeros(d);
|
||||
lp = pwr10to2(p);
|
||||
e = 53 - b - lp;
|
||||
@@ -815,7 +820,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
e -= adj;
|
||||
}
|
||||
m = (u + 1 + ((u>>2)&1)) >> 2;
|
||||
if( e<=(-972) ) return INFINITY;
|
||||
if( e<=(-972) ) return (double)INFINITY;
|
||||
if((m & U64_BIT(52)) != 0){
|
||||
m = (m & ~U64_BIT(52)) | ((u64)(1075-e)<<52);
|
||||
}
|
||||
|
||||
+67
-11
@@ -437,10 +437,12 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
|
||||
int eType = sqlite3_value_type(pVal);
|
||||
if( eType==SQLITE_TEXT ){
|
||||
Mem *pMem = (Mem*)pVal;
|
||||
assert( pMem->db!=0 );
|
||||
sqlite3_mutex_enter(pMem->db->mutex);
|
||||
#if SQLITE_THREADSAFE>0
|
||||
sqlite3_mutex *pMutex = pMem->db ? pMem->db->mutex : 0;
|
||||
#endif
|
||||
sqlite3_mutex_enter(pMutex);
|
||||
applyNumericAffinity(pMem, 0);
|
||||
sqlite3_mutex_leave(pMem->db->mutex);
|
||||
sqlite3_mutex_leave(pMutex);
|
||||
eType = sqlite3_value_type(pVal);
|
||||
}
|
||||
return eType;
|
||||
@@ -708,7 +710,6 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** For OP_Column, factor out the case where content is loaded from
|
||||
** overflow pages, so that the code to implement this case is separate
|
||||
@@ -794,6 +795,40 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
|
||||
** open on an index. If the current index entry matches the blob value in
|
||||
** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
|
||||
**
|
||||
** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
|
||||
** case as well.
|
||||
*/
|
||||
static SQLITE_NOINLINE int vdbeIndexKeyCompare(
|
||||
BtCursor *pCsr, /* Cursor to compare key to */
|
||||
Mem *pMem,
|
||||
int *pRc
|
||||
){
|
||||
int ret = 0;
|
||||
u32 nKey = 0;
|
||||
|
||||
assert( pMem->flags & (MEM_Blob|MEM_Null) );
|
||||
nKey = sqlite3BtreePayloadSize(pCsr);
|
||||
if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
|
||||
/* This code could just use sqlite3BtreePayloadFetch(). But calling that
|
||||
** function here apparently prevents compilers from inlining it in other,
|
||||
** more performance critical, places. So this code uses
|
||||
** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
|
||||
** handles the case where the index record uses overflow pages. */
|
||||
Mem m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
*pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
|
||||
ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
|
||||
sqlite3VdbeMemReleaseMalloc(&m);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** Send a "statement aborts" message to the error log.
|
||||
*/
|
||||
@@ -6622,15 +6657,20 @@ case OP_SorterInsert: { /* in2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxDelete P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P2@P3]
|
||||
/* Opcode: IdxDelete P1 P2 P3 P4 P5
|
||||
** Synopsis: key=r[P2@P5]
|
||||
**
|
||||
** The content of P3 registers starting at register P2 form
|
||||
** The content of P5 registers starting at register P2 form
|
||||
** an unpacked index key. This opcode removes that entry from the
|
||||
** index opened by cursor P1.
|
||||
**
|
||||
** P4 is a pointer to an Index structure.
|
||||
**
|
||||
** If P3 is non-zero, it is the register number of a register holding
|
||||
** a record that will be inserted into this index. If that record is
|
||||
** identical to the one that would be deleted by this instruction,
|
||||
** skip the delete and set register P3 to NULL.
|
||||
**
|
||||
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
|
||||
** and not in writable_schema mode.
|
||||
*/
|
||||
@@ -6640,8 +6680,8 @@ case OP_IdxDelete: {
|
||||
int res;
|
||||
UnpackedRecord r;
|
||||
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
|
||||
assert( pOp->p5>0 );
|
||||
assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
@@ -6650,7 +6690,7 @@ case OP_IdxDelete: {
|
||||
pCrsr = pC->uc.pCursor;
|
||||
assert( pCrsr!=0 );
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = (u16)pOp->p3;
|
||||
r.nField = pOp->p5;
|
||||
r.default_rc = 0;
|
||||
r.aMem = &aMem[pOp->p2];
|
||||
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
|
||||
@@ -6669,6 +6709,13 @@ case OP_IdxDelete: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
|
||||
if( rc ) goto abort_due_to_error;
|
||||
sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
assert( pC->deferredMoveto==0 );
|
||||
@@ -7102,12 +7149,19 @@ case OP_SqlExec: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ParseSchema P1 * * P4 *
|
||||
/* Opcode: ParseSchema P1 * * P4 P5
|
||||
**
|
||||
** Read and parse all entries from the schema table of database P1
|
||||
** that match the WHERE clause P4. If P4 is a NULL pointer, then the
|
||||
** entire schema for P1 is reparsed.
|
||||
**
|
||||
** When P4 is NULL, the P5 value is used as the mFlags argument
|
||||
** to sqlite3InitOne(). In other words, P5 should be a mask composed
|
||||
** of INITFLAG_* values.
|
||||
**
|
||||
** The P4==0 case is only used by ALTER TABLE and P5!=0 for all such
|
||||
** cases. For uses other than ALTER TABLE, P4<>0 and P5==0.
|
||||
**
|
||||
** This opcode invokes the parser to create a new virtual machine,
|
||||
** then runs the new virtual machine. It is thus a re-entrant opcode.
|
||||
*/
|
||||
@@ -7135,6 +7189,7 @@ case OP_ParseSchema: {
|
||||
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
if( pOp->p4.z==0 ){
|
||||
assert( pOp->p5!=0 );
|
||||
sqlite3SchemaClear(db->aDb[iDb].pSchema);
|
||||
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
|
||||
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
|
||||
@@ -7143,6 +7198,7 @@ case OP_ParseSchema: {
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
assert( pOp->p5==0 );
|
||||
zSchema = LEGACY_SCHEMA_TABLE;
|
||||
initData.db = db;
|
||||
initData.iDb = iDb;
|
||||
|
||||
+11
-2
@@ -556,11 +556,21 @@ void sqlite3VdbeExplainPop(Parse *pParse){
|
||||
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
|
||||
** as having been used.
|
||||
**
|
||||
** The zWhere string must have been obtained from sqlite3_malloc().
|
||||
** zWhere is a WHERE clause that defines which entries of the schema
|
||||
** to reparse. If zWhere==0, that means all entries. p5 is a mask
|
||||
** of INITFLAG_* values for the parse.
|
||||
**
|
||||
** In the current usage, the following are always true:
|
||||
**
|
||||
** ALTER TABLE: zWhere==0, p5!=0
|
||||
** Otherwise: zWhere!=0, p5==0
|
||||
**
|
||||
** The zWhere string must have been obtained from sqlite3DbMalloc().
|
||||
** This routine will take ownership of the allocated memory.
|
||||
*/
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
|
||||
int j;
|
||||
assert( p5==0 || zWhere==0 );
|
||||
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
|
||||
sqlite3VdbeChangeP5(p, p5);
|
||||
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
|
||||
@@ -1900,7 +1910,6 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
#if VDBE_DISPLAY_P4
|
||||
/*
|
||||
** Compute a string that describes the P4 parameter for an opcode.
|
||||
** Use zTemp for any required temporary buffer space.
|
||||
*/
|
||||
char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
|
||||
char *zP4 = 0;
|
||||
|
||||
+10
-24
@@ -163,7 +163,7 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
|
||||
** If the ONEPASS optimization is used (if this routine returns true)
|
||||
** then also write the indices of open cursors used by ONEPASS
|
||||
** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
|
||||
** table and iaCur[1] gets the cursor used by an auxiliary index.
|
||||
** table and aiCur[1] gets the cursor used by an auxiliary index.
|
||||
** Either value may be -1, indicating that cursor is not used.
|
||||
** Any cursors returned will have been opened for writing.
|
||||
**
|
||||
@@ -3088,9 +3088,10 @@ static void whereLoopOutputAdjust(
|
||||
&& (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
|
||||
){
|
||||
Expr *pRight = pOpExpr->pRight;
|
||||
Parse *pParse = pWC->pWInfo->pParse;
|
||||
int k = 0;
|
||||
testcase( pOpExpr->op==TK_IS );
|
||||
if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
|
||||
if( sqlite3ExprIsInteger(pRight, &k, pParse) && k>=(-1) && k<=1 ){
|
||||
k = 10;
|
||||
}else{
|
||||
k = 20;
|
||||
@@ -3187,7 +3188,8 @@ static int whereRangeVectorLen(
|
||||
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
|
||||
if( aff!=idxaff ) break;
|
||||
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
|
||||
if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
||||
if( pColl==0 ) break;
|
||||
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
|
||||
}
|
||||
@@ -7583,27 +7585,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists
|
||||
&& (i==pWInfo->nLevel-1
|
||||
|| pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
|
||||
){
|
||||
/* This is an EXISTS-to-JOIN optimization which is either the
|
||||
** inner-most loop, or the inner-most of a group of nested
|
||||
** EXISTS-to-JOIN optimization loops. If this loop sees a successful
|
||||
** row, it should break out of itself as well as other EXISTS-to-JOIN
|
||||
** loops in which is is directly nested. */
|
||||
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
|
||||
while( nOuter<i ){
|
||||
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
|
||||
nOuter++;
|
||||
}
|
||||
testcase( nOuter>0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
|
||||
if( nOuter ){
|
||||
VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
|
||||
}else{
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists ){
|
||||
/* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
|
||||
** successful row, it should break out of itself. */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
||||
if( pLevel->op!=OP_Noop ){
|
||||
|
||||
+9
-2
@@ -2297,7 +2297,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
||||
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
||||
*/
|
||||
if( pWInfo->nLevel>1 ){
|
||||
if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
|
||||
int nNotReady; /* The number of notReady tables */
|
||||
SrcItem *origSrc; /* Original list of tables */
|
||||
nNotReady = pWInfo->nLevel - iLevel - 1;
|
||||
@@ -2310,6 +2310,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
for(k=1; k<=nNotReady; k++){
|
||||
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
|
||||
}
|
||||
|
||||
/* Clear the fromExists flag on the OR-optimized table entry so that
|
||||
** the calls to sqlite3WhereEnd() do not code early-exits after the
|
||||
** first row is visited. The early exit applies to this table's
|
||||
** overall loop - including the multiple OR branches and any WHERE
|
||||
** conditions not passed to the sub-loops - not to the sub-loops. */
|
||||
pOrTab->a[0].fg.fromExists = 0;
|
||||
}else{
|
||||
pOrTab = pWInfo->pTabList;
|
||||
}
|
||||
@@ -2553,7 +2560,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
assert( pLevel->op==OP_Return );
|
||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( !untestedTerms ) disableTerm(pLevel, pTerm);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
||||
|
||||
+3
-8
@@ -954,8 +954,7 @@ static void exprAnalyzeOrTerm(
|
||||
** 3. Not originating in the ON clause of an OUTER JOIN
|
||||
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
|
||||
** 5. The affinities of A and B must be compatible
|
||||
** 6a. Both operands use the same collating sequence OR
|
||||
** 6b. The overall collating sequence is BINARY
|
||||
** 6. Both operands use the same collating sequence
|
||||
** 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
|
||||
@@ -963,7 +962,6 @@ static void exprAnalyzeOrTerm(
|
||||
*/
|
||||
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
char aff1, aff2;
|
||||
CollSeq *pColl;
|
||||
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
|
||||
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
|
||||
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
|
||||
@@ -981,10 +979,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
||||
){
|
||||
return 0; /* (5) */
|
||||
}
|
||||
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
|
||||
if( !sqlite3IsBinary(pColl)
|
||||
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
|
||||
){
|
||||
if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
|
||||
return 0; /* (6) */
|
||||
}
|
||||
return 1;
|
||||
@@ -1316,7 +1311,7 @@ static void exprAnalyze(
|
||||
/* Analyze a term that is composed of two or more subterms connected by
|
||||
** an OR operator.
|
||||
*/
|
||||
else if( pExpr->op==TK_OR ){
|
||||
else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
|
||||
assert( pWC->op==TK_AND );
|
||||
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
|
||||
+10
-1
@@ -981,6 +981,15 @@ do_execsql_test alter-21.4 {
|
||||
SELECT name, type FROM sqlite_schema ORDER BY name;
|
||||
} {r2 trigger t1 table t99 table}
|
||||
|
||||
|
||||
# 2026-05-12 Verify that ADD COLUMN cannot insert internal-use-only
|
||||
# functions.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test alter-22.1 {
|
||||
CREATE TABLE t1(a,b);
|
||||
}
|
||||
do_catchsql_test alter-22.2 {
|
||||
ALTER TABLE t1 ADD COLUMN c CHECK( if(c<10,1,sqlite_fail('bummer',1)));
|
||||
} {1 {error in table t1 after add column: no such function: sqlite_fail}}
|
||||
|
||||
finish_test
|
||||
|
||||
+15
-1
@@ -438,5 +438,19 @@ do_execsql_test 9.2.5 {
|
||||
SELECT sql FROM aux.sqlite_schema WHERE name='t2';
|
||||
} {{CREATE TABLE t2(x, y, z)}}
|
||||
|
||||
finish_test
|
||||
# Cannot add constraints the use internal functions.
|
||||
# Forum post 2026-05-10T01:11:28Z
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE t1(x,y,z);
|
||||
INSERT INTO t1 VALUES(1,'two',x'3333');
|
||||
}
|
||||
do_catchsql_test 10.2 {
|
||||
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( sqlite_drop_column(22,'CREATE TABLE a(b,c)', 0));
|
||||
} {1 {no such function: sqlite_drop_column}}
|
||||
do_catchsql_test 10.3 {
|
||||
ALTER TABLE t1 ADD CONSTRAINT c1 CHECK( x>#2 );
|
||||
} {1 {near "#2": syntax error}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -243,5 +243,53 @@ do_execsql_test 11.2.3 {
|
||||
do_execsql_test 11.2.2 {ALTER TABLE t2 ALTER b SET NOT NULL --new cons
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
ALTER TABLE Test DROP CONSTRAINT BooleanZeroOrOne
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.3 {
|
||||
DROP TABLE Test;
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.4 {
|
||||
ALTER TABLE Test DROP CONSTRAINT "BooleanZeroOrOne"
|
||||
}
|
||||
|
||||
do_execsql_test 12.5 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.6 {
|
||||
CREATE TABLE t1(a, b CONSTRAINT "a""b" CHECK (b IS NOT NULL));
|
||||
}
|
||||
|
||||
do_execsql_test 12.7 {
|
||||
ALTER TABLE t1 DROP CONSTRAINT "a""b"
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -114,4 +114,20 @@ do_execsql_test amatch1-2.22 {
|
||||
WHERE word MATCH 'joxxph' AND distance<300;
|
||||
} {}
|
||||
|
||||
# Forum post 2026-05-09T05:48:28Z
|
||||
reset_db
|
||||
load_static_extension db amatch
|
||||
do_execsql_test amatch1-3.0 {
|
||||
CREATE TABLE cost(iLang,cFrom,cTo,Cost);
|
||||
INSERT INTO cost VALUES(0,'?','?',1);
|
||||
CREATE TABLE vocab(word TEXT PRIMARY KEY);
|
||||
CREATE VIRTUAL TABLE am USING approximate_match(
|
||||
vocabulary_table=vocab,
|
||||
vocabulary_word=word,
|
||||
edit_distances=cost
|
||||
);
|
||||
INSERT INTO vocab(word) VALUES(format('%.81c','a'));
|
||||
SELECT length(word) FROM am WHERE word MATCH format('%.81c','a');
|
||||
} {81}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -415,7 +415,7 @@ do_test analyze3-3.4.1 {
|
||||
do_test analyze3-3.4.2 {
|
||||
sqlite3_bind_text $S 1 "abc" 3
|
||||
sqlite3_expired $S
|
||||
} {0}
|
||||
} {1}
|
||||
do_test analyze3-3.4.3 {
|
||||
sqlite3_bind_text $S 2 "def" 3
|
||||
sqlite3_expired $S
|
||||
|
||||
@@ -157,4 +157,34 @@ SQLITE_SELECT {} {} {} v2
|
||||
}
|
||||
db2 close
|
||||
|
||||
do_test auth2-3.1 {
|
||||
set ::authargs {}
|
||||
db eval {
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
}
|
||||
set ::authargs
|
||||
} {SQLITE_INSERT t2 {} main {}
|
||||
SQLITE_SELECT {} {} {} {}
|
||||
SQLITE_READ t1 a main {}
|
||||
SQLITE_READ t1 b main {}
|
||||
SQLITE_READ t1 c main {}
|
||||
}
|
||||
proc auth {op a0 a1 a2 a3} {
|
||||
global authargs
|
||||
append authargs "$op $a0 [list $a1] [list $a2] [list $a3]\n"
|
||||
if {$op eq "SQLITE_READ" && $a0 eq "t1" && $a1 eq "b"} {
|
||||
return SQLITE_IGNORE
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
db null NULL
|
||||
set authargs {}
|
||||
do_execsql_test auth2-3.2 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(1,2,3),('a','b','c');
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
} {1 NULL 3 a NULL c}
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user