Compare commits

..

6 Commits

Author SHA1 Message Date
drh 60405cd15c Version 3.34.1
FossilOrigin-Name: 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f
2021-01-20 14:10:07 +00:00
drh b08dbd0f28 Fix an issue with sha3_query() when the first argument contains blank
SQL statements.

FossilOrigin-Name: a1a7a5f238fcfdcd56faba063e381258c9e2944d9b02b31d402a4207a607fc1c
2021-01-19 20:38:13 +00:00
drh 00a0b135ec Bump the version number to 3.34.1.
FossilOrigin-Name: cea7d0f8a3d9b3f5caae63ad555de25b53c577fc8e004127ec18cc7f0c6f1714
2021-01-19 20:17:46 +00:00
drh 90ab71bdc8 Fix a problem handling sub-queries with both a correlated WHERE clause and a "HAVING 0" clause where the parent query is itself an aggregate.
The problem was apparently introduced by check-in [6e6b3729e0549de0]

FossilOrigin-Name: 30a4c323650cc9498a6dacd1760dd5170d7cc7848c4e96ff6bd64da365f96366
2021-01-19 20:09:44 +00:00
drh 4dca7d4cfb Prevent potential segfault in the sqlite-expert idxPopulateStat1 context cleanup code.
FossilOrigin-Name: 69e31d52b2a7bde1ed72bc7b927ff451139fbc76504e750324e6368ad26b11b1
2021-01-19 20:04:37 +00:00
drh 1dc9cf947b Fix a typo in the sqlite3_free_filename() documentation.
FossilOrigin-Name: 7316ee19c590854545019a56799968143109929049424a8cc1dcf9624f98a544
2020-12-16 13:20:15 +00:00
79 changed files with 944 additions and 4511 deletions
-3
View File
@@ -1378,9 +1378,6 @@ wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
startup$(TEXE): $(TOP)/test/startup.c sqlite3.c
$(CC) -Os -g -DSQLITE_THREADSAFE=0 -o $@ $(TOP)/test/startup.c sqlite3.c $(TLIBS)
KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
-3
View File
@@ -380,9 +380,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
!ENDIF
# Always enable math functions on Windows
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
# Should the rbu extension be enabled? If so, add compilation options
# to enable it.
#
+1 -1
View File
@@ -1 +1 @@
3.35.0
3.34.1
+1 -3
View File
@@ -87,9 +87,7 @@ AC_SUBST(READLINE_LIBS)
AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
[--enable-threadsafe], [build a thread-safe library [default=yes]])],
[], [enable_threadsafe=yes])
if test x"$enable_threadsafe" == "xno"; then
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0"
else
if test x"$enable_threadsafe" != "xno"; then
BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
AC_SEARCH_LIBS(pthread_create, pthread)
AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
Vendored
+23 -100
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.35.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.34.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.35.0'
PACKAGE_STRING='sqlite 3.35.0'
PACKAGE_VERSION='3.34.1'
PACKAGE_STRING='sqlite 3.34.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -903,7 +903,6 @@ with_readline_inc
enable_debug
enable_amalgamation
enable_load_extension
enable_math
enable_memsys5
enable_memsys3
enable_all
@@ -1467,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.35.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.34.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1532,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.35.0:";;
short | recursive ) echo "Configuration of sqlite 3.34.1:";;
esac
cat <<\_ACEOF
@@ -1558,7 +1557,6 @@ Optional Features:
separately
--disable-load-extension
Disable loading of external extensions
--disable-math Disable math functions
--enable-memsys5 Enable MEMSYS5
--enable-memsys3 Enable MEMSYS3
--enable-all Enable FTS4, FTS5, Geopoly, JSON, RTree, Sessions
@@ -1660,7 +1658,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.35.0
sqlite configure 3.34.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2079,7 +2077,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.35.0, which was
It was created by sqlite $as_me 3.34.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3937,13 +3935,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3940: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3938: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3943: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3941: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3946: output\"" >&5)
(eval echo "\"\$as_me:3944: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5149,7 +5147,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5152 "configure"' > conftest.$ac_ext
echo '#line 5150 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6674,11 +6672,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6677: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6675: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6681: \$? = $ac_status" >&5
echo "$as_me:6679: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7013,11 +7011,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7016: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7014: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7020: \$? = $ac_status" >&5
echo "$as_me:7018: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7118,11 +7116,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7121: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7119: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7125: \$? = $ac_status" >&5
echo "$as_me:7123: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7173,11 +7171,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7176: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7174: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7180: \$? = $ac_status" >&5
echo "$as_me:7178: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9553,7 +9551,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9556 "configure"
#line 9554 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9649,7 +9647,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9652 "configure"
#line 9650 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11413,81 +11411,6 @@ else
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi
##########
# Do we want to support math functions
#
# Check whether --enable-math was given.
if test "${enable_math+set}" = set; then :
enableval=$enable_math;
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support math functions" >&5
$as_echo_n "checking whether to support math functions... " >&6; }
if test "$enable_math" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ceil" >&5
$as_echo_n "checking for library containing ceil... " >&6; }
if ${ac_cv_search_ceil+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ceil ();
int
main ()
{
return ceil ();
;
return 0;
}
_ACEOF
for ac_lib in '' m; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_ceil=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_ceil+:} false; then :
break
fi
done
if ${ac_cv_search_ceil+:} false; then :
else
ac_cv_search_ceil=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ceil" >&5
$as_echo "$ac_cv_search_ceil" >&6; }
ac_res=$ac_cv_search_ceil
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
fi
##########
# Do we want to support memsys3 and/or memsys5
#
@@ -12313,7 +12236,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.35.0, which was
This file was extended by sqlite $as_me 3.34.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12379,7 +12302,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.35.0
sqlite config.status 3.34.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
-14
View File
@@ -586,20 +586,6 @@ else
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
fi
##########
# Do we want to support math functions
#
AC_ARG_ENABLE(math,
AC_HELP_STRING([--disable-math],[Disable math functions]))
AC_MSG_CHECKING([whether to support math functions])
if test "$enable_math" = "no"; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
AC_SEARCH_LIBS(ceil, m)
fi
##########
# Do we want to support memsys3 and/or memsys5
#
+1 -25
View File
@@ -28,7 +28,6 @@ if {[info commands sqlite3_expert_new]==""} {
return
}
set CLI [test_binary_name sqlite3]
set CMD [test_binary_name sqlite3_expert]
@@ -368,29 +367,6 @@ do_setup_rec_test $tn.17.5 {
SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
}
do_setup_rec_test $tn.18.0 {
CREATE TABLE SomeObject (
a INTEGER PRIMARY KEY,
x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
);
} {
SELECT x FROM SomeObject;
} {
(no new indexes)
SCAN TABLE SomeObject
}
do_setup_rec_test $tn.18.1 {
CREATE TABLE SomeObject (
a INTEGER PRIMARY KEY,
x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
);
} {
SELECT * FROM SomeObject WHERE x=?;
} {
CREATE INDEX SomeObject_idx_00000078 ON SomeObject(x);
SEARCH TABLE SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
}
}
proc do_candidates_test {tn sql res} {
@@ -454,5 +430,5 @@ do_execsql_test 5.3 {
t2 t2_idx_0001295b {100 20 5}
}
finish_test
finish_test
+1 -1
View File
@@ -687,7 +687,7 @@ static int idxGetTableInfo(
char *pCsr = 0;
int nPk = 0;
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
nByte += 1 + STRLEN(zCol);
+2 -2
View File
@@ -1500,8 +1500,8 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
}
/* If the iterator is not at a real match, skip forward until it is. */
while( pRoot->bNomatch && rc==SQLITE_OK ){
assert( pRoot->bEof==0 );
while( pRoot->bNomatch ){
assert( pRoot->bEof==0 && rc==SQLITE_OK );
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
}
return rc;
+222 -292
View File
@@ -2070,10 +2070,14 @@ static void fts5SegIterNext(
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
** code is inlined. */
** code is inlined.
**
** Later: Switched back to fts5SegIterLoadNPos() because it supports
** detail=none mode. Not ideal.
*/
int nSz;
assert( p->rc==SQLITE_OK );
assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -3065,7 +3069,7 @@ static void fts5ChunkIterate(
int pgno = pSeg->iLeafPgno;
int pgnoSave = 0;
/* This function does not work with detail=none databases. */
/* This function does notmwork with detail=none databases. */
assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
@@ -3078,9 +3082,6 @@ static void fts5ChunkIterate(
fts5DataRelease(pData);
if( nRem<=0 ){
break;
}else if( pSeg->pSeg==0 ){
p->rc = FTS5_CORRUPT;
return;
}else{
pgno++;
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
@@ -3132,72 +3133,66 @@ static void fts5SegiterPoslist(
}
/*
** Parameter pPos points to a buffer containing a position list, size nPos.
** This function filters it according to pColset (which must be non-NULL)
** and sets pIter->base.pData/nData to point to the new position list.
** If memory is required for the new position list, use buffer pIter->poslist.
** Or, if the new position list is a contiguous subset of the input, set
** pIter->base.pData/nData to point directly to it.
**
** This function is a no-op if *pRc is other than SQLITE_OK when it is
** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
** before returning.
** IN/OUT parameter (*pa) points to a position list n bytes in size. If
** the position list contains entries for column iCol, then (*pa) is set
** to point to the sub-position-list for that column and the number of
** bytes in it returned. Or, if the argument position list does not
** contain any entries for column iCol, return 0.
*/
static int fts5IndexExtractCol(
const u8 **pa, /* IN/OUT: Pointer to poslist */
int n, /* IN: Size of poslist in bytes */
int iCol /* Column to extract from poslist */
){
int iCurrent = 0; /* Anything before the first 0x01 is col 0 */
const u8 *p = *pa;
const u8 *pEnd = &p[n]; /* One byte past end of position list */
while( iCol>iCurrent ){
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
** not part of a varint. Note that it is not possible for a negative
** or extremely large varint to occur within an uncorrupted position
** list. So the last byte of each varint may be assumed to have a clear
** 0x80 bit. */
while( *p!=0x01 ){
while( *p++ & 0x80 );
if( p>=pEnd ) return 0;
}
*pa = p++;
iCurrent = *p++;
if( iCurrent & 0x80 ){
p--;
p += fts5GetVarint32(p, iCurrent);
}
}
if( iCol!=iCurrent ) return 0;
/* 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 );
}
return p - (*pa);
}
static void fts5IndexExtractColset(
int *pRc,
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
Fts5Iter *pIter
Fts5Buffer *pBuf /* Output buffer */
){
if( *pRc==SQLITE_OK ){
const u8 *p = pPos;
const u8 *aCopy = p;
const u8 *pEnd = &p[nPos]; /* One byte past end of position list */
int i = 0;
int iCurrent = 0;
if( pColset->nCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
return;
}
while( 1 ){
while( pColset->aiCol[i]<iCurrent ){
i++;
if( i==pColset->nCol ){
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
return;
}
}
/* 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 );
}
if( pColset->aiCol[i]==iCurrent ){
if( pColset->nCol==1 ){
pIter->base.pData = aCopy;
pIter->base.nData = p-aCopy;
return;
}
fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
}
if( p==pEnd ){
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
return;
}
aCopy = p++;
iCurrent = *p++;
if( iCurrent & 0x80 ){
p--;
p += fts5GetVarint32(p, iCurrent);
int i;
fts5BufferZero(pBuf);
for(i=0; i<pColset->nCol; i++){
const u8 *pSub = pPos;
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
if( nSub ){
fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
}
}
}
}
/*
@@ -3317,9 +3312,16 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
int *pRc = &pIter->pIndex->rc;
fts5BufferZero(&pIter->poslist);
fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
if( pColset->nCol==1 ){
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
pIter->base.pData = a;
}else{
int *pRc = &pIter->pIndex->rc;
fts5BufferZero(&pIter->poslist);
fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
@@ -4802,7 +4804,7 @@ static void fts5AppendPoslist(
static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
assert( pIter->aPoslist );
if( p>=pIter->aEof ){
pIter->aPoslist = 0;
}else{
@@ -4886,20 +4888,16 @@ static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
static void fts5MergeRowidLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
int nBuf, /* Number of entries in apBuf[] */
Fts5Buffer *aBuf /* Array of other lists to merge into p1 */
Fts5Buffer *p2 /* Second list to merge */
){
int i1 = 0;
int i2 = 0;
i64 iRowid1 = 0;
i64 iRowid2 = 0;
i64 iOut = 0;
Fts5Buffer *p2 = &aBuf[0];
Fts5Buffer out;
(void)nBuf;
Fts5Buffer out;
memset(&out, 0, sizeof(out));
assert( nBuf==1 );
sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
if( p->rc ) return;
@@ -4926,213 +4924,180 @@ static void fts5MergeRowidLists(
fts5BufferFree(&out);
}
typedef struct PrefixMerger PrefixMerger;
struct PrefixMerger {
Fts5DoclistIter iter; /* Doclist iterator */
i64 iPos; /* For iterating through a position list */
int iOff;
u8 *aPos;
PrefixMerger *pNext; /* Next in docid/poslist order */
};
static void fts5PrefixMergerInsertByRowid(
PrefixMerger **ppHead,
PrefixMerger *p
){
if( p->iter.aPoslist ){
PrefixMerger **pp = ppHead;
while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
pp = &(*pp)->pNext;
}
p->pNext = *pp;
*pp = p;
}
}
static void fts5PrefixMergerInsertByPosition(
PrefixMerger **ppHead,
PrefixMerger *p
){
if( p->iPos>=0 ){
PrefixMerger **pp = ppHead;
while( *pp && p->iPos>(*pp)->iPos ){
pp = &(*pp)->pNext;
}
p->pNext = *pp;
*pp = p;
}
}
/*
** Array aBuf[] contains nBuf doclists. These are all merged in with the
** doclist in buffer p1.
** Buffers p1 and p2 contain doclists. This function merges the content
** of the two doclists together and sets buffer p1 to the result before
** returning.
**
** If an error occurs, an error code is left in p->rc. If an error has
** already occurred, this function is a no-op.
*/
static void fts5MergePrefixLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
int nBuf, /* Number of buffers in array aBuf[] */
Fts5Buffer *aBuf /* Other lists to merge in */
Fts5Buffer *p2 /* Second list to merge */
){
#define fts5PrefixMergerNextPosition(p) \
sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos);
#define FTS5_MERGE_NLIST 16
PrefixMerger aMerger[FTS5_MERGE_NLIST];
PrefixMerger *pHead = 0;
int i;
int nOut = 0;
Fts5Buffer out = {0, 0, 0};
Fts5Buffer tmp = {0, 0, 0};
i64 iLastRowid = 0;
if( p2->n ){
i64 iLastRowid = 0;
Fts5DoclistIter i1;
Fts5DoclistIter i2;
Fts5Buffer out = {0, 0, 0};
Fts5Buffer tmp = {0, 0, 0};
/* Initialize a doclist-iterator for each input buffer. Arrange them in
** a linked-list starting at pHead in ascending order of rowid. Avoid
** linking any iterators already at EOF into the linked list at all. */
assert( nBuf+1<=sizeof(aMerger)/sizeof(aMerger[0]) );
memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
pHead = &aMerger[nBuf];
fts5DoclistIterInit(p1, &pHead->iter);
for(i=0; i<nBuf; i++){
fts5DoclistIterInit(&aBuf[i], &aMerger[i].iter);
fts5PrefixMergerInsertByRowid(&pHead, &aMerger[i]);
nOut += aBuf[i].n;
}
if( nOut==0 ) return;
nOut += p1->n + 9 + 10*nBuf;
/* The maximum size of the output is equal to the sum of the two
** input sizes + 1 varint (9 bytes). The extra varint is because if the
** first rowid in one input is a large negative number, and the first in
** the other a non-negative number, the delta for the non-negative
** number will be larger on disk than the literal integer value
** was.
**
** Or, if the input position-lists are corrupt, then the output might
** include up to 2 extra 10-byte positions created by interpreting -1
** (the value PoslistNext64() uses for EOF) as a position and appending
** it to the output. This can happen at most once for each input
** position-list, hence two 10 byte paddings. */
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9+10+10) ) return;
fts5DoclistIterInit(p1, &i1);
fts5DoclistIterInit(p2, &i2);
/* The maximum size of the output is equal to the sum of the
** input sizes + 1 varint (9 bytes). The extra varint is because if the
** first rowid in one input is a large negative number, and the first in
** the other a non-negative number, the delta for the non-negative
** number will be larger on disk than the literal integer value
** was.
**
** Or, if the input position-lists are corrupt, then the output might
** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
** (the value PoslistNext64() uses for EOF) as a position and appending
** it to the output. This can happen at most once for each input
** position-list, hence (nBuf+1) 10 byte paddings. */
if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
while( pHead ){
fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
/* Merge data from two or more poslists */
i64 iPrev = 0;
int nTmp = FTS5_DATA_ZERO_PADDING;
int nMerge = 0;
PrefixMerger *pSave = pHead;
PrefixMerger *pThis = 0;
int nTail = 0;
pHead = 0;
while( pSave && pSave->iter.iRowid==iLastRowid ){
PrefixMerger *pNext = pSave->pNext;
pSave->iOff = 0;
pSave->iPos = 0;
pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
fts5PrefixMergerNextPosition(pSave);
nTmp += pSave->iter.nPoslist + 10;
nMerge++;
fts5PrefixMergerInsertByPosition(&pHead, pSave);
pSave = pNext;
while( 1 ){
if( i1.iRowid<i2.iRowid ){
/* Copy entry from i1 */
fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
fts5DoclistIterNext(&i1);
if( i1.aPoslist==0 ) break;
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
if( pHead==0 || pHead->pNext==0 ){
p->rc = FTS5_CORRUPT;
break;
else if( i2.iRowid!=i1.iRowid ){
/* Copy entry from i2 */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
fts5DoclistIterNext(&i2);
if( i2.aPoslist==0 ) break;
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
else{
/* Merge the two position lists. */
i64 iPos1 = 0;
i64 iPos2 = 0;
int iOff1 = 0;
int iOff2 = 0;
u8 *a1 = &i1.aPoslist[i1.nSize];
u8 *a2 = &i2.aPoslist[i2.nSize];
int nCopy;
u8 *aCopy;
/* See the earlier comment in this function for an explanation of why
** corrupt input position lists might cause the output to consume
** at most nMerge*10 bytes of unexpected space. */
if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){
break;
}
fts5BufferZero(&tmp);
i64 iPrev = 0;
Fts5PoslistWriter writer;
memset(&writer, 0, sizeof(writer));
pThis = pHead;
pHead = pThis->pNext;
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
fts5PrefixMergerNextPosition(pThis);
fts5PrefixMergerInsertByPosition(&pHead, pThis);
/* See the earlier comment in this function for an explanation of why
** corrupt input position lists might cause the output to consume
** at most 20 bytes of unexpected space. */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferZero(&tmp);
sqlite3Fts5BufferSize(&p->rc, &tmp,
i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
);
if( p->rc ) break;
while( pHead->pNext ){
pThis = pHead;
if( pThis->iPos!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
assert_nc( iPos1>=0 && iPos2>=0 );
if( iPos1<iPos2 ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
}else{
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
}
fts5PrefixMergerNextPosition(pThis);
pHead = pThis->pNext;
fts5PrefixMergerInsertByPosition(&pHead, pThis);
}
if( pHead->iPos!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
}
nTail = pHead->iter.nPoslist - pHead->iOff;
/* WRITEPOSLISTSIZE */
assert( tmp.n+nTail<=nTmp );
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
break;
}
fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
if( nTail>0 ){
fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
}
pHead = pSave;
for(i=0; i<nBuf+1; i++){
PrefixMerger *pX = &aMerger[i];
if( pX->iter.aPoslist && pX->iter.iRowid==iLastRowid ){
fts5DoclistIterNext(&pX->iter);
fts5PrefixMergerInsertByRowid(&pHead, pX);
if( iPos1>=0 && iPos2>=0 ){
while( 1 ){
if( iPos1<iPos2 ){
if( iPos1!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
}
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
if( iPos1<0 ) break;
}else{
assert_nc( iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
if( iPos2<0 ) break;
}
}
}
}
}else{
/* Copy poslist from pHead to output */
PrefixMerger *pThis = pHead;
Fts5DoclistIter *pI = &pThis->iter;
fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
fts5DoclistIterNext(pI);
pHead = pThis->pNext;
fts5PrefixMergerInsertByRowid(&pHead, pThis);
if( iPos1>=0 ){
if( iPos1!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
}
aCopy = &a1[iOff1];
nCopy = i1.nPoslist - iOff1;
}else{
assert_nc( iPos2>=0 && iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
aCopy = &a2[iOff2];
nCopy = i2.nPoslist - iOff2;
}
if( nCopy>0 ){
fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
}
/* WRITEPOSLISTSIZE */
assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
if( tmp.n>i1.nPoslist+i2.nPoslist ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
break;
}
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
fts5DoclistIterNext(&i1);
fts5DoclistIterNext(&i2);
assert_nc( out.n<=(p1->n+p2->n+9) );
if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
}
}
fts5BufferFree(p1);
fts5BufferFree(&tmp);
memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
*p1 = out;
if( i1.aPoslist ){
fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
}
else if( i2.aPoslist ){
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
}
assert_nc( out.n<=(p1->n+p2->n+9) );
fts5BufferFree(p1);
fts5BufferFree(&tmp);
memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
*p1 = out;
}
}
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
int iIdx, /* Index to scan for data */
u8 *pToken, /* Buffer containing prefix to match */
const u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
Fts5Buffer *aBuf;
int nBuf = 32;
int nMerge = 1;
const int nBuf = 32;
void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid;
}else{
nMerge = FTS5_MERGE_NLIST-1;
nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
xMerge = fts5MergePrefixLists;
xAppend = fts5AppendPoslist;
}
@@ -5152,27 +5117,6 @@ static void fts5SetupPrefixIter(
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
if( iIdx!=0 ){
int dummy = 0;
const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
pToken[0] = FTS5_MAIN_PREFIX;
fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for(;
fts5MultiIterEof(p, p1)==0;
fts5MultiIterNext2(p, p1, &dummy)
){
Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
p1->xSetOutputs(p1, pSeg);
if( p1->base.nData ){
xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
iLastRowid = p1->base.iRowid;
}
}
fts5MultiIterFree(p1);
}
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
@@ -5193,21 +5137,13 @@ static void fts5SetupPrefixIter(
if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
int i1 = i*nMerge;
int iStore;
assert( i1+nMerge<=nBuf );
for(iStore=i1; iStore<i1+nMerge; iStore++){
if( aBuf[iStore].n==0 ){
fts5BufferSwap(&doclist, &aBuf[iStore]);
fts5BufferZero(&doclist);
break;
}
}
if( iStore==i1+nMerge ){
xMerge(p, &doclist, nMerge, &aBuf[i1]);
for(iStore=i1; iStore<i1+nMerge; iStore++){
fts5BufferZero(&aBuf[iStore]);
}
assert( i<nBuf );
if( aBuf[i].n==0 ){
fts5BufferSwap(&doclist, &aBuf[i]);
fts5BufferZero(&doclist);
}else{
xMerge(p, &doclist, &aBuf[i]);
fts5BufferZero(&aBuf[i]);
}
}
iLastRowid = 0;
@@ -5217,15 +5153,11 @@ static void fts5SetupPrefixIter(
iLastRowid = p1->base.iRowid;
}
assert( (nBuf%nMerge)==0 );
for(i=0; i<nBuf; i+=nMerge){
int iFree;
for(i=0; i<nBuf; i++){
if( p->rc==SQLITE_OK ){
xMerge(p, &doclist, nMerge, &aBuf[i]);
}
for(iFree=i; iFree<i+nMerge; iFree++){
fts5BufferFree(&aBuf[iFree]);
xMerge(p, &doclist, &aBuf[i]);
}
fts5BufferFree(&aBuf[i]);
}
fts5MultiIterFree(p1);
@@ -5480,7 +5412,6 @@ int sqlite3Fts5IndexQuery(
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
int iPrefixIdx = 0; /* +1 prefix index */
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
@@ -5502,9 +5433,7 @@ int sqlite3Fts5IndexQuery(
if( flags & FTS5INDEX_QUERY_PREFIX ){
int nChar = fts5IndexCharlen(pToken, nToken);
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
int nIdxChar = pConfig->aPrefix[iIdx-1];
if( nIdxChar==nChar ) break;
if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
if( pConfig->aPrefix[iIdx-1]==nChar ) break;
}
}
@@ -5521,7 +5450,8 @@ int sqlite3Fts5IndexQuery(
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
buf.p[0] = FTS5_MAIN_PREFIX;
fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
fts5IterSetOutputCb(&p->rc, pRet);
if( p->rc==SQLITE_OK ){
+1 -257
View File
@@ -8346,7 +8346,6 @@ do_catchsql_test 58.1 {
#-------------------------------------------------------------------------
do_test 59.0 {
sqlite3 db {}
sqlite3_fts5_register_matchinfo db
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-96b136358d01ec.db
@@ -8545,12 +8544,11 @@ do_test 59.0 {
do_catchsql_test 59.1 {
SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*eŸ'
} {0 {}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
do_test 60.0 {
sqlite3 db {}
sqlite3_fts5_register_matchinfo db
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-c77b90b929dc92.db
@@ -10509,260 +10507,6 @@ do_catchsql_test 71.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 72.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-77b86d070d0ac6.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j
| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .....=..........
| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet
| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con
| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE
| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k
| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v)
| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^..
| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d
| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz
| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE '
| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id
| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)]..
| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c
| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten
| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id
| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l...
| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id
| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE
| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'(
| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn
| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s
| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT
| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX.....
| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data
| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE
| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data'
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B
| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl
| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI
| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
| page 2 offset 4096
| 0: 0d 0f 44 00 05 0e 81 00 0f e7 0e 81 0f af 0f 58 ..D............X
| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0..........
| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$......
| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e.....
| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................
| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................
| 3792: 08 03 03 02 01 65 03 1e 03 05 05 04 05 05 01 01 .....e..........
| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 05 05 04 ........6.......
| 3824: 05 05 04 05 05 01 01 03 06 04 04 06 04 04 06 04 ................
| 3840: 04 06 04 03 03 01 65 03 14 04 05 07 05 05 01 01 ......e.........
| 3856: 02 08 0a 01 20 04 05 07 05 07 05 07 05 05 01 01 .... ...........
| 3872: 02 08 0a 09 fa 04 01 65 03 02 0a 01 06 0a 1a 0a .......e........
| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e.............
| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*.......
| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P.......
| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e......
| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e....
| 3968: 05 04 05 05 01 01 03 06 04 04 06 04 03 03 01 65 ...............e
| 3984: 02 14 04 05 07 05 05 01 01 02 08 0a 04 01 65 02 ..............e.
| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1
| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e
| 4032: 01 10 02 05 05 01 01 04 03 9f 02 01 65 01 12 03 ............e...
| 4048: 05 05 01 01 03 06 04 03 03 01 65 01 0e 14 05 05 ..........e.....
| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL.
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 03 0f 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R....
| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee
| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 65 20 65 eee e ee eeee e
| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 3664: 20 65 65 20 65 65 55 65 20 65 65 20 65 65 65 20 ee eeUe ee eee
| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee
| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e
| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e
| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 85 65 20 65 e e e e ee e.e e
| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 20 65 e eeeee ee e e e
| 3760: 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 65 ee eee ee eeeee
| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee
| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 20 65 ee eeeee ee e e
| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej
| 3824: 03 04 00 75 71 65 20 65 65 20 65 65 65 20 65 20 ...uqe ee eee e
| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee
| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee
| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee
| 3888: 65 20 65 20 65 20 65 64 20 65 65 65 20 65 65 20 e e e ed eee ee
| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 10 65 eeeee ee e e e.e
| 3920: 65 20 65 65 65 10 65 65 20 65 65 6a 02 04 00 75 e eee.ee eej...u
| 3936: 71 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 qe ee eee e ee e
| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee
| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e
| 3984: 65 20 65 65 65 66 65 65 20 65 65 20 65 20 65 20 e eeefee ee e e
| 4000: 65 88 65 65 20 65 65 65 30 65 65 20 65 65 65 65 e.ee eee0ee eeee
| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee
| 4032: 65 20 65 65 20 65 65 37 01 04 00 41 3f 65 20 65 e ee ee7...A?e e
| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e
| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee
| page 5 offset 16384
| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 03 03 00 10 .........!!.....
| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-77b86d070d0ac6.db
}]} {}
do_catchsql_test 72.1 {
INSERT INTO ttt(ttt) VALUES('integrity-check');
} {1 {database disk image is malformed}}
do_catchsql_test 72.1 {
SELECT 1 FROM ttt('e* NOT ee*');
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 73.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-b02ca2cc4d7dda.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j
| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .....=..........
| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet
| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con
| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE
| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k
| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v)
| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^..
| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d
| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz
| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE '
| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id
| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)]..
| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c
| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten
| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id
| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l...
| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id
| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE
| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'(
| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn
| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s
| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT
| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX.....
| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data
| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE
| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data'
| 4000: 28 69 65 20 49 4e 54 45 47 45 52 20 50 52 49 4d (ie INTEGER PRIM
| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B
| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl
| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI
| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
| page 2 offset 4096
| 0: 0d 0f 44 00 05 0e 81 00 0f e7 0e 81 0f af 0f 58 ..D............X
| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0..........
| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$......
| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e.....
| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................
| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................
| 3792: 08 03 03 02 01 65 03 1e 03 05 05 04 05 05 01 01 .....e..........
| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 05 05 04 ........6.......
| 3824: 05 04 f4 04 05 01 01 03 06 04 04 06 04 04 06 04 ................
| 3840: 04 06 04 db 03 01 65 03 14 04 05 07 05 05 01 01 ......e.........
| 3856: 02 08 0a 01 20 04 05 07 05 07 05 07 05 05 01 01 .... ...........
| 3872: 02 08 0a 0a 0a 04 01 65 03 02 0a 01 06 0a 0a 0a .......e........
| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e.............
| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*.......
| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P.......
| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e......
| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e....
| 3968: 05 04 05 05 01 01 03 06 09 14 06 04 03 03 01 65 ...............e
| 3984: 02 14 04 05 07 05 05 01 01 02 08 ed 04 01 65 02 ..............e.
| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1
| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e
| 4032: 01 10 02 05 05 01 01 04 03 03 02 01 55 01 12 03 ............U...
| 4048: 05 05 01 01 03 06 05 03 03 01 65 01 0e 04 05 05 ..........e.....
| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL.
| 4080: 00 00 11 24 00 00 00 00 01 0f c1 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R....
| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee
| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 65 20 65 eee e ee eeee e
| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 3664: 20 65 65 20 65 65 65 65 20 65 65 20 65 65 65 20 ee eeee ee eee
| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee
| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e
| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e
| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 65 65 20 65 e e e e ee eee e
| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 20 65 e eeeee ee e e e
| 3760: 20 65 65 20 65 62 d5 20 65 65 20 65 65 65 65 65 ee eb. ee eeeee
| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee
| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 21 65 ee eeeee ee e!e
| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej
| 3824: 03 04 00 75 71 65 20 65 65 10 65 65 65 20 65 20 ...uqe ee.eee e
| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee
| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee
| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee
| 3888: 65 20 65 20 65 20 65 65 20 65 65 65 20 62 55 20 e e e ee eee bU
| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 20 65 eeeee ee e e e e
| 3920: 65 20 65 65 65 20 55 65 20 65 65 6a 02 04 00 75 e eee Ue eej...u
| 3936: 71 65 20 65 65 20 65 65 65 20 65 10 65 65 20 65 qe ee eee e.ee e
| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee
| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e
| 3984: 65 20 65 65 65 65 65 65 20 65 65 20 65 20 65 20 e eeeeee ee e e
| 4000: 65 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 e ee eee ee eeee
| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee
| 4032: 65 20 65 65 21 65 65 37 0a 04 00 41 3f 65 20 65 e ee!ee7...A?e e
| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e
| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee
| page 5 offset 16384
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 13 03 00 10 .........!!.....
| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-b02ca2cc4d7dda.db
}]} {}
do_catchsql_test 73.1 {
SELECT snippet(ttt,ttt, NOT 54 ),
* FROM ttt('e* NOT ee*e* NOT ee* NOT ee*e* NOT e*') ;
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
-2
View File
@@ -29,8 +29,6 @@ do_execsql_test 1.0 {
INSERT INTO ttt SELECT a||a, b||b FROM ttt;
}
expr srand(1)
proc mutate {blob i} {
set o [expr {$i % [string length $blob]}]
set a [string range $blob 0 $o-1]
+1 -22
View File
@@ -91,27 +91,6 @@ do_catchsql_test 2.4 {
SELECT rowid FROM test_idx WHERE test_idx MATCH 'two' ORDER BY rank;
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE tx USING fts5(a, b, c, d, content=);
INSERT INTO tx(rowid, a, c) VALUES(1, 'abc def', 'a b c');
INSERT INTO tx(rowid, a, c) VALUES(5, 'a b c', 'a b d def');
}
do_execsql_test 3.1 {
INSERT INTO tx(tx, rowid, a, b, c, d)
VALUES('delete', 5, 'a b c', NULL, 'a b d def', NULL);
}
do_execsql_test 3.2 {
INSERT INTO tx(tx) VALUES('integrity-check');
}
do_execsql_test 3.3 {
INSERT INTO tx(tx, rowid, a, b, c, d)
VALUES('delete', 1, 'abc def', NULL, 'a b c', NULL);
}
do_execsql_test 3.4 {
INSERT INTO tx(tx) VALUES('integrity-check');
}
finish_test
-57
View File
@@ -1,57 +0,0 @@
# 2020 Dec 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests focused on prefix indexes.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5prefix2
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach p {3 2 1} {
reset_db
do_execsql_test 1.$p.0 "
CREATE VIRTUAL TABLE t1 USING fts5(xyz, prefix=$p);
"
do_execsql_test 1.$p.1 {
INSERT INTO t1 VALUES
('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 f.');
}
do_execsql_test 1.$p.2 {
SELECT highlight(t1, 0, '[', ']') FROM t1('f*');
} {
{May you [find] [forgiveness] [for] yourself and [forgive] others.}
{May you share [freely], never taking more than you give [f].}
}
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE t2 USING fts5(one, prefix=3);
INSERT INTO t2 VALUES('top');
INSERT INTO t2 VALUES('to');
INSERT INTO t2 VALUES('tommy');
}
do_execsql_test 2.1 {
SELECT * FROM t2('to*');
} {top to tommy}
finish_test
+1 -51
View File
@@ -356,41 +356,6 @@ static void cksmVerifyFunc(
sqlite3_result_int(context, memcmp(data+nByte-8,cksum,8)==0);
}
#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
/*
** SQL function: initialize_cksumvfs(SCHEMANAME)
**
** This SQL functions (whose name is actually determined at compile-time
** by the value of the SQLITE_CKSUMVFS_INIT_FUNCNAME macro) invokes:
**
** sqlite3_file_control(db, SCHEMANAME, SQLITE_FCNTL_RESERVE_BYTE, &n);
**
** In order to set the reserve bytes value to 8, so that cksumvfs will
** operation. This feature is provided (if and only if the
** SQLITE_CKSUMVFS_INIT_FUNCNAME compile-time option is set to a string
** which is the name of the SQL function) so as to provide the ability
** to invoke the file-control in programming languages that lack
** direct access to the sqlite3_file_control() interface (ex: Java).
**
** This interface is undocumented, apart from this comment. Usage
** example:
**
** 1. Compile with -DSQLITE_CKSUMVFS_INIT_FUNCNAME="ckvfs_init"
** 2. Run: "SELECT cksum_init('main'); VACUUM;"
*/
static void cksmInitFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int nByte = 8;
const char *zSchemaName = (const char*)sqlite3_value_text(argv[0]);
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_file_control(db, zSchemaName, SQLITE_FCNTL_RESERVE_BYTES, &nByte);
/* Return NULL */
}
#endif /* SQLITE_CKSUMBFS_INIT_FUNCNAME */
/*
** Close a cksm-file.
*/
@@ -750,17 +715,7 @@ static int cksmGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int cksmCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
sqlite3_vfs *pOrig = ORIGVFS(pVfs);
int rc;
assert( pOrig->iVersion>=2 );
if( pOrig->xCurrentTimeInt64 ){
rc = pOrig->xCurrentTimeInt64(pOrig, p);
}else{
double r;
rc = pOrig->xCurrentTime(pOrig, &r);
*p = (sqlite3_int64)(r*86400000.0);
}
return rc;
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
}
static int cksmSetSystemCall(
sqlite3_vfs *pVfs,
@@ -791,11 +746,6 @@ static int cksmRegisterFunc(
rc = sqlite3_create_function(db, "verify_checksum", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, cksmVerifyFunc, 0, 0);
#ifdef SQLITE_CKSUMVFS_INIT_FUNCNAME
(void)sqlite3_create_function(db, SQLITE_CKSUMVFS_INIT_FUNCNAME, 1,
SQLITE_UTF8|SQLITE_DIRECTONLY,
0, cksmInitFunc, 0, 0);
#endif
return rc;
}
+3 -13
View File
@@ -247,8 +247,7 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** 4: step=VALUE
**
** Also, if bit 8 is set, that means that the series should be output
** in descending order rather than in ascending order. If bit 16 is
** set, then output must appear in ascending order.
** in descending order rather than in ascending order.
**
** This routine should initialize the cursor and position it so that it
** is pointing at the first row, or pointing off the end of the table
@@ -274,12 +273,7 @@ static int seriesFilter(
}
if( idxNum & 4 ){
pCur->iStep = sqlite3_value_int64(argv[i++]);
if( pCur->iStep==0 ){
pCur->iStep = 1;
}else if( pCur->iStep<0 ){
pCur->iStep = -pCur->iStep;
if( (idxNum & 16)==0 ) idxNum |= 8;
}
if( pCur->iStep<1 ) pCur->iStep = 1;
}else{
pCur->iStep = 1;
}
@@ -373,11 +367,7 @@ static int seriesBestIndex(
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy==1 ){
if( pIdxInfo->aOrderBy[0].desc ){
idxNum |= 8;
}else{
idxNum |= 16;
}
if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
pIdxInfo->orderByConsumed = 1;
}
}else{
-3
View File
@@ -31,10 +31,7 @@ SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#ifndef SQLITE_AMALGAMATION
typedef sqlite3_uint64 u64;
#endif /* SQLITE_AMALGAMATION */
/******************************************************************************
** The Hash Engine
-7
View File
@@ -183,13 +183,6 @@ int main(int argc, char **argv){
break;
}
if( nStatStep>0 ){
sqlite3_int64 nUsed;
sqlite3_int64 nHighwater;
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0);
fprintf(stdout, "memory used=%lld highwater=%lld\n", nUsed, nHighwater);
}
sqlite3_free(zErrmsg);
return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1;
}
+22 -60
View File
@@ -48,7 +48,6 @@ struct sqlite3_session {
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
i64 nMalloc; /* Number of bytes of data allocated */
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
@@ -432,26 +431,6 @@ static int sessionSerializeValue(
return SQLITE_OK;
}
/*
** Allocate and return a pointer to a buffer nByte bytes in size. If
** pSession is not NULL, increase the sqlite3_session.nMalloc variable
** by the number of bytes allocated.
*/
static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){
void *pRet = sqlite3_malloc64(nByte);
if( pSession ) pSession->nMalloc += sqlite3_msize(pRet);
return pRet;
}
/*
** Free buffer pFree, which must have been allocated by an earlier
** call to sessionMalloc64(). If pSession is not NULL, decrease the
** sqlite3_session.nMalloc counter by the number of bytes freed.
*/
static void sessionFree(sqlite3_session *pSession, void *pFree){
if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree);
sqlite3_free(pFree);
}
/*
** This macro is used to calculate hash key values for data structures. In
@@ -919,19 +898,13 @@ static int sessionPreupdateEqual(
** Growing the hash table in this case is a performance optimization only,
** it is not required for correct operation.
*/
static int sessionGrowHash(
sqlite3_session *pSession, /* For memory accounting. May be NULL */
int bPatchset,
SessionTable *pTab
){
static int sessionGrowHash(int bPatchset, SessionTable *pTab){
if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
int i;
SessionChange **apNew;
sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);
apNew = (SessionChange**)sessionMalloc64(
pSession, sizeof(SessionChange*) * nNew
);
apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -952,7 +925,7 @@ static int sessionGrowHash(
}
}
sessionFree(pSession, pTab->apChange);
sqlite3_free(pTab->apChange);
pTab->nChange = nNew;
pTab->apChange = apNew;
}
@@ -986,7 +959,6 @@ static int sessionGrowHash(
** be freed using sqlite3_free() by the caller
*/
static int sessionTableInfo(
sqlite3_session *pSession, /* For memory accounting. May be NULL */
sqlite3 *db, /* Database connection */
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
@@ -1041,7 +1013,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
pAlloc = sessionMalloc64(pSession, nByte);
pAlloc = sqlite3_malloc64(nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -1084,7 +1056,7 @@ static int sessionTableInfo(
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
sessionFree(pSession, azCol);
sqlite3_free(azCol);
}
sqlite3_finalize(pStmt);
return rc;
@@ -1106,7 +1078,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( pTab->nCol==0 ){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
);
if( pSession->rc==SQLITE_OK ){
@@ -1197,7 +1169,7 @@ static void sessionPreupdateOneChange(
}
/* Grow the hash table if required */
if( sessionGrowHash(pSession, 0, pTab) ){
if( sessionGrowHash(0, pTab) ){
pSession->rc = SQLITE_NOMEM;
return;
}
@@ -1264,7 +1236,7 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
pChange = (SessionChange *)sqlite3_malloc64(nByte);
if( !pChange ){
rc = SQLITE_NOMEM;
goto error_out;
@@ -1637,7 +1609,7 @@ int sqlite3session_diff(
int nCol; /* Columns in zFrom.zTbl */
u8 *abPK;
const char **azCol = 0;
rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
bMismatch = 1;
@@ -1735,7 +1707,7 @@ int sqlite3session_create(
** Free the list of table objects passed as the first argument. The contents
** of the changed-rows hash tables are also deleted.
*/
static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
static void sessionDeleteTable(SessionTable *pList){
SessionTable *pNext;
SessionTable *pTab;
@@ -1747,12 +1719,12 @@ static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
SessionChange *pNextChange;
for(p=pTab->apChange[i]; p; p=pNextChange){
pNextChange = p->pNext;
sessionFree(pSession, p);
sqlite3_free(p);
}
}
sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */
sessionFree(pSession, pTab->apChange);
sessionFree(pSession, pTab);
sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */
sqlite3_free(pTab->apChange);
sqlite3_free(pTab);
}
}
@@ -1780,11 +1752,9 @@ void sqlite3session_delete(sqlite3_session *pSession){
/* Delete all attached table objects. And the contents of their
** associated hash-tables. */
sessionDeleteTable(pSession, pSession->pTable);
sessionDeleteTable(pSession->pTable);
/* Assert that all allocations have been freed and then free the
** session object itself. */
assert( pSession->nMalloc==0 );
/* Free the session object itself. */
sqlite3_free(pSession);
}
@@ -1831,8 +1801,7 @@ int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
int nByte = sizeof(SessionTable) + nName + 1;
pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -2429,7 +2398,7 @@ static int sessionGenerateChangeset(
int nNoop; /* Size of buffer after writing tbl header */
/* Check the table schema is still Ok. */
rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
rc = SQLITE_SCHEMA;
}
@@ -2604,13 +2573,6 @@ int sqlite3session_isempty(sqlite3_session *pSession){
return (ret==0);
}
/*
** Return the amount of heap memory in use.
*/
sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
return pSession->nMalloc;
}
/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
@@ -4422,7 +4384,7 @@ static int sessionChangesetApply(
int i;
sqlite3changeset_pk(pIter, &abPK, 0);
rc = sessionTableInfo(0,
rc = sessionTableInfo(
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
@@ -4901,7 +4863,7 @@ static int sessionChangesetToHash(
}
}
if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
if( sessionGrowHash(pIter->bPatchset, pTab) ){
rc = SQLITE_NOMEM;
break;
}
@@ -5087,7 +5049,7 @@ int sqlite3changegroup_output_strm(
*/
void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
if( pGrp ){
sessionDeleteTable(0, pGrp->pList);
sessionDeleteTable(pGrp->pList);
sqlite3_free(pGrp);
}
}
@@ -5488,7 +5450,7 @@ int sqlite3rebaser_rebase_strm(
*/
void sqlite3rebaser_delete(sqlite3_rebaser *p){
if( p ){
sessionDeleteTable(0, p->grp.pList);
sessionDeleteTable(p->grp.pList);
sqlite3_free(p);
}
}
-8
View File
@@ -440,14 +440,6 @@ int sqlite3session_patchset(
*/
int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Query for the amount of heap memory used by a session object.
**
** This API returns the total amount of heap memory in bytes currently
** used by the session object passed as the only argument.
*/
sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlite3_changeset_iter
-7
View File
@@ -242,7 +242,6 @@ static int SQLITE_TCLAPI test_session_cmd(
{ "table_filter", 1, "SCRIPT", }, /* 6 */
{ "patchset", 0, "", }, /* 7 */
{ "diff", 2, "FROMDB TBL", }, /* 8 */
{ "memory_used", 0, "", }, /* 9 */
{ 0 }
};
int iSub;
@@ -348,12 +347,6 @@ static int SQLITE_TCLAPI test_session_cmd(
}
break;
}
case 9: { /* memory_used */
sqlite3_int64 nMalloc = sqlite3session_memory_used(pSession);
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nMalloc));
break;
}
}
return TCL_OK;
+76 -82
View File
@@ -1,13 +1,13 @@
C Fix\sa\spotential\suse-after-free\sfollowing\san\sOOM\sin\ssqlite3ParserAddCleanup()\nand\sadd\sa\smechanism\sto\sdetect\ssituations\swhere\sthis\smight\soccur\sin\sthe\nfuture.
D 2021-01-12T15:30:01.102
C Version\s3.34.1
D 2021-01-20T14:10:07.150
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 9cae1bffe5cb811216bf7425395e7fc0594daa2ce31f625835a9d0c3fb25315f
F Makefile.in 0e88f5d095213a9ccd45c5bbd871c8ead498f886dff4493471fbf48b1f867f9d
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc ad07bbd645132533e1fd7164a03acfa9afecda378b3787c10f62ab4c7c45e6ea
F Makefile.msc dd10dbf63b2f8ac3e2f0542963a21bc69058976ac4355165f212a31c83d17f44
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
F VERSION 92f3e4c5cdee6f0779aef1eae857dfc21d0eabb1f2af169dc90e63cd76b15bb2
F VERSION 9633e2edacc7963299a285b89cbeb832f73316c9ccc58f9a70701a5e8b16513c
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -18,7 +18,7 @@ F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a
F autoconf/Makefile.msc e0f1dafc48d000fd6ddfdb01815271528db55cbc7299ca888df5b93367f0d5a4
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 55be6fc04a5b030b367fe317b72dc8c0eafc4713991fe6182cf647b02fb782cb
F autoconf/configure.ac 3cd933b959fe514eebd1ca1717dfddbf2c9b825b6bc2c5f744deaf5d63af9288
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -34,8 +34,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure 7736c168f4fd717c8052e58428a89e645d15cf0e5a3d051e248aad859a3cb140 x
F configure.ac efdb70036084ea637226e378a14f932e70c0df9f1bc846a24a909c0e1613524a
F configure 10bbf6fa13320dc9b6197aa9574bd7360f379f904a53ad632ddb310099cf148d x
F configure.ac 73545c21eebcef9398d85c982c7be260f07708256778221b541f83ae8c6f61eb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
F doc/lemon.html c5d8ba85ac1daef7be8c2d389899480eb62451ff5c09b0c28ff8157bb8770746
@@ -50,8 +50,8 @@ F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 63d778d964e55ef2d1a723043d91c59e7dc6ef1649d91c78c0bef00f9c6f1427
F ext/expert/sqlite3expert.c de51b187c629a4c4264d5de0b77862641e11426f7a963a92abf2d4077085fc8c
F ext/expert/expert1.test dba6e752cc701621771f925f3872b183fa688f7b4a9f4822631fc02bdbffc45a
F ext/expert/sqlite3expert.c 216e250acc54b8aaa9ff5c1e1b2256788abc3994dd1d757626102718122e6a91
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -117,9 +117,9 @@ F ext/fts5/fts5Int.h 26c74dd5776f798436fbf604a0bf0e8de263b35b5060b05c15f9085845d
F ext/fts5/fts5_aux.c f558e1fb9f0f86a4f7489e258c162e1f947de5ff2709087fbb465fddb7092f98
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
F ext/fts5/fts5_config.c be54f44fca491e96c6923a4b9a736f2da2b13811600eb6e38d1bcc91c4ea2e61
F ext/fts5/fts5_expr.c 016bd06030679bd31b0f07ef87d62c42031e5da25cb3174a84e5b0f6ef4b47b0
F ext/fts5/fts5_expr.c e527e3a7410393075598cec544e3831798a8c88b3e8878e2cfb7cb147113e925
F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
F ext/fts5/fts5_index.c acbe3ccd36f5a7373009dfff02a11c4a817af73bc3ef8c340f2105d7d073f8b4
F ext/fts5/fts5_index.c 9f152a596df3a2227ddd59adb82549c2b6858ab36bc1d26fd8933f43d3d63d36
F ext/fts5/fts5_main.c b4e4931c7fcc9acfa0c3b8b5e5e80b5b424b8d9207aae3a22b674bd35ccf149d
F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
@@ -160,9 +160,9 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
F ext/fts5/test/fts5corrupt3.test 5df97f353102f0078d0bb418d620652d03460ee1cceb2992a3b5ee6fb619b24e
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5corrupt3.test dd5435659d5363fc3b3ac32175e2fc793fdc17980b47e3d598695d867eaa77a2
F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91
F ext/fts5/test/fts5delete.test 4a15fb03b6c7eac62ac807a3a32b7f0dc74f0d479c410e3e3568ae96b9469290
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
@@ -204,7 +204,6 @@ F ext/fts5/test/fts5plan.test 79d35b5e83bbdcba48d946a7f008df161f6b0ede1a966892d0
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
F ext/fts5/test/fts5prefix2.test 3847ce46f70b82d61c6095103a9d7c53f2952c40a4704157bc079c04d9c8b18b
F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee7e017ce46f2416
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
@@ -291,7 +290,7 @@ F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0e
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
F ext/misc/cksumvfs.c 8dc4e1b718e374bed3a9b5c0a08da2922438002e33267311697768e06217b983
F ext/misc/cksumvfs.c c4e7ebeae5aa578df98f23bddb63ecbcbe913ee3c32b8b769525af100d752061
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
@@ -319,9 +318,9 @@ F ext/misc/regexp.c 246244c714267f303df76acf73dcf110cf2eaf076896aaaba8db6d6d21a1
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c c6bd5d249e5199a1b55aeee4d0e6576ff3a68702fc475dbd64503a32903516c7
F ext/misc/series.c fbb8e6be97b54d10d2f235e163fa2f53a8f4421c66ebd532a233fd1c69c3f522
F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
F ext/misc/shathree.c e984f31731de4cf302a0386be5fe664580f63d8204c47b9b41cc4b997745f9ec
F ext/misc/shathree.c 86bee126b89dc7f3a9edc6d31497588a0f1e78ab867025a766b67f52bcf1f656
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
@@ -339,7 +338,7 @@ F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 520f34c3099e5b7d546f13708607dc2fa173c46b68952eecf0d19cd675fec85e
F ext/misc/zipfile.c e35e035bc2765b1ccdcb15f9815c2112843fcbc8f36aa071f0e5935df7072228
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c b880ca5cb857d6d6f52e72eb7397813058ef48c78c5402cd04ff2b6b5437f622
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
@@ -453,9 +452,9 @@ F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
F ext/session/sqlite3session.c d2aaaf05241ac7d23a1b1eaa8b1f165c90f7ff0fe57ff1932a87c6b89b886117
F ext/session/sqlite3session.h f53c99731882bf59c7362855cdeba176ce1fe8eeba089e38a8cce0172f8473aa
F ext/session/test_session.c 93ca965112d2b4d9d669c9c0be6b1e52942a268796050a145612df1eee175ce0
F ext/session/sqlite3session.c 2c76b8c3a5d6dab736686f8a48833b8bdac0871ecc6f447f9839d28bd4a63d6c
F ext/session/sqlite3session.h a2db5b72b938d12c727b4b4ec632254ca493670a9c0de597af3271a7f774fc57
F ext/session/test_session.c 24286d958dc6f4ca4d7e710f09bc0fa9d50956a40dd99fd8223e7488024c71fe
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -474,20 +473,20 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 36cae0d6e3e91a1996e1a472f8c7242c31a4e38ba4295e3056da198c04fd2a87
F src/alter.c b6de60d59419e34f5b48ff2b21fe0f9bb66fc714e5545a6ac790ac7a0c46548c
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
F src/attach.c 0f497c15c4cfe3bdcb214f0dbdbbb6c5ed7e8a9308ac445c7959f5e5780437a9
F src/auth.c 8d1df0e2ef8bafbedd4f1fe4baff03eb27507da4bf6e449df3613d383c4018b2
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 0f9cb686871ae668817673f0823b55d1bcadbc86ea28bd22c590b064a8322d5a
F src/btree.h 285f8377aa1353185a32bf455faafa9ff9a0d40d074d60509534d14990c7829e
F src/btreeInt.h 7614cae30f95b6aed0c7cac7718276a55cfe2c77058cbfd8bef5b75329757331
F src/build.c d4c06261b0e532523ede58dc511381a7a9c155132e4b65a6bb2ff76fe657793a
F src/btree.c ee14224322b9e4172d01e691e2f289f6c630ae39b7906f84b72dc780b9e42a76
F src/btree.h dcdff4037d75b3f032a5de0d922fcfaf35d48589417f634fa8627362709315f9
F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 2a322b9a3d75771fb4d99e0702851f4f68dda982507a0f798eefb0712969a410
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
F src/date.c dace306a10d9b02ee553d454c8e1cf8d3c9b932e137738a6b15b90253a9bfc10
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
@@ -495,16 +494,16 @@ F src/delete.c 927cf8f900583e79aca8f1a321979e0a8f053babd9a690b44b38f79de2cc09fe
F src/expr.c 0d196ed5a2ebf96be7e8df88add4fabfad0dce16c0fed81a4b8f6a26e259797f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72
F src/func.c 251b5953cecd0ce3e282213c5e623134415793d3569d7804d13460559d7e45ff
F src/global.c ed55af196a9b66e198aaeda3f5454c3aa7d7d050c6c938181fd044b70d180a81
F src/func.c 574f7e5a67e4b7a7855cf3478037717c8f44686c0cd727e1d7f7773414165c03
F src/global.c 943256ac44f333039d35a9830c18d075a81fa6b6bf2af05771494a9acfb9a40b
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c c5e0c25cfb9960d9b7d49043de6adc12748853bc6dea76f5adef059e366f2f70
F src/insert.c 7e081d33aab4a9d761c39dccf3c3872c35501565d2ed9db66301918d23bc7901
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
F src/main.c 97e9f137354bc1f76dc9bb60a0a24f8c45cf73b33e80d3ee4c64155336fb820d
F src/main.c 54d61d1e94f225636053c862c930d7dd7b29162b93d3f3ecb00439910ccba02a
F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -520,7 +519,7 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f956d
F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
F src/os.c 2d6e646370b1aa78942c68d7edf124e518963adf4a90bce87f365a5a5495529a
F src/os.c 80e4cf3e5da06be03ca641661e331ce60eeeeabf0d7354dbb1c0e166d0eedbbe
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
@@ -529,28 +528,28 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c c49952ac5e9cc536778eff528091d79d38b3e45cbeeed4695dc05e207dc6547d
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
F src/parse.y 6c8aa09a7fa6e0867c3a3d67ef61b911aa392c9b084a61dc632cd93732aef8ad
F src/parse.y 9ce4dfb772608ed5bd3c32f33e943e021e3b06cfd2c01932d4280888fdd2ebed
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
F src/prepare.c cfe5a0ec9fd612c89b4d50acfd4b796bd5fe850441cab0d866d72fa3aa982c45
F src/prepare.c 270170a239c0f66bd3c228f373afe24447c2614a6829ae22080babc64f241931
F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c a9c38abfbaaf1230fa9079b4d1d43694cac335a85efa39684bd4969a5c877a19
F src/shell.c.in 79bceb990e4bac23a09bb8dd65783ea4867b8bfca9242b5a82b884043e65109a
F src/sqlite.h.in 0af968a1fa3c717261e1df0ed105fa7bddb4d82de7e0adb3eab49e6aa81b4de7
F src/select.c 847062694ac9a6add162d39182584b7ca53948ad821c52512a125cd845904e71
F src/shell.c.in 55113760ae91a05c6ce4558714a1c8fc7a44bf266f735de6e71ea40f79e69830
F src/sqlite.h.in 843471c794810d090b7bc1a31ff1d7c6fed5d029dc47ccc54605bd418df5d294
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
F src/sqliteInt.h c7c7e0e79769885a1c7fa519299bdb222e83e2d7d4843ed6ca1cd9a585016386
F src/sqliteInt.h c01115c8dd967f7d334a98ba37ac821eafb04144c8085a795daaf2185743d27a
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
F src/test1.c 2197966d2f7211ef9eefaa6c3c7dd2c7d786d1f33f2aadef2f08c8c79eceec26
F src/test1.c 465b7a35b7e231bf2833e47c1371b5dfc99bd803ebe73783862399d479d696a5
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
@@ -565,7 +564,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 98698f5242be88af75eaac54adde573471d5ed2f6484e0dac034cb1e763a551a
F src/test_config.c 5ea19bf0972a9d91728518b4d30e91477acce80496003ecbef3a7fb18d0bd081
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
@@ -604,31 +603,31 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c c64c49d7c2ec4490c2fef1f24350167ba16b03b0c6cee58ad1a1d70a4325d4e9
F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
F src/trigger.c 29680c54c1aa088fa1b4d50137d75669a40d5ef814394e321fab1e547868e3d3
F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
F src/vdbe.c 67de20067fa3a2ee8566342c751e941a2fe3fd88940fd9886ca5115f04165cce
F src/vdbe.c d24a43b6b1ed2dba893636a14f5e56001444ab3fd5465e3bca8ab01799840acd
F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e
F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
F src/vdbeaux.c e91d74e24babcf61969279b193e228cf4f8bc724a9cc59ed287db064326876f8
F src/vdbeaux.c c76b7e96e189f5056d1de914d33d07bd03d3b88741f75375c8e18c9b11ffd379
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c 5f5fc793092f53bbdfde296c50f563fb7bda58cf48e9cf6a8bdfbc5abd409845
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c d9c4e454ebb9499e908aa62d55b8994c375cf5355ac78f60d45af17f7890701c
F src/where.c 3d31871d03906312d7d71a9c0b28c97bcbaead7606dfc15f9b3d080b18702385
F src/whereInt.h 9a3f577619f07700d16d89eeb2f3d94d6b7ed7f109c2dacf0ce8844921549506
F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
F src/where.c ad738741bf45999188a3047f6277063e3f6843304d581e3ad5875419afdeb6b2
F src/whereInt.h 59077fbd0b3d01bc8715e746c86a99ebf4c85bde8a57077ec04d2a23e59666ec
F src/wherecode.c a3a1aff30fe99a818d8e7c607980f033f40c68d890e03ed25838b9dbb7908bee
F src/whereexpr.c 3a463e156ea388083c501502229c2c7f4f5c6b5330ea59bdf40d6eb6e155a25f
F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
@@ -791,7 +790,6 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test 22589f503602cc5984e80f27f46c4de2134f24f1515ba2440513c377cb692258
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/corruptN.test 781c5f26a2d8918f03d45ac4968a738031eeb113a4b153c7588756d9b09c7b04
F test/cost.test 1d156ce9858780a966c062694687afe0343a0ed12d081d071fb57027e726bafc
F test/count.test e0699a15712bc2a4679d60e408921c2cce7f6365a30340e790c98e0f334a9c77
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
@@ -800,7 +798,7 @@ F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
F test/crash5.test 98f77ad22bceaea9043bf87088d5b61d004a1f40bb7c9dc3b6a7c70bd502c0bb
F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
@@ -819,7 +817,7 @@ F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c db2a1710c0d30d38e1352ee1b52b717fcb224c8caacc6f10909ef540f73cc9e8
F test/dbfuzz2.c 40cc4600947f30600f0ab365a2714ec76a899c9adb2c0ccd63ba583b2f71390e
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
@@ -1018,7 +1016,7 @@ F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd4
F test/fts4record.test a48508f69a84c9287c8019d3a1ae712f5730d8335ffaf8e2101e691d078950bb
F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3cfd0c880
F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
F test/fts4unicode.test 82a9c16b68ba2f358a856226bb2ee02f81583797bc4744061c54401bf1a0f4c9
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
F test/fts4upfrom.test 8df5acb6e10ad73f393d1add082b042ab1db72567888847d098152121e507b34
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
@@ -1027,7 +1025,6 @@ F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1
F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
F test/func7.test bb05a77daedf0e3f8764f323a49bc3b8d98f280a0bc6a370387117f4596bde05
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
@@ -1035,7 +1032,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 95427205d6cedb8fdb95bf7738e95785c790febf782d9c1e6067baaa1adc871d
F test/fuzzcheck.c 5f81f2cc65f13068620245f2e2c6059657d3b26be476df379ae2da539f17676d
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1043,14 +1040,14 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
F test/fuzzdata8.db 7f6c5443d67ba040f760b4d28da54cc9f68174fa212ae34ccb86c645de761ec4
F test/fuzzdata8.db f8451a1fd38efbea8c1a7cdf5d02259c4702446a9fabf566becd306b64a50236
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
F test/having.test ea5cb01cdf3d90fd1b516ef36b1fbde518dbbd61c50141f5eb830d8101844040
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test e97382e68e4379838e888756d653afd159f5f14780315ff97b70360d3d8485bc
@@ -1331,7 +1328,7 @@ F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 68de52409e45a3313d00b8461b48bef4fb729faf36ade9067a994eae55cc86f4
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test fec14c9015ed4ec941508bbc144f30b42e40ac34a4bb33001450369865dd0b75
F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
F test/selectD.test fc20452847a01775710090383cfb4423275d2f745fed61f34fbf37573ac0d214
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
@@ -1352,10 +1349,10 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 56a7358a2a05e850e9e4aa24629db9c8975e8038dbe8debd2d95be22a5f03612
F test/shell1.test 0ba53c72545de142e1b76fa793ee33293134aa02abb9b50b35398670481ea661
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
F test/shell5.test 84a30b55722a95a5b72989e691c469a999ca7591e7aa00b7fabc783ea5c9a6fe
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
@@ -1393,7 +1390,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
F test/speedtest1.c 5e5b805f24cc939656058f6a498f5a2160f9142e4815c54faf758ec798d4cdad
F test/speedtest1.c 849dbcb0bded9f966e43f28e8ce824b2915cb5dd0031a2e85996f7e3de36c2b1
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1401,7 +1398,6 @@ F test/spellfix4.test 51c7c26514ade169855c66bcf130bd5acfb4d7fd090cc624645ab275ae
F test/sqldiff1.test 28cd737cf1b0078b1ec1bbf425e674c47785835e
F test/sqllimits1.test 264f4b0f941800ba139d25e33ee919c5d95fea06dfbe8ac291d6811a30984ca5
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
F test/stat.test 15a3106eddedfc882f64bc09f237b4169be4b92dd57c93031b8ff8b13af3e7c5
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
@@ -1435,7 +1431,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 56c059c88c5b96a624f1193ba48b0bac034190b79cd9c75cb4acbfe84baf7ec5
F test/tester.tcl 754521f0db534d51ab504b2d14fe0bdca1f1c15de731ceb8ee5bfd78372a2a5f
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1596,7 +1592,7 @@ F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
F test/trace3.test ae2004df24b585fed9046cc0bae4601762bc6fc4aa321d475f1350bba5047f31
F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
@@ -1628,9 +1624,6 @@ F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unionall.test ca6f612930c79e30f41f804dff4cce949b61347930847642e333ecd5d79f5964
F test/unionall2.test c9a62db63350bcbce3a7bec50dd8c5410f08be33f8af435473756286d4657215
F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
@@ -1648,7 +1641,6 @@ F test/upsert1.test 88f9e258c6a0eeeb85937b08831e8daad440ba41f125af48439e9d33f266
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
F test/upsert5.test f49faf5f15b5c3641c6f5d7c7cc531ef5ac997567b2b6bb7bc96f7c88753ca0b
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
@@ -1656,11 +1648,10 @@ F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum-into.test 48f4cec354fb6f27c98ef58d2fe49a11b71ff131af0cd9140efacc9858b9f670
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
F test/vacuum6.test d3173a54edc81d13d99e4cf4972232b3cbb52f1d56ed48c3a939ef4e751c1ee8
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
@@ -1722,7 +1713,7 @@ F test/walsetlk.test 11f7fe792fdce54cf09874dab824e0627f2eedecfb9f7983e325606ec51
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
F test/walvfs.test bccb3e0d235ef85e276f491d34db32c9ada1ea67be8d9f10aabe7b30319ec656
F test/walvfs.test a2913001a83b19c1d20220e556cee14d87d47ecb6949b5e0a2e9e2590abecf1e
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
F test/where.test e713c0c64e3e6b062235e39a2f7e5508c517df16b63d69fd786e26bc7330b1c6
@@ -1745,7 +1736,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
F test/whereL.test 1afe47227f093dc0547236491fb37529b7be9724b8575925a321001b80e6a23a
F test/whereL.test e05cedc9389c6f09ad55bd5999a3fddccebec90672fb989433c145dcdaf26996
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
@@ -1814,8 +1805,8 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c d44ba4f03427c9bd34b601f315fe77c2b6d4bd215801a0259aeedbcc4c94a95c
F tool/lempar.c 1d3d075da18681c67ecc66c1f171e7094e18cd2cfba6a8a1bd4f3f639d6656e1
F tool/lemon.c 70eedc31614a58fe31a71025c17ebd1502a6ce9cfef0ed5e33acb0b5b737b291
F tool/lempar.c 0e1d5eeb9736108d3dba782a9dd56f4e7cb69006b6ee181308b7ebfb15313a12
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1823,7 +1814,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c 24e4396ae665d985fed9e040e8b748129c1a12d77eeeae7ad4609821c41ba7bf
F tool/mkkeywordhash.c 11a3f3af8e787d0c5ca459ed66fe80fd09e661876506e7b978ec08c19477bdc2
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
@@ -1895,7 +1886,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P affa2b7b316941b8a6c4d0d1ff212c81a593faf1d05d129e14d2b70d73a25c59
R f95fa7a0a6ecfccf053d41ca6f333d8f
P a1a7a5f238fcfdcd56faba063e381258c9e2944d9b02b31d402a4207a607fc1c
R 58ed0e2a70acf908b3c6a7c54bbafc77
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.34.1 *
U drh
Z 25b7965ccc91991627419c27b1a54eed
Z 11054c73a336ca8fa32ae8cddcafd46b
+1 -1
View File
@@ -1 +1 @@
38ef8ab9830e12acd2c710e113939b1f8dced02612c6933c37a3c948a4030d0a
10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f
+2 -5
View File
@@ -381,14 +381,11 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*zEnd-- = '\0';
}
db->mDbFlags |= DBFLAG_PreferBuiltin;
/* substr() operations on characters, but addColOffset is in bytes. So we
** have to use printf() to translate between these units: */
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = printf('%%.%ds, ',sql) || %Q"
" || substr(sql,1+length(printf('%%.%ds',sql))) "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
"WHERE type = 'table' AND name = %Q",
zDb, pNew->addColOffset, zCol, pNew->addColOffset,
zDb, pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
+5 -1
View File
@@ -209,7 +209,11 @@ 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( db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
if( db->xAuth==0 ){
return SQLITE_OK;
}
+4 -145
View File
@@ -1143,24 +1143,6 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
}
/*
** Given a record with nPayload bytes of payload stored within btree
** page pPage, return the number of bytes of payload stored locally.
*/
static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
int maxLocal; /* Maximum amount of payload held locally */
maxLocal = pPage->maxLocal;
if( nPayload<=maxLocal ){
return nPayload;
}else{
int minLocal; /* Minimum amount of payload held locally */
int surplus; /* Overflow payload available for local storage */
minLocal = pPage->minLocal;
surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
return ( surplus <= maxLocal ) ? surplus : minLocal;
}
}
/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
@@ -8678,8 +8660,7 @@ int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
@@ -8697,7 +8678,7 @@ int sqlite3BtreeInsert(
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
@@ -8807,7 +8788,7 @@ int sqlite3BtreeInsert(
|| CORRUPT_DB );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->intKey || pX->nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( pCur->eState>CURSOR_INVALID ){
@@ -8824,21 +8805,7 @@ int sqlite3BtreeInsert(
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = pBt->nPreformatSize;
if( szNew<4 ) szNew = 4;
if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
CellInfo info;
pPage->xParseCell(pPage, newCell, &info);
if( info.nPayload!=info.nLocal ){
Pgno ovfl = get4byte(&newCell[szNew-4]);
ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
}
}
}else{
rc = fillInCell(pPage, newCell, pX, &szNew);
}
rc = fillInCell(pPage, newCell, pX, &szNew);
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
@@ -8945,114 +8912,6 @@ end_insert:
return rc;
}
/*
** This function is used as part of copying the current row from cursor
** pSrc into cursor pDest. If the cursors are open on intkey tables, then
** parameter iKey is used as the rowid value when the record is copied
** into pDest. Otherwise, the record is copied verbatim.
**
** This function does not actually write the new value to cursor pDest.
** Instead, it creates and populates any required overflow pages and
** writes the data for the new cell into the BtShared.pTmpSpace buffer
** for the destination database. The size of the cell, in bytes, is left
** in BtShared.nPreformatSize. The caller completes the insertion by
** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
int rc = SQLITE_OK;
BtShared *pBt = pDest->pBt;
u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
const u8 *aIn; /* Pointer to next input buffer */
u32 nIn; /* Size of input buffer aIn[] */
u32 nRem; /* Bytes of data still to copy */
getCellInfo(pSrc);
aOut += putVarint32(aOut, pSrc->info.nPayload);
if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
if( aIn+nIn>pSrc->pPage->aDataEnd ){
return SQLITE_CORRUPT_BKPT;
}
nRem = pSrc->info.nPayload;
if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
memcpy(aOut, aIn, nIn);
pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
}else{
Pager *pSrcPager = pSrc->pBt->pPager;
u8 *pPgnoOut = 0;
Pgno ovflIn = 0;
DbPage *pPageIn = 0;
MemPage *pPageOut = 0;
u32 nOut; /* Size of output buffer aOut[] */
nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
if( nOut<pSrc->info.nPayload ){
pPgnoOut = &aOut[nOut];
pBt->nPreformatSize += 4;
}
if( nRem>nIn ){
if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
return SQLITE_CORRUPT_BKPT;
}
ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
}
do {
nRem -= nOut;
do{
assert( nOut>0 );
if( nIn>0 ){
int nCopy = MIN(nOut, nIn);
memcpy(aOut, aIn, nCopy);
nOut -= nCopy;
nIn -= nCopy;
aOut += nCopy;
aIn += nCopy;
}
if( nOut>0 ){
sqlite3PagerUnref(pPageIn);
pPageIn = 0;
rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
aIn = (const u8*)sqlite3PagerGetData(pPageIn);
ovflIn = get4byte(aIn);
aIn += 4;
nIn = pSrc->pBt->usableSize - 4;
}
}
}while( rc==SQLITE_OK && nOut>0 );
if( rc==SQLITE_OK && nRem>0 ){
Pgno pgnoNew;
MemPage *pNew = 0;
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
put4byte(pPgnoOut, pgnoNew);
if( ISAUTOVACUUM && pPageOut ){
ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
}
releasePage(pPageOut);
pPageOut = pNew;
if( pPageOut ){
pPgnoOut = pPageOut->aData;
put4byte(pPgnoOut, 0);
aOut = &pPgnoOut[4];
nOut = MIN(pBt->usableSize - 4, nRem);
}
}
}while( nRem>0 && rc==SQLITE_OK );
releasePage(pPageOut);
sqlite3PagerUnref(pPageIn);
}
return rc;
}
/*
** Delete the entry that the cursor is pointing to.
**
-3
View File
@@ -262,7 +262,6 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags);
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
#define BTREE_PREFORMAT 0x80 /* Insert is likely an append */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -362,8 +361,6 @@ void sqlite3BtreeCursorList(Btree*);
int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
-1
View File
@@ -455,7 +455,6 @@ struct BtShared {
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
int nPreformatSize; /* Size of last cell written by TransferRow() */
};
/*
+3 -10
View File
@@ -143,10 +143,6 @@ void sqlite3FinishCoding(Parse *pParse){
/* Begin by generating some termination code at the end of the
** vdbe program
*/
if( pParse->pVdbe==0 && db->init.busy ){
pParse->rc = SQLITE_DONE;
return;
}
v = sqlite3GetVdbe(pParse);
assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
@@ -1259,8 +1255,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
u8 hName;
if( (p = pParse->pNewTable)==0 ) return;
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
@@ -1272,9 +1266,8 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3Dequote(z);
hName = sqlite3StrIHash(z);
for(i=0; i<p->nCol; i++){
if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlite3DbFree(db, z);
return;
@@ -1292,7 +1285,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
pCol->hName = hName;
pCol->hName = sqlite3StrIHash(z);
sqlite3ColumnPropertiesFromName(p, pCol);
if( pType->n==0 ){
@@ -2568,7 +2561,7 @@ void sqlite3EndTable(
pCons = pEnd;
}
nName = (int)((const char *)pCons->z - zName);
p->addColOffset = 13 + nName;
p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
}
#endif
}
-3
View File
@@ -259,9 +259,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#if SQLITE_ENABLE_MATH_FUNCTIONS
"ENABLE_MATH_FUNCTIONS",
#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
-233
View File
@@ -1904,202 +1904,6 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
return 1;
}
/* Mathematical Constants */
#ifndef M_PI
# define M_PI 3.141592653589793238462643383279502884
#endif
#ifndef M_LN10
# define M_LN10 2.302585092994045684017991454684364208
#endif
#ifndef M_LN2
# define M_LN2 0.693147180559945309417232121458176568
#endif
/* Extra math functions that require linking with -lm
*/
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
/*
** Implementation SQL functions:
**
** ceil(X)
** ceiling(X)
** floor(X)
**
** The sqlite3_user_data() pointer is a pointer to the libm implementation
** of the underlying C function.
*/
static void ceilingFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
switch( sqlite3_value_numeric_type(argv[0]) ){
case SQLITE_INTEGER: {
sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
break;
}
case SQLITE_FLOAT: {
double (*x)(double) = (double(*)(double))sqlite3_user_data(context);
sqlite3_result_double(context, x(sqlite3_value_double(argv[0])));
break;
}
default: {
break;
}
}
}
/*
** On some systems, ceil() and floor() are intrinsic function. You are
** unable to take a pointer to these functions. Hence, we here wrap them
** in our own actual functions.
*/
static double xCeil(double x){ return ceil(x); }
static double xFloor(double x){ return floor(x); }
/*
** Implementation of SQL functions:
**
** ln(X) - natural logarithm
** log(X) - log X base 10
** log10(X) - log X base 10
** log(B,X) - log X base B
*/
static void logFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
double x, b, ans;
assert( argc==1 || argc==2 );
switch( sqlite3_value_numeric_type(argv[0]) ){
case SQLITE_INTEGER:
case SQLITE_FLOAT:
x = sqlite3_value_double(argv[0]);
if( x<0.0 ) return;
break;
default:
return;
}
if( argc==2 ){
switch( sqlite3_value_numeric_type(argv[0]) ){
case SQLITE_INTEGER:
case SQLITE_FLOAT:
b = x;
x = sqlite3_value_double(argv[1]);
if( x<0.0 ) return;
break;
default:
return;
}
ans = log(x)/log(b);
}else{
ans = log(x);
switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
case 1:
/* Convert from natural logarithm to log base 10 */
ans *= 1.0/M_LN10;
break;
case 2:
/* Convert from natural logarithm to log base 2 */
ans *= 1.0/M_LN2;
break;
default:
break;
}
}
sqlite3_result_double(context, ans);
}
/*
** Functions to converts degrees to radians and radians to degrees.
*/
static double degToRad(double x){ return x*(M_PI/180.0); }
static double radToDeg(double x){ return x*(180.0/M_PI); }
/*
** Implementation of 1-argument SQL math functions:
**
** exp(X) - Compute e to the X-th power
*/
static void math1Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int type0;
double v0, ans;
double (*x)(double);
assert( argc==1 );
type0 = sqlite3_value_numeric_type(argv[0]);
if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
v0 = sqlite3_value_double(argv[0]);
x = (double(*)(double))sqlite3_user_data(context);
ans = x(v0);
sqlite3_result_double(context, ans);
}
/*
** Implementation of 2-argument SQL math functions:
**
** power(X,Y) - Compute X to the Y-th power
*/
static void math2Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int type0, type1;
double v0, v1, ans;
double (*x)(double,double);
assert( argc==2 );
type0 = sqlite3_value_numeric_type(argv[0]);
if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
type1 = sqlite3_value_numeric_type(argv[1]);
if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
v0 = sqlite3_value_double(argv[0]);
v1 = sqlite3_value_double(argv[1]);
x = (double(*)(double,double))sqlite3_user_data(context);
ans = x(v0, v1);
sqlite3_result_double(context, ans);
}
/*
** Implementation of 2-argument SQL math functions:
**
** power(X,Y) - Compute X to the Y-th power
*/
static void piFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==0 );
sqlite3_result_double(context, M_PI);
}
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
/*
** Implementation of sign(X) function.
*/
static void signFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int type0;
double x;
UNUSED_PARAMETER(argc);
assert( argc==1 );
type0 = sqlite3_value_numeric_type(argv[0]);
if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
x = sqlite3_value_double(argv[0]);
sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
}
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -2218,43 +2022,6 @@ void sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
MFUNCTION(ceil, 1, xCeil, ceilingFunc ),
MFUNCTION(ceiling, 1, xCeil, ceilingFunc ),
MFUNCTION(floor, 1, xFloor, ceilingFunc ),
#if SQLITE_HAVE_C99_MATH_FUNCS
MFUNCTION(trunc, 1, trunc, ceilingFunc ),
#endif
FUNCTION(ln, 1, 0, 0, logFunc ),
FUNCTION(log, 1, 1, 0, logFunc ),
FUNCTION(log10, 1, 1, 0, logFunc ),
FUNCTION(log2, 1, 2, 0, logFunc ),
FUNCTION(log, 2, 0, 0, logFunc ),
MFUNCTION(exp, 1, exp, math1Func ),
MFUNCTION(pow, 2, pow, math2Func ),
MFUNCTION(power, 2, pow, math2Func ),
MFUNCTION(mod, 2, fmod, math2Func ),
MFUNCTION(acos, 1, acos, math1Func ),
MFUNCTION(asin, 1, asin, math1Func ),
MFUNCTION(atan, 1, atan, math1Func ),
MFUNCTION(atan2, 2, atan2, math2Func ),
MFUNCTION(cos, 1, cos, math1Func ),
MFUNCTION(sin, 1, sin, math1Func ),
MFUNCTION(tan, 1, tan, math1Func ),
MFUNCTION(cosh, 1, cosh, math1Func ),
MFUNCTION(sinh, 1, sinh, math1Func ),
MFUNCTION(tanh, 1, tanh, math1Func ),
#if SQLITE_HAVE_C99_MATH_FUNCS
MFUNCTION(acosh, 1, acosh, math1Func ),
MFUNCTION(asinh, 1, asinh, math1Func ),
MFUNCTION(atanh, 1, atanh, math1Func ),
#endif
MFUNCTION(sqrt, 1, sqrt, math1Func ),
MFUNCTION(radians, 1, degToRad, math1Func ),
MFUNCTION(degrees, 1, radToDeg, math1Func ),
FUNCTION(pi, 0, 0, 0, piFunc ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
};
+2 -3
View File
@@ -301,10 +301,9 @@ int sqlite3PendingByte = 0x40000000;
#endif
/*
** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
** Flags for select tracing and the ".selecttrace" macro of the CLI
*/
u32 sqlite3SelectTrace = 0;
u32 sqlite3WhereTrace = 0;
u32 sqlite3_unsupported_selecttrace = 0;
#include "opcodes.h"
/*
+60 -208
View File
@@ -370,9 +370,7 @@ static int autoIncBegin(
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
sqlite3ParserAddCleanup(pToplevel, sqlite3DbFree, pInfo);
testcase( pParse->earlyCleanup );
if( pParse->db->mallocFailed ) return 0;
if( pInfo==0 ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
pInfo->pTab = pTab;
@@ -977,7 +975,6 @@ void sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
Upsert *pNx;
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
pTab->zName);
@@ -991,17 +988,13 @@ void sqlite3Insert(
goto insert_cleanup;
}
pTabList->a[0].iCursor = iDataCur;
pNx = pUpsert;
do{
pNx->pUpsertSrc = pTabList;
pNx->regData = regData;
pNx->iDataCur = iDataCur;
pNx->iIdxCur = iIdxCur;
if( pNx->pUpsertTarget ){
sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx);
}
pNx = pNx->pNextUpsert;
}while( pNx!=0 );
pUpsert->pUpsertSrc = pTabList;
pUpsert->regData = regData;
pUpsert->iDataCur = iDataCur;
pUpsert->iIdxCur = iIdxCur;
if( pUpsert->pUpsertTarget ){
sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
}
}
#endif
@@ -1406,70 +1399,6 @@ int sqlite3ExprReferencesUpdatedColumn(
return w.eCode!=0;
}
/*
** The sqlite3GenerateConstraintChecks() routine usually wants to visit
** the indexes of a table in the order provided in the Table->pIndex list.
** However, sometimes (rarely - when there is an upsert) it wants to visit
** the indexes in a different order. The following data structures accomplish
** this.
**
** The IndexIterator object is used to walk through all of the indexes
** of a table in either Index.pNext order, or in some other order established
** by an array of IndexListTerm objects.
*/
typedef struct IndexListTerm IndexListTerm;
typedef struct IndexIterator IndexIterator;
struct IndexIterator {
int eType; /* 0 for Index.pNext list. 1 for an array of IndexListTerm */
int i; /* Index of the current item from the list */
union {
struct { /* Use this object for eType==0: A Index.pNext list */
Index *pIdx; /* The current Index */
} lx;
struct { /* Use this object for eType==1; Array of IndexListTerm */
int nIdx; /* Size of the array */
IndexListTerm *aIdx; /* Array of IndexListTerms */
} ax;
} u;
};
/* When IndexIterator.eType==1, then each index is an array of instances
** of the following object
*/
struct IndexListTerm {
Index *p; /* The index */
int ix; /* Which entry in the original Table.pIndex list is this index*/
};
/* Return the first index on the list */
static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){
assert( pIter->i==0 );
if( pIter->eType ){
*pIx = pIter->u.ax.aIdx[0].ix;
return pIter->u.ax.aIdx[0].p;
}else{
*pIx = 0;
return pIter->u.lx.pIdx;
}
}
/* Return the next index from the list. Return NULL when out of indexes */
static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
if( pIter->eType ){
int i = ++pIter->i;
if( i>=pIter->u.ax.nIdx ){
*pIx = i;
return 0;
}
*pIx = pIter->u.ax.aIdx[i].ix;
return pIter->u.ax.aIdx[i].p;
}else{
++(*pIx);
pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
return pIter->u.lx.pIdx;
}
}
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
@@ -1578,7 +1507,7 @@ void sqlite3GenerateConstraintChecks(
){
Vdbe *v; /* VDBE under constrution */
Index *pIdx; /* Pointer to one of the indices */
Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */
Index *pPk = 0; /* The PRIMARY KEY index */
sqlite3 *db; /* Database connection */
int i; /* loop counter */
int ix; /* Index loop counter */
@@ -1586,11 +1515,11 @@ void sqlite3GenerateConstraintChecks(
int onError; /* Conflict resolution strategy */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */
u8 isUpdate; /* True if this is an UPDATE operation */
Index *pUpIdx = 0; /* Index to which to apply the upsert */
u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */
int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
/* Variables associated with retesting uniqueness constraints after
@@ -1600,7 +1529,6 @@ void sqlite3GenerateConstraintChecks(
int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
int nReplaceTrig = 0; /* Number of replace triggers coded */
IndexIterator sIdxIter; /* Index iterator */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -1798,63 +1726,19 @@ void sqlite3GenerateConstraintChecks(
** list of indexes attached to a table puts all OE_Replace indexes last
** in the list. See sqlite3CreateIndex() for where that happens.
*/
sIdxIter.eType = 0;
sIdxIter.i = 0;
sIdxIter.u.ax.aIdx = 0; /* Silence harmless compiler warning */
sIdxIter.u.lx.pIdx = pTab->pIndex;
if( pUpsert ){
if( pUpsert->pUpsertTarget==0 ){
/* There is just on ON CONFLICT clause and it has no constraint-target */
assert( pUpsert->pNextUpsert==0 );
if( pUpsert->isDoUpdate==0 ){
/* A single ON CONFLICT DO NOTHING clause, without a constraint-target.
** Make all unique constraint resolution be OE_Ignore */
overrideError = OE_Ignore;
pUpsert = 0;
}else{
/* A single ON CONFLICT DO UPDATE. Make all resolutions OE_Update */
overrideError = OE_Update;
}
}else if( pTab->pIndex!=0 ){
/* Otherwise, we'll need to run the IndexListTerm array version of the
** iterator to ensure that all of the ON CONFLICT conditions are
** checked first and in order. */
int nIdx, jj;
u64 nByte;
Upsert *pTerm;
u8 *bUsed;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
assert( aRegIdx[nIdx]>0 );
}
sIdxIter.eType = 1;
sIdxIter.u.ax.nIdx = nIdx;
nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx;
sIdxIter.u.ax.aIdx = sqlite3DbMallocZero(db, nByte);
if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */
bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx];
pUpsert->pToFree = sIdxIter.u.ax.aIdx;
for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){
if( pTerm->pUpsertTarget==0 ) break;
if( pTerm->pUpsertIdx==0 ) continue; /* Skip ON CONFLICT for the IPK */
jj = 0;
pIdx = pTab->pIndex;
while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){
pIdx = pIdx->pNext;
jj++;
}
if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */
bUsed[jj] = 1;
sIdxIter.u.ax.aIdx[i].p = pIdx;
sIdxIter.u.ax.aIdx[i].ix = jj;
i++;
}
for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){
if( bUsed[jj] ) continue;
sIdxIter.u.ax.aIdx[i].p = pIdx;
sIdxIter.u.ax.aIdx[i].ix = jj;
i++;
}
assert( i==nIdx );
/* An ON CONFLICT DO NOTHING clause, without a constraint-target.
** Make all unique constraint resolution be OE_Ignore */
assert( pUpsert->pUpsertSet==0 );
overrideError = OE_Ignore;
pUpsert = 0;
}else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
/* If the constraint-target uniqueness check must be run first.
** Jump to that uniqueness check now */
upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
VdbeComment((v, "UPSERT constraint goes first"));
}
}
@@ -1917,20 +1801,11 @@ void sqlite3GenerateConstraintChecks(
}
/* figure out whether or not upsert applies in this case */
if( pUpsert ){
pUpsertClause = sqlite3UpsertOfIndex(pUpsert,0);
if( pUpsertClause!=0 ){
if( pUpsertClause->isDoUpdate==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
}
}
if( pUpsertClause!=pUpsert ){
/* The first ON CONFLICT clause has a conflict target other than
** the IPK. We have to jump ahead to that first ON CONFLICT clause
** and then come back here and deal with the IPK afterwards */
upsertIpkDelay = sqlite3VdbeAddOp0(v, OP_Goto);
if( pUpsert && pUpsert->pUpsertIdx==0 ){
if( pUpsert->pUpsertSet==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
}
}
@@ -1940,7 +1815,7 @@ void sqlite3GenerateConstraintChecks(
** the UNIQUE constraints have run.
*/
if( onError==OE_Replace /* IPK rule is REPLACE */
&& onError!=overrideError /* Rules for other constraints are different */
&& onError!=overrideError /* Rules for other contraints are different */
&& pTab->pIndex /* There exist other constraints */
){
ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
@@ -2037,9 +1912,7 @@ void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrRowidOk);
if( pUpsert && pUpsertClause!=pUpsert ){
upsertIpkReturn = sqlite3VdbeAddOp0(v, OP_Goto);
}else if( ipkTop ){
if( ipkTop ){
ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, ipkTop-1);
}
@@ -2052,10 +1925,7 @@ void sqlite3GenerateConstraintChecks(
** This loop also handles the case of the PRIMARY KEY index for a
** WITHOUT ROWID table.
*/
for(pIdx = indexIteratorFirst(&sIdxIter, &ix);
pIdx;
pIdx = indexIteratorNext(&sIdxIter, &ix)
){
for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
int regIdx; /* Range of registers hold conent for pIdx */
int regR; /* Range of registers holding conflicting PK */
int iThisCur; /* Cursor for this UNIQUE index */
@@ -2063,14 +1933,15 @@ void sqlite3GenerateConstraintChecks(
int addrConflictCk; /* First opcode in the conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
if( pUpsert ){
pUpsertClause = sqlite3UpsertOfIndex(pUpsert, pIdx);
if( upsertIpkDelay && pUpsertClause==pUpsert ){
sqlite3VdbeJumpHere(v, upsertIpkDelay);
}
if( pUpIdx==pIdx ){
addrUniqueOk = upsertJump+1;
upsertBypass = sqlite3VdbeGoto(v, 0);
VdbeComment((v, "Skip upsert subroutine"));
sqlite3VdbeJumpHere(v, upsertJump);
}else{
addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
}
addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
if( bAffinityDone==0 ){
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
@@ -2141,8 +2012,8 @@ void sqlite3GenerateConstraintChecks(
}
/* Figure out if the upsert clause applies to this index */
if( pUpsertClause ){
if( pUpsertClause->isDoUpdate==0 ){
if( pUpIdx==pIdx ){
if( pUpsert->pUpsertSet==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
@@ -2180,7 +2051,7 @@ void sqlite3GenerateConstraintChecks(
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */
regR = pIdx==pPk ? regIdx : sqlite3GetTempRange(pParse, nPkField);
regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
if( isUpdate || onError==OE_Replace ){
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
@@ -2332,16 +2203,13 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
if( pUpsertClause
&& upsertIpkReturn
&& sqlite3UpsertNextIsIPK(pUpsertClause)
){
sqlite3VdbeGoto(v, upsertIpkDelay+1);
sqlite3VdbeJumpHere(v, upsertIpkReturn);
upsertIpkReturn = 0;
if( pUpIdx==pIdx ){
sqlite3VdbeGoto(v, upsertJump+1);
sqlite3VdbeJumpHere(v, upsertBypass);
}else{
sqlite3VdbeResolveLabel(v, addrUniqueOk);
}
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
/* If the IPK constraint is a REPLACE, run it last */
@@ -2880,7 +2748,6 @@ static int xferOptimization(
iDest = pParse->nTab++;
regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
regData = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
@@ -2916,13 +2783,11 @@ static int xferOptimization(
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
sqlite3VdbeVerifyAbortable(v, onError);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, onError, pDest);
sqlite3VdbeJumpHere(v, addr2);
}
sqlite3VdbeVerifyAbortable(v, onError);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, onError, pDest);
sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){
addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
@@ -2930,26 +2795,16 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
if( db->mDbFlags & DBFLAG_Vacuum ){
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
}else{
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( db->xPreUpdateCallback ){
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
insFlags &= ~OPFLAG_PREFORMAT;
}else
#endif
{
sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
}
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
(char*)pDest, P4_TABLE);
(char*)pDest, P4_TABLE);
sqlite3VdbeChangeP5(v, insFlags);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -2991,16 +2846,13 @@ static int xferOptimization(
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
idxInsFlags = OPFLAG_USESEEKRESULT;
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc);
}
}else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
idxInsFlags |= OPFLAG_NCHANGE;
}
if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
}
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
+1 -20
View File
@@ -4255,26 +4255,7 @@ int sqlite3_test_control(int op, ...){
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
**
** "ptr" is a pointer to a u32.
**
** op==0 Store the current sqlite3SelectTrace in *ptr
** op==1 Set sqlite3SelectTrace to the value *ptr
** op==3 Store the current sqlite3WhereTrace in *ptr
** op==3 Set sqlite3WhereTrace to the value *ptr
*/
case SQLITE_TESTCTRL_TRACEFLAGS: {
int opTrace = va_arg(ap, int);
u32 *ptr = va_arg(ap, u32*);
switch( opTrace ){
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
+1 -8
View File
@@ -129,8 +129,6 @@ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_TEST
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
&& op!=SQLITE_FCNTL_CKPT_DONE
&& op!=SQLITE_FCNTL_CKPT_START
){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
@@ -141,12 +139,7 @@ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
** The core must call OsFileControl() though, not OsFileControlHint(),
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
** means the commit really has failed and an error should be returned
** to the user.
**
** The CKPT_DONE and CKPT_START file-controls are write-only signals
** to the cksumvfs. Their return code is meaningless and is ignored
** by the SQLite core, so there is no point in simulating OOMs for them.
*/
** to the user. */
DO_OS_MALLOC_TEST(id);
}
#endif
+5 -7
View File
@@ -960,14 +960,12 @@ cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES.
//%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
upsert(A) ::= . { A = 0; }
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW)
DO UPDATE SET setlist(Z) where_opt(W) upsert(N).
{ A = sqlite3UpsertNew(pParse->db,T,TW,Z,W,N);}
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING upsert(N).
{ A = sqlite3UpsertNew(pParse->db,T,TW,0,0,N); }
DO UPDATE SET setlist(Z) where_opt(W).
{ A = sqlite3UpsertNew(pParse->db,T,TW,Z,W);}
upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING.
{ A = sqlite3UpsertNew(pParse->db,T,TW,0,0); }
upsert(A) ::= ON CONFLICT DO NOTHING.
{ A = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W).
{ A = sqlite3UpsertNew(pParse->db,0,0,Z,W,0);}
{ A = sqlite3UpsertNew(pParse->db,0,0,0,0); }
%type insert_cmd {int}
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
+18 -74
View File
@@ -102,18 +102,11 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[3]==0 ){
corruptSchema(pData, argv[1], 0);
}else if( argv[4]
&& 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
&& 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
}else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
**
** No other valid SQL statement, other than the variable CREATE statements,
** can begin with the letters "C" and "R". Thus, it is not possible run
** any other kind of statement while parsing the schema, even a corrupt
** schema.
*/
int rc;
u8 saved_iDb = db->init.iDb;
@@ -570,16 +563,8 @@ void sqlite3ParserReset(Parse *pParse){
agginfoFree(db, pThis);
pThis = pNext;
}
while( pParse->pCleanup ){
ParseCleanup *pThis = pParse->pCleanup;
pParse->pCleanup = pThis->pNext;
pThis->xCleanup(db, pThis->pPtr);
sqlite3DbFree(db, pThis);
}
sqlite3DbFree(db, pParse->aLabel);
if( pParse->pConstExpr ){
sqlite3ExprListDelete(db, pParse->pConstExpr);
}
sqlite3ExprListDelete(db, pParse->pConstExpr);
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
@@ -588,45 +573,6 @@ void sqlite3ParserReset(Parse *pParse){
pParse->disableLookaside = 0;
}
/*
** Add a new cleanup operation to a Parser. The cleanup should happen when
** the parser object is destroyed. But, beware: the cleanup might happen
** immediately.
**
** Use this mechanism for uncommon cleanups. There is a higher setup
** cost for this mechansim (an extra malloc), so it should not be used
** for common cleanups that happen on most calls. But for less
** common cleanups, we save a single NULL-pointer comparison in
** sqlite3ParserReset(), which reduces the total CPU cycle count.
**
** If a memory allocation error occurs, then the cleanup happens immediately.
** When eithr SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
** pParse->earlyCleanup flag is set in that case. Calling code show verify
** that test cases exist for which this happens, to guard against possible
** use-after-free errors following an OOM. The preferred way to do this is
** to immediately follow the call to this routine with:
**
** testcase( pParse->earlyCleanup );
*/
void sqlite3ParserAddCleanup(
Parse *pParse, /* Destroy when this Parser finishes */
void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */
void *pPtr /* Pointer to object to be cleaned up */
){
ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
if( pCleanup ){
pCleanup->pNext = pParse->pCleanup;
pParse->pCleanup = pCleanup;
pCleanup->pPtr = pPtr;
pCleanup->xCleanup = xCleanup;
}else{
xCleanup(pParse->db, pPtr);
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
pParse->earlyCleanup = 1;
#endif
}
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -725,6 +671,12 @@ static int sqlite3Prepare(
}
assert( 0==sParse.nQueryLoop );
if( sParse.rc==SQLITE_DONE ){
sParse.rc = SQLITE_OK;
}
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( pzTail ){
*pzTail = sParse.zTail;
}
@@ -735,28 +687,20 @@ static int sqlite3Prepare(
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
}
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( sParse.pVdbe ){
sqlite3VdbeFinalize(sParse.pVdbe);
}
assert( 0==(*ppStmt) );
rc = sParse.rc;
if( zErrMsg ){
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
sqlite3DbFree(db, zErrMsg);
}else{
sqlite3Error(db, rc);
}
rc = sParse.rc;
if( rc!=SQLITE_OK ){
if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
assert(!(*ppStmt));
}else{
assert( zErrMsg==0 );
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
rc = SQLITE_OK;
sqlite3ErrorClear(db);
}
if( zErrMsg ){
sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
sqlite3DbFree(db, zErrMsg);
}else{
sqlite3Error(db, rc);
}
/* Delete any TriggerPrg structures allocated while parsing this statement. */
while( sParse.pTriggerPrg ){
+69 -154
View File
@@ -347,7 +347,7 @@ static void addWhereTerm(
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pEq, EP_NoReduce);
pEq->iRightJoinTable = pE2->iTable;
pEq->iRightJoinTable = (i16)pE2->iTable;
}
*ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq);
}
@@ -383,7 +383,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = iTable;
p->iRightJoinTable = (i16)iTable;
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
@@ -3649,88 +3649,6 @@ static void recomputeColumnsUsed(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Assign new cursor numbers to each of the items in pSrc. For each
** new cursor number assigned, set an entry in the aCsrMap[] array
** to map the old cursor number to the new:
**
** aCsrMap[iOld] = iNew;
**
** The array is guaranteed by the caller to be large enough for all
** existing cursor numbers in pSrc.
**
** If pSrc contains any sub-selects, call this routine recursively
** on the FROM clause of each such sub-select, with iExcept set to -1.
*/
static void srclistRenumberCursors(
Parse *pParse, /* Parse context */
int *aCsrMap, /* Array to store cursor mappings in */
SrcList *pSrc, /* FROM clause to renumber */
int iExcept /* FROM clause item to skip */
){
int i;
struct SrcList_item *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( i!=iExcept ){
Select *p;
pItem->iCursor = aCsrMap[pItem->iCursor] = pParse->nTab++;
for(p=pItem->pSelect; p; p=p->pPrior){
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
}
}
}
}
/*
** Expression walker callback used by renumberCursors() to update
** Expr objects to match newly assigned cursor numbers.
*/
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
int *aCsrMap = pWalker->u.aiCol;
if( pExpr->op==TK_COLUMN && aCsrMap[pExpr->iTable] ){
pExpr->iTable = aCsrMap[pExpr->iTable];
}
if( ExprHasProperty(pExpr, EP_FromJoin) && aCsrMap[pExpr->iRightJoinTable] ){
pExpr->iRightJoinTable = aCsrMap[pExpr->iRightJoinTable];
}
return WRC_Continue;
}
/*
** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
** of the SELECT statement passed as the second argument, and to each
** cursor in the FROM clause of any FROM clause sub-selects, recursively.
** Except, do not assign a new cursor number to the iExcept'th element in
** the FROM clause of (*p). Update all expressions and other references
** to refer to the new cursor numbers.
**
** Argument aCsrMap is an array that may be used for temporary working
** space. Two guarantees are made by the caller:
**
** * the array is larger than the largest cursor number used within the
** select statement passed as an argument, and
**
** * the array entries for all cursor numbers that do *not* appear in
** FROM clauses of the select statement as described above are
** initialized to zero.
*/
static void renumberCursors(
Parse *pParse, /* Parse context */
Select *p, /* Select to renumber cursors within */
int iExcept, /* FROM clause item to skip */
int *aCsrMap /* Working space */
){
Walker w;
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
memset(&w, 0, sizeof(w));
w.u.aiCol = aCsrMap;
w.xExprCallback = renumberCursorsCb;
w.xSelectCallback = sqlite3SelectWalkNoop;
sqlite3WalkSelect(&w, p);
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
@@ -3825,9 +3743,9 @@ static void renumberCursors(
** (17c) every term within the subquery compound must have a FROM clause
** (17d) the outer query may not be
** (17d1) aggregate, or
** (17d2) DISTINCT
** (17e) the subquery may not contain window functions, and
** (17f) the subquery must not be the RHS of a LEFT JOIN.
** (17d2) DISTINCT, or
** (17d3) a join.
** (17e) the subquery may not contain window functions
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -3843,8 +3761,8 @@ static void renumberCursors(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
** ORDER BY clause of the parent must be copies of a term returned
** by the parent query.
** ORDER BY clause of the parent must be simple references to
** columns of the sub-query.
**
** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
@@ -3860,8 +3778,9 @@ static void renumberCursors(
**
** (22) The subquery may not be a recursive CTE.
**
** (23) If the outer query is a recursive CTE, then the sub-query may not be
** a compound query. This restriction is because transforming the
** (**) Subsumed into restriction (17d3). Was: If the outer query is
** a recursive CTE, then the sub-query may not be a compound query.
** This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
@@ -3906,7 +3825,6 @@ static int flattenSubquery(
struct SrcList_item *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -4002,14 +3920,13 @@ static int flattenSubquery(
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
if( isAgg || (p->selFlags & SF_Distinct)!=0 || isLeftJoin>0 ){
return 0; /* (17d1), (17d2), or (17f) */
if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
return 0; /* (17d1), (17d2), or (17d3) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
assert( (pSub->selFlags & SF_Recursive)==0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
@@ -4030,15 +3947,16 @@ static int flattenSubquery(
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
if( pSrc->nSrc>1 ){
aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
}
}
/* Ex-restriction (23):
** The only way that the recursive part of a CTE can contain a compound
** subquery is for the subquery to be one term of a join. But if the
** subquery is a join, then the flattening has already been stopped by
** restriction (17d3)
*/
assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
pSub->selId, pSub, iFrom));
@@ -4049,17 +3967,6 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
/* Delete the transient structures associated with thesubquery */
pSub1 = pSubitem->pSelect;
sqlite3DbFree(db, pSubitem->zDatabase);
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
pSubitem->pSelect = 0;
assert( pSubitem->pOn==0 );
/* If the sub-query is a compound SELECT statement, then (by restrictions
** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
@@ -4098,22 +4005,18 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
Table *pItemTab = pSubitem->pTab;
pSubitem->pTab = 0;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
p->op = TK_ALL;
pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
if( aCsrMap && db->mallocFailed==0 ){
renumberCursors(pParse, pNew, iFrom, aCsrMap);
}
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
@@ -4121,14 +4024,25 @@ static int flattenSubquery(
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
assert( pSubitem->pSelect==0 );
}
sqlite3DbFree(db, aCsrMap);
if( db->mallocFailed ){
pSubitem->pSelect = pSub1;
return 1;
if( db->mallocFailed ) return 1;
}
/* Begin flattening the iFrom-th entry of the FROM clause
** in the outer query.
*/
pSub = pSub1 = pSubitem->pSelect;
/* Delete the transient table structure associated with the
** subquery
*/
sqlite3DbFree(db, pSubitem->zDatabase);
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
pSubitem->pSelect = 0;
/* Defer deleting the Table object associated with the
** subquery until code generation is
** complete, since there may still exist Expr.pTab entries that
@@ -4140,10 +4054,8 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel,
(void(*)(sqlite3*,void*))sqlite3DeleteTable,
pTabToDel);
testcase( pToplevel->earlyCleanup );
pTabToDel->pNextZombie = pToplevel->pZombieTab;
pToplevel->pZombieTab = pTabToDel;
}else{
pTabToDel->nTabRef--;
}
@@ -4163,7 +4075,6 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
@@ -4172,10 +4083,16 @@ static int flattenSubquery(
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
if( pParent==p ){
jointype = pSubitem->fg.jointype; /* First time through the loop */
if( pSrc ){
assert( pParent==p ); /* First time through the loop */
jointype = pSubitem->fg.jointype;
}else{
assert( pParent!=p ); /* 2nd and subsequent times through the loop */
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc==0 ) break;
pParent->pSrc = pSrc;
}
/* The subquery uses a single slot of the FROM clause of the outer
** query. If the subquery has more than one element in its FROM clause,
** then expand the outer query to make space for it to hold all elements
@@ -4293,7 +4210,7 @@ static int flattenSubquery(
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -4858,16 +4775,12 @@ static struct Cte *searchWith(
** statement with which it is associated.
*/
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
if( pWith ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
if( bFree ){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3WithDelete,
pWith);
testcase( pParse->earlyCleanup );
}
if( bFree ) pParse->pWithToFree = pWith;
}
}
@@ -5743,7 +5656,7 @@ static void havingToWhere(Parse *pParse, Select *p){
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
#if SELECTTRACE_ENABLED
if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
if( sWalker.eCode && (sqlite3_unsupported_selecttrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5865,7 +5778,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
p->selFlags &= ~SF_Aggregate;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5918,7 +5831,7 @@ int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -5943,7 +5856,7 @@ int sqlite3Select(
}
assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x104 ){
if( sqlite3_unsupported_selecttrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5978,7 +5891,7 @@ int sqlite3Select(
goto select_end;
}
#if SELECTTRACE_ENABLED
if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
if( p->pWin && (sqlite3_unsupported_selecttrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6085,7 +5998,7 @@ int sqlite3Select(
rc = multiSelect(pParse, p, pDest);
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -6104,7 +6017,7 @@ int sqlite3Select(
&& propagateConstants(pParse, p)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6192,7 +6105,7 @@ int sqlite3Select(
(pItem->fg.jointype & JT_OUTER)!=0)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
@@ -6292,7 +6205,7 @@ int sqlite3Select(
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6328,7 +6241,7 @@ int sqlite3Select(
assert( sDistinct.isTnct );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6576,7 +6489,7 @@ int sqlite3Select(
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
@@ -6978,13 +6891,15 @@ select_end:
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
assert( pExpr!=0 );
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
assert( pExpr!=0 );
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
@@ -6993,7 +6908,7 @@ select_end:
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+45 -62
View File
@@ -1085,12 +1085,12 @@ struct ShellState {
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
u8 autoEQPtest; /* autoEQP is in test mode */
u8 autoEQPtrace; /* autoEQP is in trace mode */
u8 statsOn; /* True to display memory stats before each finalize */
u8 scanstatsOn; /* True to display scan stats before each finalize */
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
@@ -2591,7 +2591,7 @@ static int display_stats(
if( pArg==0 || pArg->out==0 ) return 0;
out = pArg->out;
if( pArg->pStmt && pArg->statsOn==2 ){
if( pArg->pStmt && (pArg->statsOn & 2) ){
int nCol, i, x;
sqlite3_stmt *pStmt = pArg->pStmt;
char z[100];
@@ -2615,14 +2615,6 @@ static int display_stats(
}
}
if( pArg->statsOn==3 ){
if( pArg->pStmt ){
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "VM-steps: %d\n", iCur);
}
return 0;
}
displayStatLine(pArg, "Memory Used:",
"%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
displayStatLine(pArg, "Number of Outstanding Allocations:",
@@ -2889,18 +2881,31 @@ static void explain_data_delete(ShellState *p){
/*
** Disable and restore .wheretrace and .selecttrace settings.
*/
static unsigned int savedSelectTrace;
static unsigned int savedWhereTrace;
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
extern unsigned int sqlite3_unsupported_selecttrace;
static int savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
extern int sqlite3WhereTrace;
static int savedWhereTrace;
#endif
static void disable_debug_trace_modes(void){
unsigned int zero = 0;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
savedSelectTrace = sqlite3_unsupported_selecttrace;
sqlite3_unsupported_selecttrace = 0;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
savedWhereTrace = sqlite3WhereTrace;
sqlite3WhereTrace = 0;
#endif
}
static void restore_debug_trace_modes(void){
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
sqlite3_unsupported_selecttrace = savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
sqlite3WhereTrace = savedWhereTrace;
#endif
}
/* Create the TEMP table used to store parameter bindings */
@@ -4055,11 +4060,7 @@ static const char *(azHelp[]) = {
".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
".show Show the current values for various settings",
".stats ?ARG? Show stats or turn stats on or off",
" off Turn off automatic stat display",
" on Turn on automatic stat display",
" stmt Show statement stats",
" vmstep Show the virtual machine step count only",
".stats ?on|off? Show stats or turn stats on or off",
#ifndef SQLITE_NOHAVE_SYSTEM
".system CMD ARGS... Run CMD ARGS... in a system shell",
#endif
@@ -7875,17 +7876,16 @@ static int do_meta_command(char *zLine, ShellState *p){
int ctrlCode; /* Integer code for that option */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{ "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
{ "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
{ "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
/* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
{ "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
{ "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
/* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
{ "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
{ "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
{ "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
{ "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
/* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
{ "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
{ "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
{ "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
{ "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
/* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
};
int filectrl = -1;
int iCtrl = -1;
@@ -7972,7 +7972,6 @@ static int do_meta_command(char *zLine, ShellState *p){
isOk = 1;
break;
}
case SQLITE_FCNTL_DATA_VERSION:
case SQLITE_FCNTL_HAS_MOVED: {
int x;
if( nArg!=2 ) break;
@@ -8681,9 +8680,9 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif /* SQLITE_DEBUG */
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
char *zNewFilename; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */
session_close_all(p);
close_db(p->db);
@@ -8695,7 +8694,7 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openFlags = 0;
p->szMax = 0;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
const char *z = azArg[iName];
if( optionMatch(z,"new") ){
newFlag = 1;
@@ -8721,15 +8720,10 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
goto meta_command_exit;
}else if( zNewFilename ){
utf8_printf(stderr, "extra argument: \"%s\"\n", z);
rc = 1;
goto meta_command_exit;
}else{
zNewFilename = sqlite3_mprintf("%s", z);
}
}
/* If a filename is specified, try to open it first */
zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
@@ -9252,10 +9246,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
sqlite3_unsupported_selecttrace = nArg>=2 ? (int)integerValue(azArg[1]) : 0xffff;
}else
#endif
#if defined(SQLITE_ENABLE_SESSION)
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
@@ -9736,7 +9731,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
static const char *azBool[] = { "off", "on", "trigger", "full"};
const char *zOut;
int i;
if( nArg!=1 ){
raw_printf(stderr, "Usage: .show\n");
@@ -9761,13 +9755,7 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(p->out,"%12.12s: ", "rowseparator");
output_c_string(p->out, p->rowSeparator);
raw_printf(p->out, "\n");
switch( p->statsOn ){
case 0: zOut = "off"; break;
default: zOut = "on"; break;
case 2: zOut = "stmt"; break;
case 3: zOut = "vmstep"; break;
}
utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
utf8_printf(p->out, "%12.12s: ", "width");
for (i=0;i<p->nWidth;i++) {
raw_printf(p->out, "%d ", p->colWidth[i]);
@@ -9779,17 +9767,11 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
if( nArg==2 ){
if( strcmp(azArg[1],"stmt")==0 ){
p->statsOn = 2;
}else if( strcmp(azArg[1],"vmstep")==0 ){
p->statsOn = 3;
}else{
p->statsOn = (u8)booleanValue(azArg[1]);
}
p->statsOn = (u8)booleanValue(azArg[1]);
}else if( nArg==1 ){
display_stats(p->db, p, 0);
}else{
raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
raw_printf(stderr, "Usage: .stats ?on|off?\n");
rc = 1;
}
}else
@@ -10323,10 +10305,11 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
}else
#endif
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
int j;
+1 -3
View File
@@ -3499,7 +3499,6 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** Use "ro" instead: "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -7766,8 +7765,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
#define SQLITE_TESTCTRL_TRACEFLAGS 31
#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
+25 -87
View File
@@ -119,18 +119,6 @@
# define MSVC_VERSION 0
#endif
/*
** Some C99 functions in "math.h" are only present for MSVC when its version
** is associated with Visual Studio 2013 or higher.
*/
#ifndef SQLITE_HAVE_C99_MATH_FUNCS
# if MSVC_VERSION==0 || MSVC_VERSION>=1800
# define SQLITE_HAVE_C99_MATH_FUNCS (1)
# else
# define SQLITE_HAVE_C99_MATH_FUNCS (0)
# endif
#endif
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
@@ -214,8 +202,7 @@
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
#if GCC_VERSION>=4007000 || \
(__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
@@ -997,14 +984,15 @@ typedef INT16_TYPE LogEst;
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
#if !defined(SQLITE_AMALGAMATION)
extern u32 sqlite3SelectTrace;
#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
#else
# define SELECTTRACE_ENABLED 0
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE))
#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
if(sqlite3_unsupported_selecttrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
@@ -1012,19 +1000,6 @@ extern u32 sqlite3SelectTrace;
# define SELECTTRACE_ENABLED 0
#endif
/*
** Macros for "wheretrace"
*/
extern u32 sqlite3WhereTrace;
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define WHERETRACE(K,X)
#endif
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@@ -1154,7 +1129,6 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
@@ -1876,9 +1850,6 @@ struct FuncDestructor {
** a single query. The iArg is ignored. The user-data is always set
** to a NULL pointer. The bNC parameter is not used.
**
** MFUNCTION(zName, nArg, xPtr, xFunc)
** For math-library functions. xPtr is an arbitrary pointer.
**
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
** Used for "pure" date/time functions, this macro is like DFUNCTION
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
@@ -1914,9 +1885,6 @@ struct FuncDestructor {
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
@@ -2187,6 +2155,7 @@ struct Table {
#endif
Trigger *pTrigger; /* List of triggers stored in pSchema */
Schema *pSchema; /* Schema that contains this table */
Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -2315,22 +2284,16 @@ struct FKey {
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
** UPDATE applies to insert operations only and means that the insert
** is omitted and the DO UPDATE clause of an upsert is run instead.
**
** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
** key is set to NULL. SETDFLT means that the foreign key is set
** to its default value. CASCADE means that a DELETE or UPDATE of the
** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
** The OE_Default value is a place holder that means to use whatever
** conflict resolution algorthm is required from context.
**
** The following symbolic values are used to record which type
** of conflict resolution action to take.
** of action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
@@ -2716,7 +2679,7 @@ struct Expr {
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
@@ -3084,21 +3047,15 @@ struct NameContext {
** WHERE clause is omitted.
*/
struct Upsert {
ExprList *pUpsertTarget; /* Optional description of conflict target */
ExprList *pUpsertTarget; /* Optional description of conflicting index */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
/* Above this point is the parse tree for the ON CONFLICT clauses.
** The next group of fields stores intermediate data. */
void *pToFree; /* Free memory when deleting the Upsert object */
/* All fields above are owned by the Upsert object and must be freed
** when the Upsert is destroyed. The fields below are used to transfer
** information from the INSERT processing down into the UPDATE processing
** while generating code. The fields below are owned by the INSERT
** statement and will be freed by INSERT processing. */
Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
/* The fields above comprise the parse tree for the upsert clause.
** The fields below are used to transfer information from the INSERT
** processing down into the UPDATE processing while generating code.
** Upsert owns the memory allocated above, but not the memory below. */
Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
@@ -3348,17 +3305,6 @@ struct TriggerPrg {
# define DbMaskNonZero(M) (M)!=0
#endif
/*
** An instance of the ParseCleanup object specifies an operation that
** should be performed after parsing to deallocation resources obtained
** during the parse and which are no longer needed.
*/
struct ParseCleanup {
ParseCleanup *pNext; /* Next cleanup task */
void *pPtr; /* Pointer to object to deallocate */
void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
};
/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
@@ -3390,9 +3336,6 @@ struct Parse {
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 disableVtab; /* Disable all virtual tables for this parse */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -3471,9 +3414,10 @@ struct Parse {
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
With *pWithToFree; /* Free this WITH object at the end of the parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
@@ -3553,7 +3497,6 @@ struct AuthContext {
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -3932,6 +3875,7 @@ int sqlite3WindowCompare(Parse*, Window*, Window*, int);
void sqlite3WindowCodeInit(Parse*, Select*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
@@ -4587,7 +4531,6 @@ int sqlite3Atoi64(const char*, i64*, int, u8);
int sqlite3DecOrHexToI64(const char*, i64*);
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
void sqlite3Error(sqlite3*,int);
void sqlite3ErrorClear(sqlite3*);
void sqlite3SystemError(sqlite3*,int);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
@@ -4651,6 +4594,7 @@ extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
extern u32 sqlite3_unsupported_selecttrace;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
@@ -4669,7 +4613,6 @@ void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchEName(
const struct ExprList_item*,
@@ -4840,7 +4783,6 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
void sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
char *sqlite3Normalize(Vdbe*, const char*);
#endif
@@ -4863,19 +4805,15 @@ const char *sqlite3JournalModename(int);
#define sqlite3WithDelete(x,y)
#endif
#ifndef SQLITE_OMIT_UPSERT
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
void sqlite3UpsertDelete(sqlite3*,Upsert*);
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
int sqlite3UpsertNextIsIPK(Upsert*);
#else
#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
#define sqlite3UpsertNextIsIPK(x) 0
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
#endif
+5 -2
View File
@@ -8512,7 +8512,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern LONG volatile sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG
extern u32 sqlite3WhereTrace;
extern int sqlite3WhereTrace;
extern int sqlite3OSTrace;
extern int sqlite3WalTrace;
#endif
@@ -8520,6 +8520,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_FTS3
extern int sqlite3_fts3_enable_parentheses;
#endif
#endif
#if defined(SQLITE_ENABLE_SELECTTRACE)
extern u32 sqlite3_unsupported_selecttrace;
#endif
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
@@ -8608,7 +8611,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_fullsync_count, TCL_LINK_INT);
#if defined(SQLITE_ENABLE_SELECTTRACE)
Tcl_LinkVar(interp, "sqlite3_unsupported_selecttrace",
(char*)&sqlite3SelectTrace, TCL_LINK_INT);
(char*)&sqlite3_unsupported_selecttrace, TCL_LINK_INT);
#endif
#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
-6
View File
@@ -154,12 +154,6 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "deserialize", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
Tcl_SetVar2(interp, "sqlite_options", "mathlib", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "mathlib", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_MEMSYS3
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
#else
+37 -27
View File
@@ -27,8 +27,8 @@
** all of them need to be used within the switch.
*/
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
#define CC_KYWD0 1 /* First letter of a keyword */
#define CC_KYWD 2 /* Alphabetics or '_'. Usable in a keyword */
#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
#define CC_ID 2 /* unicode characters usable in IDs */
#define CC_DIGIT 3 /* Digits */
#define CC_DOLLAR 4 /* '$' */
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
@@ -53,21 +53,20 @@
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
#define CC_ID 27 /* unicode characters usable in IDs */
#define CC_ILLEGAL 28 /* Illegal character */
#define CC_NUL 29 /* 0x00 */
#define CC_ILLEGAL 27 /* Illegal character */
#define CC_NUL 28 /* 0x00 */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -79,22 +78,22 @@ static const unsigned char aiClass[] = {
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28,
/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 4x */ 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
/* 5x */ 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15, 4, 21, 18, 19, 28,
/* 6x */ 11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22, 2, 13, 6,
/* 7x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 8, 5, 5, 5, 8, 14, 8,
/* 8x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
/* 9x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
/* Ax */ 28, 25, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
/* Bx */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, 28,
/* Cx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
/* Dx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
/* Ex */ 28, 28, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 28, 28, 28, 28, 28, 28,
/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27,
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27,
#endif
};
@@ -500,7 +499,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
case CC_KYWD0: {
case CC_KYWD: {
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
@@ -530,7 +529,6 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
case CC_KYWD:
case CC_ID: {
i = 1;
break;
@@ -713,7 +711,19 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
if( !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DbFree(db, pParse->pVList);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
sqlite3DbFreeNN(db, p);
}
while( pParse->pZombieTab ){
Table *p = pParse->pZombieTab;
pParse->pZombieTab = p->pNextZombie;
sqlite3DeleteTable(db, p);
}
db->pParse = pParse->pParentParse;
pParse->pParentParse = 0;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
+1
View File
@@ -1000,6 +1000,7 @@ static TriggerPrg *codeRowTrigger(
sqlite3VdbeDelete(v);
}
assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
+90 -146
View File
@@ -18,22 +18,15 @@
/*
** Free a list of Upsert objects
*/
static void SQLITE_NOINLINE upsertDelete(sqlite3 *db, Upsert *p){
do{
Upsert *pNext = p->pNextUpsert;
void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
if( p ){
sqlite3ExprListDelete(db, p->pUpsertTarget);
sqlite3ExprDelete(db, p->pUpsertTargetWhere);
sqlite3ExprListDelete(db, p->pUpsertSet);
sqlite3ExprDelete(db, p->pUpsertWhere);
sqlite3DbFree(db, p->pToFree);
sqlite3DbFree(db, p);
p = pNext;
}while( p );
}
}
void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
if( p ) upsertDelete(db, p);
}
/*
** Duplicate an Upsert object.
@@ -44,8 +37,7 @@ Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
sqlite3ExprListDup(db, p->pUpsertTarget, 0),
sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
sqlite3ExprListDup(db, p->pUpsertSet, 0),
sqlite3ExprDup(db, p->pUpsertWhere, 0),
sqlite3UpsertDup(db, p->pNextUpsert)
sqlite3ExprDup(db, p->pUpsertWhere, 0)
);
}
@@ -57,25 +49,22 @@ Upsert *sqlite3UpsertNew(
ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
Expr *pTargetWhere, /* Optional WHERE clause on the target */
ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */
Expr *pWhere, /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNext /* Next ON CONFLICT clause in the list */
Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */
){
Upsert *pNew;
pNew = sqlite3DbMallocZero(db, sizeof(Upsert));
pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
if( pNew==0 ){
sqlite3ExprListDelete(db, pTarget);
sqlite3ExprDelete(db, pTargetWhere);
sqlite3ExprListDelete(db, pSet);
sqlite3ExprDelete(db, pWhere);
sqlite3UpsertDelete(db, pNext);
return 0;
}else{
pNew->pUpsertTarget = pTarget;
pNew->pUpsertTargetWhere = pTargetWhere;
pNew->pUpsertSet = pSet;
pNew->pUpsertWhere = pWhere;
pNew->isDoUpdate = pSet!=0;
pNew->pNextUpsert = pNext;
pNew->pUpsertIdx = 0;
}
return pNew;
}
@@ -100,7 +89,6 @@ int sqlite3UpsertAnalyzeTarget(
Expr *pTerm; /* One term of the conflict-target clause */
NameContext sNC; /* Context for resolving symbolic names */
Expr sCol[2]; /* Index column converted into an Expr */
int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
assert( pTabList->a[0].pTab!=0 );
@@ -114,131 +102,87 @@ int sqlite3UpsertAnalyzeTarget(
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
for(; pUpsert && pUpsert->pUpsertTarget;
pUpsert=pUpsert->pNextUpsert, nClause++){
rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
if( rc ) return rc;
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
if( rc ) return rc;
/* Check to see if the conflict target matches the rowid. */
pTab = pTabList->a[0].pTab;
pTarget = pUpsert->pUpsertTarget;
iCursor = pTabList->a[0].iCursor;
if( HasRowid(pTab)
&& pTarget->nExpr==1
&& (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
&& pTerm->iColumn==XN_ROWID
){
/* The conflict-target is the rowid of the primary table */
assert( pUpsert->pUpsertIdx==0 );
continue;
}
/* Initialize sCol[0..1] to be an expression parse tree for a
** single column of an index. The sCol[0] node will be the TK_COLLATE
** operator and sCol[1] will be the TK_COLUMN operator. Code below
** will populate the specific collation and column number values
** prior to comparing against the conflict-target expression.
*/
memset(sCol, 0, sizeof(sCol));
sCol[0].op = TK_COLLATE;
sCol[0].pLeft = &sCol[1];
sCol[1].op = TK_COLUMN;
sCol[1].iTable = pTabList->a[0].iCursor;
/* Check for matches against other indexes */
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int ii, jj, nn;
if( !IsUniqueIndex(pIdx) ) continue;
if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
if( pIdx->pPartIdxWhere ){
if( pUpsert->pUpsertTargetWhere==0 ) continue;
if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
pIdx->pPartIdxWhere, iCursor)!=0 ){
continue;
}
}
nn = pIdx->nKeyCol;
for(ii=0; ii<nn; ii++){
Expr *pExpr;
sCol[0].u.zToken = (char*)pIdx->azColl[ii];
if( pIdx->aiColumn[ii]==XN_EXPR ){
assert( pIdx->aColExpr!=0 );
assert( pIdx->aColExpr->nExpr>ii );
pExpr = pIdx->aColExpr->a[ii].pExpr;
if( pExpr->op!=TK_COLLATE ){
sCol[0].pLeft = pExpr;
pExpr = &sCol[0];
}
}else{
sCol[0].pLeft = &sCol[1];
sCol[1].iColumn = pIdx->aiColumn[ii];
pExpr = &sCol[0];
}
for(jj=0; jj<nn; jj++){
if( sqlite3ExprCompare(pParse,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
break; /* Column ii of the index matches column jj of target */
}
}
if( jj>=nn ){
/* The target contains no match for column jj of the index */
break;
}
}
if( ii<nn ){
/* Column ii of the index did not match any term of the conflict target.
** Continue the search with the next index. */
rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
if( rc ) return rc;
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
if( rc ) return rc;
/* Check to see if the conflict target matches the rowid. */
pTab = pTabList->a[0].pTab;
pTarget = pUpsert->pUpsertTarget;
iCursor = pTabList->a[0].iCursor;
if( HasRowid(pTab)
&& pTarget->nExpr==1
&& (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
&& pTerm->iColumn==XN_ROWID
){
/* The conflict-target is the rowid of the primary table */
assert( pUpsert->pUpsertIdx==0 );
return SQLITE_OK;
}
/* Initialize sCol[0..1] to be an expression parse tree for a
** single column of an index. The sCol[0] node will be the TK_COLLATE
** operator and sCol[1] will be the TK_COLUMN operator. Code below
** will populate the specific collation and column number values
** prior to comparing against the conflict-target expression.
*/
memset(sCol, 0, sizeof(sCol));
sCol[0].op = TK_COLLATE;
sCol[0].pLeft = &sCol[1];
sCol[1].op = TK_COLUMN;
sCol[1].iTable = pTabList->a[0].iCursor;
/* Check for matches against other indexes */
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int ii, jj, nn;
if( !IsUniqueIndex(pIdx) ) continue;
if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
if( pIdx->pPartIdxWhere ){
if( pUpsert->pUpsertTargetWhere==0 ) continue;
if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
pIdx->pPartIdxWhere, iCursor)!=0 ){
continue;
}
pUpsert->pUpsertIdx = pIdx;
break;
}
if( pUpsert->pUpsertIdx==0 ){
char zWhich[16];
if( nClause==0 && pUpsert->pNextUpsert==0 ){
zWhich[0] = 0;
nn = pIdx->nKeyCol;
for(ii=0; ii<nn; ii++){
Expr *pExpr;
sCol[0].u.zToken = (char*)pIdx->azColl[ii];
if( pIdx->aiColumn[ii]==XN_EXPR ){
assert( pIdx->aColExpr!=0 );
assert( pIdx->aColExpr->nExpr>ii );
pExpr = pIdx->aColExpr->a[ii].pExpr;
if( pExpr->op!=TK_COLLATE ){
sCol[0].pLeft = pExpr;
pExpr = &sCol[0];
}
}else{
sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
sCol[0].pLeft = &sCol[1];
sCol[1].iColumn = pIdx->aiColumn[ii];
pExpr = &sCol[0];
}
for(jj=0; jj<nn; jj++){
if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){
break; /* Column ii of the index matches column jj of target */
}
}
if( jj>=nn ){
/* The target contains no match for column jj of the index */
break;
}
sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
"PRIMARY KEY or UNIQUE constraint", zWhich);
return SQLITE_ERROR;
}
if( ii<nn ){
/* Column ii of the index did not match any term of the conflict target.
** Continue the search with the next index. */
continue;
}
pUpsert->pUpsertIdx = pIdx;
return SQLITE_OK;
}
return SQLITE_OK;
}
/*
** Return true if pUpsert is the last ON CONFLICT clause with a
** conflict target, or if pUpsert is followed by another ON CONFLICT
** clause that targets the INTEGER PRIMARY KEY.
*/
int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
Upsert *pNext;
if( NEVER(pUpsert==0) ) return 0;
pNext = pUpsert->pNextUpsert;
if( pNext==0 ) return 1;
if( pNext->pUpsertTarget==0 ) return 1;
if( pNext->pUpsertIdx==0 ) return 1;
return 0;
}
/*
** Given the list of ON CONFLICT clauses described by pUpsert, and
** a particular index pIdx, return a pointer to the particular ON CONFLICT
** clause that applies to the index. Or, if the index is not subject to
** any ON CONFLICT clause, return NULL.
*/
Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
while(
pUpsert
&& pUpsert->pUpsertTarget!=0
&& pUpsert->pUpsertIdx!=pIdx
){
pUpsert = pUpsert->pNextUpsert;
}
return pUpsert;
sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
"PRIMARY KEY or UNIQUE constraint");
return SQLITE_ERROR;
}
/*
@@ -262,13 +206,11 @@ void sqlite3UpsertDoUpdate(
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
Upsert *pTop = pUpsert;
assert( v!=0 );
assert( pUpsert!=0 );
iDataCur = pUpsert->iDataCur;
pUpsert = sqlite3UpsertOfIndex(pTop, pIdx);
VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
iDataCur = pUpsert->iDataCur;
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlite3GetTempReg(pParse);
@@ -298,17 +240,19 @@ void sqlite3UpsertDoUpdate(
sqlite3VdbeJumpHere(v, i);
}
}
/* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
** So we have to make a copy before passing it down into sqlite3Update() */
pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
/* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
** we have to make a copy before passing it down into sqlite3Update() */
pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
}
}
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */
pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */
VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
}
-10
View File
@@ -114,16 +114,6 @@ void sqlite3Error(sqlite3 *db, int err_code){
if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
}
/*
** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state
** and error message.
*/
void sqlite3ErrorClear(sqlite3 *db){
assert( db!=0 );
db->errCode = SQLITE_OK;
if( db->pErr ) sqlite3ValueSetNull(db->pErr);
}
/*
** Load the sqlite3.iSysErrno field if that is an appropriate thing
** to do based on the SQLite error code in rc.
+3 -31
View File
@@ -5126,8 +5126,7 @@ case OP_Insert: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
seekResult
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -5144,33 +5143,6 @@ case OP_Insert: {
break;
}
/* Opcode: RowCell P1 P2 P3 * *
**
** P1 and P2 are both open cursors. Both must be opened on the same type
** of table - intkey or index. This opcode is used as part of copying
** the current row from P2 into P1. If the cursors are opened on intkey
** tables, register P3 contains the rowid to use with the new record in
** P1. If they are opened on index tables, P3 is not used.
**
** This opcode must be followed by either an Insert or InsertIdx opcode
** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
*/
case OP_RowCell: {
VdbeCursor *pDest; /* Cursor to write to */
VdbeCursor *pSrc; /* Cursor to read from */
i64 iKey; /* Rowid value to insert with */
assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
assert( pOp[1].opcode==OP_Insert || pOp->p3==0 );
assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
assert( pOp[1].p5 & OPFLAG_PREFORMAT );
pDest = p->apCsr[pOp->p1];
pSrc = p->apCsr[pOp->p2];
iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
break;
};
/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
@@ -5826,7 +5798,7 @@ case OP_IdxInsert: { /* in2 */
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
assert( pIn2->flags & MEM_Blob );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isTable==0 );
@@ -5837,7 +5809,7 @@ case OP_IdxInsert: { /* in2 */
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
+2 -2
View File
@@ -2358,8 +2358,6 @@ void sqlite3VdbeMakeReady(
assert( pParse!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
assert( pParse==p->pParse );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -2444,6 +2442,8 @@ void sqlite3VdbeMakeReady(
}
}
p->pVList = pParse->pVList;
pParse->pVList = 0;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
+1 -1
View File
@@ -125,7 +125,7 @@ char *sqlite3VdbeExpandSql(
assert( idx>0 );
}
zRawSql += nToken;
nextIndex = MAX(idx + 1, nextIndex);
nextIndex = idx + 1;
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
+3 -4
View File
@@ -22,7 +22,7 @@
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
static int walkWindowList(Walker *pWalker, Window *pList){
Window *pWin;
for(pWin=pList; pWin; pWin=pWin->pNextWin){
int rc;
@@ -41,7 +41,6 @@ static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
if( NEVER(rc) ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
if( NEVER(rc) ) return WRC_Abort;
if( bOneOnly ) break;
}
return WRC_Continue;
}
@@ -89,7 +88,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort;
if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
}
#endif
}
@@ -136,7 +135,7 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( pParse && IN_RENAME_OBJECT ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
int rc = walkWindowList(pWalker, p->pWinDefn, 0);
int rc = walkWindowList(pWalker, p->pWinDefn);
return rc;
}
}
+7 -1
View File
@@ -37,6 +37,12 @@ struct HiddenIndexInfo {
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
/* Test variable that can be set to enable WHERE tracing */
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ int sqlite3WhereTrace = 0;
#endif
/*
** Return the estimated number of output rows from a WHERE clause
*/
@@ -2605,7 +2611,7 @@ static int whereLoopAddBtreeIndex(
pBtm = pTerm;
pTop = 0;
if( pTerm->wtFlags & TERM_LIKEOPT ){
/* Range constraints that come from the LIKE optimization are
/* Range contraints that come from the LIKE optimization are
** always used in pairs. */
pTop = &pTerm[1];
assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
+13
View File
@@ -17,6 +17,19 @@
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H
/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ extern int sqlite3WhereTrace;
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define WHERETRACE(K,X)
#endif
/* Forward references
*/
-106
View File
@@ -1,106 +0,0 @@
# 2020-12-16
#
# 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.
#
#***********************************************************************
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptN
# These tests deal with corrupt database files
#
database_may_be_corrupt
reset_db
do_test 1.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 4096 pagesize 512 filename sql024239.txt.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 02 00 01 01 00 40 20 20 00 00 00 0c 00 00 00 07 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 04 ................
| 48: 00 00 00 00 89 00 00 04 00 10 00 01 0a 00 00 01 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c ................
| 96: 00 2e 2c 50 0d 00 00 00 06 01 06 00 01 da 01 b0 ..,P............
| 112: 01 56 01 86 01 2a 01 06 00 00 00 00 00 00 00 00 .V...*..........
| 256: 00 00 00 00 00 00 22 07 06 17 11 11 01 31 74 61 .............1ta
| 272: 62 6c 65 74 34 74 34 07 43 52 45 41 54 45 20 54 blet4t4.CREATE T
| 288: 41 42 4c 45 20 74 34 28 78 29 2a 06 06 17 13 11 ABLE t4(x)*.....
| 304: 01 3f 69 6e 64 65 78 74 33 78 74 33 05 43 52 45 .?indext3xt3.CRE
| 320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e ATE INDEX t3x ON
| 336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e t3(x).......Ein
| 352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45 dext2cdt2.CREATE
| 368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74 INDEX t2cd ON t
| 384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61 2(c,d)(......=ta
| 400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54 blet3t3.CREATE T
| 416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29 ABLE t3(c,x,e,f)
| 432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74 (......=tablet2t
| 448: 32 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 2.CREATE TABLE t
| 464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11 2(c,d,e,f)$.....
| 480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .5tablet1t1.CREA
| 496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29 TE TABLE t1(a,b)
| page 2 offset 512
| 0: 0d 00 00 00 04 01 41 00 01 fa 01 f3 01 de 01 cf ......A.........
| 160: 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 .. .............
| 448: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d ................
| 464: 04 03 17 17 73 65 76 65 6e 65 69 67 68 74 13 03 ....seveneight..
| 480: 03 07 07 40 14 00 00 00 00 00 00 40 18 00 00 00 ...@.......@....
| 496: 00 00 00 05 02 03 01 01 03 04 04 01 03 09 01 02 ................
| page 3 offset 1024
| 0: 0d 00 00 00 08 01 54 00 01 f7 01 ec 01 c5 01 aa ......T.........
| 16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 112: 00 00 dd 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 336: 00 00 00 00 19 08 05 17 17 17 17 65 69 67 68 74 ...........eight
| 352: 65 69 67 68 74 73 65 76 65 6e 73 65 76 65 6e 25 eightsevenseven%
| 368: 07 05 07 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 432: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
| 480: 00 00 0f 04 17 17 01 65 69 67 68 74 65 69 67 68 .......eighteigh
| 496: 74 08 15 04 07 07 01 40 18 00 00 00 00 00 00 40 t......@.......@
| page 4 offset 1536
| 0: 18 00 00 00 00 00 00 07 07 04 01 01 01 04 04 06 ................
| 16: 07 04 01 01 01 02 02 05 0f 04 17 17 01 73 6d 76 .............smv
| 32: 65 6e 65 69 67 68 74 04 15 04 07 07 01 40 14 00 eneight......@..
| page 5 offset 2048
| 0: 0a 00 00 00 08 01 96 00 01 fa 01 c4 01 f2 01 bc ................
| 16: 01 dc 01 e1 01 96 01 cc 00 00 00 00 00 00 00 00 ................
| 160: 00 00 00 00 00 00 32 00 00 00 00 00 00 00 00 00 ......2.........
| 368: 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 400: 00 00 00 00 00 00 0f 04 17 17 01 85 69 67 68 74 ............ight
| 416: 65 69 67 68 74 08 15 04 07 07 01 40 18 00 00 00 eight......@....
| 432: 00 00 00 40 18 00 00 00 00 00 00 07 07 04 01 01 ...@............
| 448: 01 04 04 06 07 04 01 01 01 02 02 05 0f 04 17 17 ................
| 464: 01 73 6d 76 65 6e 65 69 67 68 74 04 15 04 07 07 .smveneight.....
| 480: 01 40 14 00 00 00 00 00 00 40 18 00 00 00 00 00 .@.......@......
| 496: 00 03 07 04 01 01 01 03 04 02 05 04 03 01 09 02 ................
| page 6 offset 2560
| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 16: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 ................
| 304: 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 00 ...&............
| page 7 offset 3072
| 0: 0d 00 00 00 08 01 c2 00 01 fb 01 f6 01 f1 01 ec ................
| 16: 01 e0 01 d4 01 cb 01 c2 00 00 00 00 00 00 00 00 ................
| 128: 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 04 ............. ..
| 384: 00 00 00 00 00 00 00 00 00 07 08 02 17 65 69 fc .............ei.
| 400: 68 74 07 07 02 17 65 69 67 68 74 0a fb fd f8 bf ht....eight.....
| 416: e7 ff ff ff 00 00 00 0a 05 02 07 40 18 00 00 00 ...........@....
| 432: 00 00 00 03 04 02 01 04 03 03 02 01 04 03 02 01 ................
| 448: ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 ................
| end sql024239.txt.db
}]} {}
do_catchsql_test 1.1 {
VACUUM;
} {1 {database disk image is malformed}}
finish_test
+28 -39
View File
@@ -29,7 +29,7 @@ ifcapable !crashtest||!memorymanage {
db close
for {set ii 0} {$ii < 10} {incr ii} {
for {set jj 1} {$jj < 100} {incr jj} {
for {set jj 50} {$jj < 100} {incr jj} {
# Set up the database so that it is an auto-vacuum database
# containing a single table (root page 3) with a single row.
@@ -47,14 +47,6 @@ for {set ii 0} {$ii < 10} {incr ii} {
do_test crash5-$ii.$jj.1 {
crashsql -delay 1 -file test.db-journal -seed $ii -tclbody [join [list \
[list set iFail $jj] {
proc get_pwd {} {
if {$::tcl_platform(platform) eq "windows"} {
return [string map [list \\ /] \
[string trim [exec -- $::env(ComSpec) /c echo %CD%]]]
} else {
return [pwd]
}
}
sqlite3_crashparams 0 [file join [get_pwd] test.db-journal]
# Begin a transaction and evaluate a "CREATE INDEX" statement
@@ -69,39 +61,36 @@ for {set ii 0} {$ii < 10} {incr ii} {
#
db eval BEGIN
sqlite3_memdebug_fail $iFail -repeat 0
set rc [catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg]
# puts "$msg ac=[sqlite3_get_autocommit db] iFail=$iFail"
# puts "fail=[sqlite3_memdebug_fail -1]"
catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg
# puts "$n $msg ac=[sqlite3_get_autocommit db]"
if {$rc} {
# If the transaction is still active (it may not be if the malloc()
# failure occurred in the OS layer), write to the database. Make sure
# page 4 is among those written.
#
if {![sqlite3_get_autocommit db]} {
db eval {
DELETE FROM t1; -- This will put page 4 on the free list.
INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
INSERT INTO t1 SELECT * FROM t1; -- 2
INSERT INTO t1 SELECT * FROM t1; -- 4
INSERT INTO t1 SELECT * FROM t1; -- 8
INSERT INTO t1 SELECT * FROM t1; -- 16
INSERT INTO t1 SELECT * FROM t1; -- 32
INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48
}
# If the transaction is still active (it may not be if the malloc()
# failure occurred in the OS layer), write to the database. Make sure
# page 4 is among those written.
#
if {![sqlite3_get_autocommit db]} {
db eval {
DELETE FROM t1; -- This will put page 4 on the free list.
INSERT INTO t1 VALUES('111111111', '2222222222', '33333333');
INSERT INTO t1 SELECT * FROM t1; -- 2
INSERT INTO t1 SELECT * FROM t1; -- 4
INSERT INTO t1 SELECT * FROM t1; -- 8
INSERT INTO t1 SELECT * FROM t1; -- 16
INSERT INTO t1 SELECT * FROM t1; -- 32
INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48
}
# If the right malloc() failed during the 'CREATE INDEX' above and
# the transaction was not rolled back, then the sqlite cache now
# has a dirty page 4 that it incorrectly believes is already safely
# in the synced part of the journal file. When
# sqlite3_release_memory() is called sqlite tries to free memory
# by writing page 4 out to the db file. If it crashes later on,
# before syncing the journal... Corruption!
#
sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
sqlite3_release_memory 8092
}
# If the right malloc() failed during the 'CREATE INDEX' above and
# the transaction was not rolled back, then the sqlite cache now
# has a dirty page 4 that it incorrectly believes is already safely
# in the synced part of the journal file. When
# sqlite3_release_memory() is called sqlite tries to free memory
# by writing page 4 out to the db file. If it crashes later on,
# before syncing the journal... Corruption!
#
sqlite3_crashparams 1 [file join [get_pwd] test.db-journal]
sqlite3_release_memory 8092
}]] {}
expr 1
} {1}
+4 -12
View File
@@ -287,6 +287,10 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
sqlite3MemTraceActivate(stdout);
continue;
}
if( strcmp(z,"mem")==0 ){
bVdbeDebug = 1;
continue;
}
if( strcmp(z,"max-db-size")==0 ){
if( i+1==argc ){
fprintf(stderr, "missing argument to %s\n", argv[i]);
@@ -295,18 +299,6 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
szMax = strtol(argv[++i], 0, 0);
continue;
}
if( strcmp(z, "lookaside")==0 ){
int sz, nSlot;
if( i+2>=argc ){
fprintf(stderr,
"--lookaside requires two arguments: slot-size num-slots\n");
exit(1);
}
sz = atoi(argv[++i]);
nSlot = atoi(argv[++i]);
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, nSlot);
continue;
}
#ifndef _WIN32
if( strcmp(z,"max-stack")==0
|| strcmp(z,"max-data")==0
-18
View File
@@ -567,22 +567,4 @@ do_execsql_test 11.1 {
berlin@street sydney.road
}
# Test for embedded nul characters in fts4 unicode index.
#
do_execsql_test 12.0 {
CREATE VIRTUAL TABLE t12 USING fts4(tokenize=unicode61);
INSERT INTO t12 VALUES('abc' || char(0) || 'def');
SELECT hex(CAST(content AS blob)) FROM t12;
} {61626300646566}
do_execsql_test 12.1 {
INSERT INTO t12(t12) VALUES('integrity-check');
} {}
do_execsql_test 12.2 {
CREATE VIRTUAL TABLE t12aux USING fts4aux(t12);
SELECT * FROM t12aux;
} {abc * 1 1 abc 0 1 1}
do_execsql_test 12.3 {
SELECT hex(CAST(content AS blob)) FROM t12 WHERE t12 MATCH 'abc'
} {61626300646566}
finish_test
-245
View File
@@ -1,245 +0,0 @@
# 2020-12-07
#
# 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.
#
#*************************************************************************
#
# Test cases for SQL functions based off the standard math library
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !mathlib {
finish_test
return
}
do_execsql_test func7-100 {
SELECT ceil(99.9), ceiling(-99.01), floor(17), floor(-17.99);
} {100.0 -99.0 17 -18.0}
do_execsql_test func7-110 {
SELECT quote(ceil(NULL)), ceil('-99.99');
} {NULL -99.0}
do_execsql_test func7-200 {
SELECT round(ln(5),2), log(100.0), log(100), log(2,'256');
} {1.61 2.0 2.0 8.0}
do_execsql_test func7-210 {
SELECT ln(-5), log(-5,100.0);
} {{} {}}
# Test cases derived from PostgreSQL documentation
#
do_execsql_test func7-pg-100 {
SELECT abs(-17.4)
} {17.4}
do_execsql_test func7-pg-110 {
SELECT ceil(42.2)
} {43.0}
do_execsql_test func7-pg-120 {
SELECT ceil(-42.2)
} {-42.0}
do_execsql_test func7-pg-130 {
SELECT round(exp(1.0),7)
} {2.7182818}
do_execsql_test func7-pg-140 {
SELECT floor(42.8)
} {42.0}
do_execsql_test func7-pg-150 {
SELECT floor(-42.8)
} {-43.0}
do_execsql_test func7-pg-160 {
SELECT round(ln(2.0),7)
} {0.6931472}
do_execsql_test func7-pg-170 {
SELECT log(100.0)
} {2.0}
do_execsql_test func7-pg-180 {
SELECT log10(1000.0)
} {3.0}
do_execsql_test func7-pg-190 {
SELECT log(2.0, 64.0)
} {6.0}
do_execsql_test func7-pg-200 {
SELECT mod(9,4);
} {1.0}
do_execsql_test func7-pg-210 {
SELECT round(pi(),7);
} {3.1415927}
do_execsql_test func7-pg-220 {
SELECT power(9,3);
} {729.0}
do_execsql_test func7-pg-230 {
SELECT round(radians(45.0),7);
} {0.7853982}
do_execsql_test func7-pg-240 {
SELECT round(42.4);
} {42.0}
do_execsql_test func7-pg-250 {
SELECT round(42.4382,2);
} {42.44}
do_execsql_test func7-pg-260 {
SELECT sign(-8.4);
} {-1}
do_execsql_test func7-pg-270 {
SELECT round( sqrt(2), 7);
} {1.4142136}
do_execsql_test func7-pg-280 {
SELECT trunc(42.8), trunc(-42.8);
} {42.0 -42.0}
do_execsql_test func7-pg-300 {
SELECT acos(1);
} {0.0}
do_execsql_test func7-pg-301 {
SELECT degrees(acos(0.5));
} {60.0}
do_execsql_test func7-pg-310 {
SELECT round( asin(1), 7);
} {1.5707963}
do_execsql_test func7-pg-311 {
SELECT degrees( asin(0.5) );
} {30.0}
do_execsql_test func7-pg-320 {
SELECT round( atan(1), 7);
} {0.7853982}
do_execsql_test func7-pg-321 {
SELECT degrees( atan(1) );
} {45.0}
do_execsql_test func7-pg-330 {
SELECT round( atan2(1,0), 7);
} {1.5707963}
do_execsql_test func7-pg-331 {
SELECT degrees( atan2(1,0) );
} {90.0}
do_execsql_test func7-pg-400 {
SELECT cos(0);
} {1.0}
do_execsql_test func7-pg-401 {
SELECT cos( radians(60.0) );
} {0.5}
do_execsql_test func7-pg-400 {
SELECT cos(0);
} {1.0}
do_execsql_test func7-pg-410 {
SELECT round( sin(1), 7);
} {0.841471}
do_execsql_test func7-pg-411 {
SELECT sin( radians(30) );
} {0.5}
do_execsql_test func7-pg-420 {
SELECT round( tan(1), 7);
} {1.5574077}
do_execsql_test func7-pg-421 {
SELECT tan( radians(45) );
} {1.0}
do_execsql_test func7-pg-500 {
SELECT round( sinh(1), 7);
} {1.1752012}
do_execsql_test func7-pg-510 {
SELECT round( cosh(0), 7);
} {1.0}
do_execsql_test func7-pg-520 {
SELECT round( tanh(1), 7);
} {0.7615942}
do_execsql_test func7-pg-530 {
SELECT round( asinh(1), 7);
} {0.8813736}
do_execsql_test func7-pg-540 {
SELECT round( acosh(1), 7);
} {0.0}
do_execsql_test func7-pg-550 {
SELECT round( atanh(0.5), 7);
} {0.5493061}
# Test cases derived from MySQL documentation
#
do_execsql_test func7-mysql-100 {
SELECT acos(1);
} {0.0}
do_execsql_test func7-mysql-110 {
SELECT acos(1.0001);
} {{}}
do_execsql_test func7-mysql-120 {
SELECT round( acos(0.0), 7);
} {1.5707963}
do_execsql_test func7-mysql-130 {
SELECT round( asin(0.2), 7);
} {0.2013579}
do_execsql_test func7-mysql-140 {
SELECT asin('foo');
} {{}} ;# Note: MySQL returns 0 here, not NULL.
# SQLite deliberately returns NULL.
# SQLServer and Oracle throw an error.
do_execsql_test func7-mysql-150 {
SELECT round( atan(2), 7), round( atan(-2), 7);
} {1.1071487 -1.1071487}
do_execsql_test func7-mysql-160 {
SELECT round( atan2(-2,2), 7), round( atan2(pi(),0), 7);
} {-0.7853982 1.5707963}
do_execsql_test func7-mysql-170 {
SELECT ceiling(1.23), ceiling(-1.23);
} {2.0 -1.0}
do_execsql_test func7-mysql-180 {
SELECT cos(pi());
} {-1.0}
do_execsql_test func7-mysql-190 {
SELECT degrees(pi()), degrees(pi()/2);
} {180.0 90.0}
do_execsql_test func7-mysql-190 {
SELECT round( exp(2), 7), round( exp(-2), 7), exp(0);
} {7.3890561 0.1353353 1.0}
do_execsql_test func7-mysql-200 {
SELECT floor(1.23), floor(-1.23);
} {1.0 -2.0}
do_execsql_test func7-mysql-210 {
SELECT round(ln(2),7), quote(ln(-2));
} {0.6931472 NULL}
#do_execsql_test func7-mysql-220 {
# SELECT round(log(2),7), log(-2);
#} {0.6931472 NULL}
# log() means natural logarithm in MySQL
do_execsql_test func7-mysql-230 {
SELECT log(2,65536), log(10,100), quote(log(1,100));
} {16.0 2.0 Inf}
do_execsql_test func7-mysql-240 {
SELECT log2(65536), quote(log2(-100));
} {16.0 NULL}
do_execsql_test func7-mysql-250 {
SELECT round(log10(2),7), log10(100), quote(log10(-100));
} {0.30103 2.0 NULL}
do_execsql_test func7-mysql-260 {
SELECT mod(234,10), 253%7, mod(29,9), 29%9;
} {4.0 1 2.0 2}
do_execsql_test func7-mysql-270 {
SELECT mod(34.5,3);
} {1.5}
do_execsql_test func7-mysql-280 {
SELECT pow(2,2), pow(2,-2);
} {4.0 0.25}
do_execsql_test func7-mysql-281 {
SELECT power(2,2), power(2,-2);
} {4.0 0.25}
do_execsql_test func7-mysql-290 {
SELECT round(radians(90),7);
} {1.5707963}
do_execsql_test func7-mysql-300 {
SELECT sign(-32), sign(0), sign(234);
} {-1 0 1}
do_execsql_test func7-mysql-310 {
SELECT sin(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
} {1}
do_execsql_test func7-mysql-320 {
SELECT sqrt(4), round(sqrt(20),7), quote(sqrt(-16));
} {2.0 4.472136 NULL}
do_execsql_test func7-mysql-330 {
SELECT tan(pi()) BETWEEN -1.0e-15 AND 1.0e-15;
} {1}
do_execsql_test func7-mysql-331 {
SELECT round(tan(pi()+1),7);
} {1.5574077}
finish_test
+7 -27
View File
@@ -455,12 +455,7 @@ static void blobListFree(Blob *p){
}
}
/* Return the current wall-clock time
**
** The number of milliseconds since the julian epoch.
** 1907-01-01 00:00:00 -> 210866716800000
** 2021-01-01 00:00:00 -> 212476176000000
*/
/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
@@ -718,7 +713,6 @@ static int progress_handler(void *pClientData) {
sqlite3_int64 iNow = timeOfDay();
int rc = iNow>=p->iCutoffTime;
sqlite3_int64 iDiff = iNow - p->iLastCb;
/* printf("time-remaining: %lld\n", p->iCutoffTime - iNow); */
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
p->nCb++;
if( rc==0 && p->mxCb>0 && p->mxCb<=p->nCb ) rc = 1;
@@ -841,7 +835,7 @@ static int runDbSql(sqlite3 *db, const char *zSql){
}
/* Invoke this routine to run a single test case */
int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte){
int rc; /* SQLite API return value */
int iSql; /* Index in aData[] of start of SQL */
unsigned char *aDb = 0; /* Decoded database content */
@@ -888,7 +882,7 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
** elapsed since the start of the test.
*/
cx.iLastCb = timeOfDay();
cx.iCutoffTime = cx.iLastCb + (iTimeout<giTimeout ? iTimeout : giTimeout);
cx.iCutoffTime = cx.iLastCb + giTimeout; /* Now + giTimeout seconds */
cx.mxCb = mxProgressCb;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
@@ -1439,7 +1433,7 @@ static void showHelp(void){
" --skip N Skip the first N test cases\n"
" --spinner Use a spinner to show progress\n"
" --sqlid N Use only SQL where sqlid=N\n"
" --timeout N Maximum time for any one test in N millseconds\n"
" --timeout N Abort if any single test needs more than N seconds\n"
" -v|--verbose Increased output. Repeat for more output.\n"
" --vdbe-debug Activate VDBE debugging.\n"
);
@@ -1477,7 +1471,7 @@ int main(int argc, char **argv){
const char *zFailCode = 0; /* Value of the TEST_FAILURE env variable */
int cellSzCkFlag = 0; /* --cell-size-check */
int sqlFuzz = 0; /* True for SQL fuzz. False for DB fuzz */
int iTimeout = 120000; /* Default 120-second timeout */
int iTimeout = 120; /* Default 120-second timeout */
int nMem = 0; /* Memory limit override */
int nMemThisDb = 0; /* Memory limit set by the CONFIG table */
char *zExpDb = 0; /* Write Databases to files in this directory */
@@ -1488,9 +1482,7 @@ int main(int argc, char **argv){
int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */
sqlite3_vfs *pDfltVfs; /* The default VFS */
int openFlags4Data; /* Flags for sqlite3_open_v2() */
int bTimer = 0; /* Show elapse time for each test */
int nV; /* How much to increase verbosity with -vvvv */
sqlite3_int64 tmStart; /* Start of each test */
registerOomSimulator();
sqlite3_initialize();
@@ -1605,9 +1597,6 @@ int main(int argc, char **argv){
if( strcmp(z,"spinner")==0 ){
bSpinner = 1;
}else
if( strcmp(z,"timer")==0 ){
bTimer = 1;
}else
if( strcmp(z,"sqlid")==0 ){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
onlySqlid = integerValue(argv[++i]);
@@ -1905,7 +1894,6 @@ int main(int argc, char **argv){
*/
if( !verboseFlag && !quietFlag && !bSpinner ) printf("%s:", zDbName);
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
tmStart = timeOfDay();
if( isDbSql(pSql->a, pSql->sz) ){
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
if( bSpinner ){
@@ -1929,13 +1917,9 @@ int main(int argc, char **argv){
if( nSkip>0 ){
nSkip--;
}else{
runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout);
runCombinedDbSqlInput(pSql->a, pSql->sz);
}
nTest++;
if( bTimer ){
sqlite3_int64 tmEnd = timeOfDay();
printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
}
g.zTestName[0] = 0;
disableOom();
continue;
@@ -1988,7 +1972,7 @@ int main(int argc, char **argv){
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000);
sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50);
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
setAlarm((iTimeout+999)/1000);
setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( sqlFuzz || vdbeLimitFlag ){
sqlite3_progress_handler(db, 100000, progressHandler,
@@ -2014,10 +1998,6 @@ int main(int argc, char **argv){
}
reformatVfs();
nTest++;
if( bTimer ){
sqlite3_int64 tmEnd = timeOfDay();
printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
}
g.zTestName[0] = 0;
/* Simulate an error if the TEST_FAILURE environment variable is "5".
BIN
View File
Binary file not shown.
-13
View File
@@ -174,18 +174,5 @@ do_execsql_test 5.1 {
) FROM t1;
} {b {}}
# From chromium
# https://bugs.chromium.org/p/chromium/issues/detail?id=1161869
#
do_execsql_test 5.2 {
SELECT EXISTS (
SELECT * FROM (
SELECT * FROM (
SELECT 1
) WHERE Col0 = 1 GROUP BY 1
) WHERE 0
)
FROM (SELECT 1 Col0) GROUP BY 1
} {0}
finish_test
+3 -3
View File
@@ -261,10 +261,10 @@ do_execsql_test 5.2 {
}
do_execsql_test 5.3 {
SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3) ORDER BY 1,2;
SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3);
} {
a 21 a 22 a 23 a 24 a 25 a 301 a 302 a 303
b 21 b 22 b 23 b 24 b 25 b 301 b 302 b 303
a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301
b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301
}
finish_test
+2 -2
View File
@@ -642,7 +642,7 @@ do_test shell1-3.23.2 {
# .stats ON|OFF Turn stats on or off
#do_test shell1-3.23b.1 {
# catchcmd "test.db" ".stats"
#} {1 {Usage: .stats on|off|stmt|vmstep}}
#} {1 {Usage: .stats on|off}}
do_test shell1-3.23b.2 {
catchcmd "test.db" ".stats ON"
} {0 {}}
@@ -652,7 +652,7 @@ do_test shell1-3.23b.3 {
do_test shell1-3.23b.4 {
# too many arguments
catchcmd "test.db" ".stats OFF BAD"
} {1 {Usage: .stats ?on|off|stmt|vmstep?}}
} {1 {Usage: .stats ?on|off?}}
# Ticket 7be932dfa60a8a6b3b26bcf7623ec46e0a403ddb 2018-06-07
# Adverse interaction between .stats and .eqp
+1 -1
View File
@@ -66,7 +66,7 @@ do_test shell4-1.3.3 {
do_test shell4-1.3.4 {
# too many arguments
catchcmd "test.db" ".stats OFF BAD"
} {1 {Usage: .stats ?on|off|stmt|vmstep?}}
} {1 {Usage: .stats ?on|off?}}
# NB. whitespace is important
do_test shell4-1.4.1 {
+66 -66
View File
@@ -707,9 +707,9 @@ void testset_main(void){
maxb = roundup_allones(sz);
speedtest1_begin_test(100, "%d INSERTs into table with no index", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE%s TABLE z1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
speedtest1_exec("CREATE%s TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
isTemp(9), g.zNN, g.zNN, g.zNN);
speedtest1_prepare("INSERT INTO z1 VALUES(?1,?2,?3); -- %d times", n);
speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
@@ -726,9 +726,9 @@ void testset_main(void){
speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n);
speedtest1_exec("BEGIN");
speedtest1_exec(
"CREATE%s TABLE z2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
"CREATE%s TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
isTemp(5), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
speedtest1_prepare("INSERT INTO z2 VALUES(?1,?2,?3); -- %d times", n);
speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
@@ -768,7 +768,7 @@ void testset_main(void){
speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM z1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -788,7 +788,7 @@ void testset_main(void){
speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM z1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
" WHERE c LIKE ?1; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -810,7 +810,7 @@ void testset_main(void){
speedtest1_begin_test(142, "%d SELECTS w/ORDER BY, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT a, b, c FROM z1 WHERE c LIKE ?1\n"
"SELECT a, b, c FROM t1 WHERE c LIKE ?1\n"
" ORDER BY a; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -831,7 +831,7 @@ void testset_main(void){
speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT a, b, c FROM z1 WHERE c LIKE ?1\n"
"SELECT a, b, c FROM t1 WHERE c LIKE ?1\n"
" ORDER BY a LIMIT 10; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -851,10 +851,10 @@ void testset_main(void){
speedtest1_begin_test(150, "CREATE INDEX five times");
speedtest1_exec("BEGIN;");
speedtest1_exec("CREATE UNIQUE INDEX t1b ON z1(b);");
speedtest1_exec("CREATE INDEX t1c ON z1(c);");
speedtest1_exec("CREATE UNIQUE INDEX t2b ON z2(b);");
speedtest1_exec("CREATE INDEX t2c ON z2(c DESC);");
speedtest1_exec("CREATE UNIQUE INDEX t1b ON t1(b);");
speedtest1_exec("CREATE INDEX t1c ON t1(c);");
speedtest1_exec("CREATE UNIQUE INDEX t2b ON t2(b);");
speedtest1_exec("CREATE INDEX t2c ON t2(c DESC);");
speedtest1_exec("CREATE INDEX t3bc ON t3(b,c);");
speedtest1_exec("COMMIT;");
speedtest1_end_test();
@@ -864,7 +864,7 @@ void testset_main(void){
speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -884,7 +884,7 @@ void testset_main(void){
speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z2\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t2\n"
" WHERE a BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -904,7 +904,7 @@ void testset_main(void){
speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM z1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
" WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n
);
for(i=1; i<=n; i++){
@@ -930,14 +930,14 @@ void testset_main(void){
isTemp(1), g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
speedtest1_exec("CREATE INDEX t4b ON t4(b)");
speedtest1_exec("CREATE INDEX t4c ON t4(c)");
speedtest1_exec("INSERT INTO t4 SELECT * FROM z1");
speedtest1_exec("INSERT INTO t4 SELECT * FROM t1");
speedtest1_exec("COMMIT");
speedtest1_end_test();
n = sz;
speedtest1_begin_test(190, "DELETE and REFILL one table", n);
speedtest1_exec("DELETE FROM z2;");
speedtest1_exec("INSERT INTO z2 SELECT * FROM z1;");
speedtest1_exec("DELETE FROM t2;");
speedtest1_exec("INSERT INTO t2 SELECT * FROM t1;");
speedtest1_end_test();
@@ -947,8 +947,8 @@ void testset_main(void){
speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query");
speedtest1_exec("ALTER TABLE z2 ADD COLUMN d DEFAULT 123");
speedtest1_exec("SELECT sum(d) FROM z2");
speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123");
speedtest1_exec("SELECT sum(d) FROM t2");
speedtest1_end_test();
@@ -956,7 +956,7 @@ void testset_main(void){
speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"UPDATE z2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
"UPDATE t2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb;
@@ -973,7 +973,7 @@ void testset_main(void){
speedtest1_begin_test(240, "%d UPDATES of individual rows", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"UPDATE z2 SET d=b*3 WHERE a=?1; -- %d times", n
"UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%sz + 1;
@@ -984,12 +984,12 @@ void testset_main(void){
speedtest1_end_test();
speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz);
speedtest1_exec("UPDATE z2 SET d=b*4");
speedtest1_exec("UPDATE t2 SET d=b*4");
speedtest1_end_test();
speedtest1_begin_test(260, "Query added column after filling");
speedtest1_exec("SELECT sum(d) FROM z2");
speedtest1_exec("SELECT sum(d) FROM t2");
speedtest1_end_test();
@@ -998,7 +998,7 @@ void testset_main(void){
speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"DELETE FROM z2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
"DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%maxb + 1;
@@ -1027,16 +1027,16 @@ void testset_main(void){
speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz);
speedtest1_exec("REPLACE INTO z2(a,b,c) SELECT a,b,c FROM z1");
speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM z1");
speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1");
speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1");
speedtest1_end_test();
speedtest1_begin_test(300, "Refill a %d-row table using (b&1)==(a&1)", sz);
speedtest1_exec("DELETE FROM z2;");
speedtest1_exec("INSERT INTO z2(a,b,c)\n"
" SELECT a,b,c FROM z1 WHERE (b&1)==(a&1);");
speedtest1_exec("INSERT INTO z2(a,b,c)\n"
" SELECT a,b,c FROM z1 WHERE (b&1)<>(a&1);");
speedtest1_exec("DELETE FROM t2;");
speedtest1_exec("INSERT INTO t2(a,b,c)\n"
" SELECT a,b,c FROM t1 WHERE (b&1)==(a&1);");
speedtest1_exec("INSERT INTO t2(a,b,c)\n"
" SELECT a,b,c FROM t1 WHERE (b&1)<>(a&1);");
speedtest1_end_test();
@@ -1044,11 +1044,11 @@ void testset_main(void){
speedtest1_begin_test(310, "%d four-ways joins", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT z1.c FROM z1, z2, t3, t4\n"
"SELECT t1.c FROM t1, t2, t3, t4\n"
" WHERE t4.a BETWEEN ?1 AND ?2\n"
" AND t3.a=t4.b\n"
" AND z2.a=t3.b\n"
" AND z1.c=z2.c"
" AND t2.a=t3.b\n"
" AND t1.c=t2.c"
);
for(i=1; i<=n; i++){
x1 = speedtest1_random()%sz + 1;
@@ -1063,8 +1063,8 @@ void testset_main(void){
speedtest1_begin_test(320, "subquery in result set", n);
speedtest1_prepare(
"SELECT sum(a), max(c),\n"
" avg((SELECT a FROM z2 WHERE 5+z2.b=z1.b) AND rowid<?1), max(c)\n"
" FROM z1 WHERE rowid<?1;"
" avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n"
" FROM t1 WHERE rowid<?1;"
);
sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50);
speedtest1_run();
@@ -1282,10 +1282,10 @@ void testset_cte(void){
speedtest1_begin_test(400, "EXCEPT operator on %d-element tables", nElem);
speedtest1_prepare(
"WITH RECURSIVE \n"
" z1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM z1 WHERE x<%d),\n"
" z2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM z2 WHERE y<%d)\n"
" t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<%d),\n"
" t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<%d)\n"
"SELECT count(x), avg(x) FROM (\n"
" SELECT x FROM z1 EXCEPT SELECT y FROM z2 ORDER BY 1\n"
" SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1\n"
");",
nElem, nElem
);
@@ -1318,9 +1318,9 @@ void testset_fp(void){
n = g.szTest*5000;
speedtest1_begin_test(100, "Fill a table with %d FP values", n*2);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE%s TABLE z1(a REAL %s, b REAL %s);",
speedtest1_exec("CREATE%s TABLE t1(a REAL %s, b REAL %s);",
isTemp(1), g.zNN, g.zNN);
speedtest1_prepare("INSERT INTO z1 VALUES(?1,?2); -- %d times", n);
speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2); -- %d times", n);
for(i=1; i<=n; i++){
speedtest1_random_ascii_fp(zFP1);
speedtest1_random_ascii_fp(zFP2);
@@ -1333,7 +1333,7 @@ void testset_fp(void){
n = g.szTest/25 + 2;
speedtest1_begin_test(110, "%d range queries", n);
speedtest1_prepare("SELECT sum(b) FROM z1 WHERE a BETWEEN ?1 AND ?2");
speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2");
for(i=1; i<=n; i++){
speedtest1_random_ascii_fp(zFP1);
speedtest1_random_ascii_fp(zFP2);
@@ -1345,15 +1345,15 @@ void testset_fp(void){
speedtest1_begin_test(120, "CREATE INDEX three times");
speedtest1_exec("BEGIN;");
speedtest1_exec("CREATE INDEX t1a ON z1(a);");
speedtest1_exec("CREATE INDEX t1b ON z1(b);");
speedtest1_exec("CREATE INDEX t1ab ON z1(a,b);");
speedtest1_exec("CREATE INDEX t1a ON t1(a);");
speedtest1_exec("CREATE INDEX t1b ON t1(b);");
speedtest1_exec("CREATE INDEX t1ab ON t1(a,b);");
speedtest1_exec("COMMIT;");
speedtest1_end_test();
n = g.szTest/3 + 2;
speedtest1_begin_test(130, "%d indexed range queries", n);
speedtest1_prepare("SELECT sum(b) FROM z1 WHERE a BETWEEN ?1 AND ?2");
speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2");
for(i=1; i<=n; i++){
speedtest1_random_ascii_fp(zFP1);
speedtest1_random_ascii_fp(zFP2);
@@ -1365,14 +1365,14 @@ void testset_fp(void){
n = g.szTest*5000;
speedtest1_begin_test(140, "%d calls to round()", n);
speedtest1_exec("SELECT sum(round(a,2)+round(b,4)) FROM z1;");
speedtest1_exec("SELECT sum(round(a,2)+round(b,4)) FROM t1;");
speedtest1_end_test();
speedtest1_begin_test(150, "%d printf() calls", n*4);
speedtest1_exec(
"WITH c(fmt) AS (VALUES('%%g'),('%%e'),('%%!g'),('%%.20f'))"
"SELECT sum(printf(fmt,a)) FROM z1, c"
"SELECT sum(printf(fmt,a)) FROM t1, c"
);
speedtest1_end_test();
}
@@ -1458,8 +1458,8 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
speedtest1_begin_test(101, "Copy from rtree to a regular table");
speedtest1_exec("CREATE TABLE z1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
speedtest1_exec("INSERT INTO z1 SELECT * FROM rt1");
speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
speedtest1_end_test();
n = g.szTest*200;
@@ -1477,7 +1477,7 @@ void testset_rtree(int p1, int p2){
if( g.bVerify ){
n = g.szTest*200;
speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries");
speedtest1_prepare("SELECT count(*) FROM z1 WHERE x0>=?1 AND x1<=?2");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
@@ -1506,7 +1506,7 @@ void testset_rtree(int p1, int p2){
if( g.bVerify ){
n = g.szTest*200;
speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries");
speedtest1_prepare("SELECT count(*) FROM z1 WHERE y1>=?1 AND y0<=?2");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
@@ -1602,7 +1602,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
speedtest1_begin_test(170, "Restore deleted entries using INSERT OR IGNORE");
speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM z1");
speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM t1");
speedtest1_end_test();
}
#endif /* SQLITE_ENABLE_RTREE */
@@ -1887,11 +1887,11 @@ void testset_trigger(void){
speedtest1_exec(
"BEGIN;"
"CREATE TABLE z1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
"CREATE TABLE z2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
"CREATE TABLE t1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
"CREATE TABLE t2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
"CREATE TABLE t3(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);"
"CREATE VIEW v1 AS SELECT rowid, i, t FROM z1;"
"CREATE VIEW v2 AS SELECT rowid, i, t FROM z2;"
"CREATE VIEW v1 AS SELECT rowid, i, t FROM t1;"
"CREATE VIEW v2 AS SELECT rowid, i, t FROM t2;"
"CREATE VIEW v3 AS SELECT rowid, i, t FROM t3;"
);
for(jj=1; jj<=3; jj++){
@@ -1905,22 +1905,22 @@ void testset_trigger(void){
}
}
speedtest1_exec(
"CREATE INDEX i1 ON z1(t);"
"CREATE INDEX i2 ON z2(t);"
"CREATE INDEX i1 ON t1(t);"
"CREATE INDEX i2 ON t2(t);"
"CREATE INDEX i3 ON t3(t);"
"COMMIT;"
);
speedtest1_begin_test(100, "speed4p-join1");
speedtest1_prepare(
"SELECT * FROM z1, z2, t3 WHERE z1.oid = z2.oid AND z2.oid = t3.oid"
"SELECT * FROM t1, t2, t3 WHERE t1.oid = t2.oid AND t2.oid = t3.oid"
);
speedtest1_run();
speedtest1_end_test();
speedtest1_begin_test(110, "speed4p-join2");
speedtest1_prepare(
"SELECT * FROM z1, z2, t3 WHERE z1.t = z2.t AND z2.t = t3.t"
"SELECT * FROM t1, t2, t3 WHERE t1.t = t2.t AND t2.t = t3.t"
);
speedtest1_run();
speedtest1_end_test();
@@ -1957,8 +1957,8 @@ void testset_trigger(void){
speedtest1_begin_test(150, "speed4p-subselect1");
speedtest1_prepare("SELECT "
"(SELECT t FROM z1 WHERE rowid = ?1),"
"(SELECT t FROM z2 WHERE rowid = ?1),"
"(SELECT t FROM t1 WHERE rowid = ?1),"
"(SELECT t FROM t2 WHERE rowid = ?1),"
"(SELECT t FROM t3 WHERE rowid = ?1)"
);
for(jj=0; jj<NROW2; jj++){
@@ -1969,7 +1969,7 @@ void testset_trigger(void){
speedtest1_begin_test(160, "speed4p-rowid-update");
speedtest1_exec("BEGIN");
speedtest1_prepare("UPDATE z1 SET i=i+1 WHERE rowid=?1");
speedtest1_prepare("UPDATE t1 SET i=i+1 WHERE rowid=?1");
for(jj=0; jj<NROW2; jj++){
sqlite3_bind_int(g.pStmt, 1, jj);
speedtest1_run();
@@ -1979,7 +1979,7 @@ void testset_trigger(void){
speedtest1_exec("CREATE TABLE t5(t TEXT PRIMARY KEY, i INTEGER);");
speedtest1_begin_test(170, "speed4p-insert-ignore");
speedtest1_exec("INSERT OR IGNORE INTO t5 SELECT t, i FROM z1");
speedtest1_exec("INSERT OR IGNORE INTO t5 SELECT t, i FROM t1");
speedtest1_end_test();
speedtest1_exec(
-628
View File
@@ -1,628 +0,0 @@
/*
** 2021-01-01
**
** 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 a program used to measure the start-up performance
** of SQLite.
**
** To use:
**
** ./startup init
** valgrind --tool=cachegrind ./startup run
**
**
** The "./startup init" command creates the test database file named
** "startup.db". The performance test is run by the "./startup run"
** command. That command does nothing but open the database file and
** parse the entire schema.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "sqlite3.h"
static const char zHelp[] =
"Usage: %s COMMAND\n"
"Commands:\n"
" init Initialized the startup.db database file\n"
" run Run the startup performance test\n"
"Options:\n"
" --dbname NAME Set the name of the test database file\n"
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
" --stats Show statistics at the end\n"
/* TBD
" --journal M Set the journal_mode to M\n"
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
" --mmap SZ MMAP the first SZ bytes of the database file\n"
" --multithread Set multithreaded mode\n"
" --nomemstat Disable memory statistics\n"
" --pagesize N Set the page size to N\n"
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
" --serialized Set serialized threading mode\n"
" --singlethread Set single-threaded mode - disables all mutexing\n"
" --utf16be Set text encoding to UTF-16BE\n"
" --utf16le Set text encoding to UTF-16LE\n"
" --utf8 Set text encoding to UTF-8\n"
*/
;
static void usage(const char *argv0){
printf(zHelp, argv0);
exit(1);
}
/*
** The test schema is derived from the Fossil repository for SQLite itself.
** The schema covers the repository, the local checkout database, and
** the global configuration database.
*/
static const char zTestSchema[] =
"CREATE TABLE repo_blob(\n"
" rid INTEGER PRIMARY KEY,\n"
" rcvid INTEGER,\n"
" size INTEGER,\n"
" uuid TEXT UNIQUE NOT NULL,\n"
" content BLOB,\n"
" CHECK( length(uuid)>=40 AND rid>0 )\n"
");\n"
"CREATE TABLE repo_delta(\n"
" rid INTEGER PRIMARY KEY,\n"
" srcid INTEGER NOT NULL REFERENCES blob\n"
");\n"
"CREATE TABLE repo_rcvfrom(\n"
" rcvid INTEGER PRIMARY KEY,\n"
" uid INTEGER REFERENCES user,\n"
" mtime DATETIME,\n"
" nonce TEXT UNIQUE,\n"
" ipaddr TEXT\n"
");\n"
"CREATE TABLE repo_private(rid INTEGER PRIMARY KEY);\n"
"CREATE TABLE repo_accesslog(\n"
" uname TEXT,\n"
" ipaddr TEXT,\n"
" success BOOLEAN,\n"
" mtime TIMESTAMP);\n"
"CREATE TABLE repo_user(\n"
" uid INTEGER PRIMARY KEY,\n"
" login TEXT UNIQUE,\n"
" pw TEXT,\n"
" cap TEXT,\n"
" cookie TEXT,\n"
" ipaddr TEXT,\n"
" cexpire DATETIME,\n"
" info TEXT,\n"
" mtime DATE,\n"
" photo BLOB\n"
");\n"
"CREATE TABLE repo_reportfmt(\n"
" rn INTEGER PRIMARY KEY,\n"
" owner TEXT,\n"
" title TEXT UNIQUE,\n"
" mtime INTEGER,\n"
" cols TEXT,\n"
" sqlcode TEXT\n"
");\n"
"CREATE TABLE repo_sqlite_stat2(tbl,idx,sampleno,sample);\n"
"CREATE TABLE repo_sqlite_stat1(tbl,idx,stat);\n"
"CREATE TABLE repo_sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);\n"
"CREATE TABLE repo_config(\n"
" name TEXT PRIMARY KEY NOT NULL,\n"
" value CLOB, mtime INTEGER,\n"
" CHECK( typeof(name)='text' AND length(name)>=1 )\n"
") WITHOUT ROWID;\n"
"CREATE TABLE repo_shun(uuid PRIMARY KEY,\n"
" mtime INTEGER,\n"
" scom TEXT) WITHOUT ROWID;\n"
"CREATE TABLE repo_concealed(\n"
" hash TEXT PRIMARY KEY,\n"
" content TEXT\n"
", mtime INTEGER) WITHOUT ROWID;\n"
"CREATE TABLE repo_admin_log(\n"
" id INTEGER PRIMARY KEY,\n"
" time INTEGER, -- Seconds since 1970\n"
" page TEXT, -- path of page\n"
" who TEXT, -- User who made the change\n"
" what TEXT -- What changed\n"
");\n"
"CREATE TABLE repo_unversioned(\n"
" name TEXT PRIMARY KEY,\n"
" rcvid INTEGER,\n"
" mtime DATETIME,\n"
" hash TEXT,\n"
" sz INTEGER,\n"
" encoding INT,\n"
" content BLOB\n"
") WITHOUT ROWID;\n"
"CREATE TABLE repo_subscriber(\n"
" subscriberId INTEGER PRIMARY KEY,\n"
" subscriberCode BLOB DEFAULT (randomblob(32)) UNIQUE,\n"
" semail TEXT UNIQUE COLLATE nocase,\n"
" suname TEXT,\n"
" sverified BOOLEAN DEFAULT true,\n"
" sdonotcall BOOLEAN,\n"
" sdigest BOOLEAN,\n"
" ssub TEXT,\n"
" sctime INTDATE,\n"
" mtime INTDATE,\n"
" smip TEXT\n"
");\n"
"CREATE TABLE repo_pending_alert(\n"
" eventid TEXT PRIMARY KEY,\n"
" sentSep BOOLEAN DEFAULT false,\n"
" sentDigest BOOLEAN DEFAULT false\n"
", sentMod BOOLEAN DEFAULT false) WITHOUT ROWID;\n"
"CREATE INDEX repo_delta_i1 ON repo_delta(srcid);\n"
"CREATE INDEX repo_blob_rcvid ON repo_blob(rcvid);\n"
"CREATE INDEX repo_subscriberUname\n"
" ON repo_subscriber(suname) WHERE suname IS NOT NULL;\n"
"CREATE VIEW repo_artifact(rid,rcvid,size,atype,srcid,hash,content) AS\n"
" SELECT blob.rid,rcvid,size,1,srcid,uuid,content\n"
" FROM repo_blob LEFT JOIN repo_delta ON (blob.rid=delta.rid);\n"
"CREATE TABLE repo_filename(\n"
" fnid INTEGER PRIMARY KEY,\n"
" name TEXT UNIQUE\n"
");\n"
"CREATE TABLE repo_mlink(\n"
" mid INTEGER,\n"
" fid INTEGER,\n"
" pmid INTEGER,\n"
" pid INTEGER,\n"
" fnid INTEGER REFERENCES filename,\n"
" pfnid INTEGER,\n"
" mperm INTEGER,\n"
" isaux BOOLEAN DEFAULT 0\n"
");\n"
"CREATE INDEX repo_mlink_i1 ON repo_mlink(mid);\n"
"CREATE INDEX repo_mlink_i2 ON repo_mlink(fnid);\n"
"CREATE INDEX repo_mlink_i3 ON repo_mlink(fid);\n"
"CREATE INDEX repo_mlink_i4 ON repo_mlink(pid);\n"
"CREATE TABLE repo_plink(\n"
" pid INTEGER REFERENCES blob,\n"
" cid INTEGER REFERENCES blob,\n"
" isprim BOOLEAN,\n"
" mtime DATETIME,\n"
" baseid INTEGER REFERENCES blob,\n"
" UNIQUE(pid, cid)\n"
");\n"
"CREATE INDEX repo_plink_i2 ON repo_plink(cid,pid);\n"
"CREATE TABLE repo_leaf(rid INTEGER PRIMARY KEY);\n"
"CREATE TABLE repo_event(\n"
" type TEXT,\n"
" mtime DATETIME,\n"
" objid INTEGER PRIMARY KEY,\n"
" tagid INTEGER,\n"
" uid INTEGER REFERENCES user,\n"
" bgcolor TEXT,\n"
" euser TEXT,\n"
" user TEXT,\n"
" ecomment TEXT,\n"
" comment TEXT,\n"
" brief TEXT,\n"
" omtime DATETIME\n"
");\n"
"CREATE INDEX repo_event_i1 ON repo_event(mtime);\n"
"CREATE TABLE repo_phantom(\n"
" rid INTEGER PRIMARY KEY\n"
");\n"
"CREATE TABLE repo_orphan(\n"
" rid INTEGER PRIMARY KEY,\n"
" baseline INTEGER\n"
");\n"
"CREATE INDEX repo_orphan_baseline ON repo_orphan(baseline);\n"
"CREATE TABLE repo_unclustered(\n"
" rid INTEGER PRIMARY KEY\n"
");\n"
"CREATE TABLE repo_unsent(\n"
" rid INTEGER PRIMARY KEY\n"
");\n"
"CREATE TABLE repo_tag(\n"
" tagid INTEGER PRIMARY KEY,\n"
" tagname TEXT UNIQUE\n"
");\n"
"CREATE TABLE repo_tagxref(\n"
" tagid INTEGER REFERENCES tag,\n"
" tagtype INTEGER,\n"
" srcid INTEGER REFERENCES blob,\n"
" origid INTEGER REFERENCES blob,\n"
" value TEXT,\n"
" mtime TIMESTAMP,\n"
" rid INTEGER REFERENCE blob,\n"
" UNIQUE(rid, tagid)\n"
");\n"
"CREATE INDEX repo_tagxref_i1 ON repo_tagxref(tagid, mtime);\n"
"CREATE TABLE repo_backlink(\n"
" target TEXT,\n"
" srctype INT,\n"
" srcid INT,\n"
" mtime TIMESTAMP,\n"
" UNIQUE(target, srctype, srcid)\n"
");\n"
"CREATE INDEX repo_backlink_src ON repo_backlink(srcid, srctype);\n"
"CREATE TABLE repo_attachment(\n"
" attachid INTEGER PRIMARY KEY,\n"
" isLatest BOOLEAN DEFAULT 0,\n"
" mtime TIMESTAMP,\n"
" src TEXT,\n"
" target TEXT,\n"
" filename TEXT,\n"
" comment TEXT,\n"
" user TEXT\n"
");\n"
"CREATE INDEX repo_attachment_idx1\n"
" ON repo_attachment(target, filename, mtime);\n"
"CREATE INDEX repo_attachment_idx2 ON repo_attachment(src);\n"
"CREATE TABLE repo_cherrypick(\n"
" parentid INT,\n"
" childid INT,\n"
" isExclude BOOLEAN DEFAULT false,\n"
" PRIMARY KEY(parentid, childid)\n"
") WITHOUT ROWID;\n"
"CREATE INDEX repo_cherrypick_cid ON repo_cherrypick(childid);\n"
"CREATE TABLE repo_ticket(\n"
" -- Do not change any column that begins with tkt_\n"
" tkt_id INTEGER PRIMARY KEY,\n"
" tkt_uuid TEXT UNIQUE,\n"
" tkt_mtime DATE,\n"
" tkt_ctime DATE,\n"
" -- Add as many fields as required below this line\n"
" type TEXT,\n"
" status TEXT,\n"
" subsystem TEXT,\n"
" priority TEXT,\n"
" severity TEXT,\n"
" foundin TEXT,\n"
" private_contact TEXT,\n"
" resolution TEXT,\n"
" title TEXT,\n"
" comment TEXT\n"
");\n"
"CREATE TABLE repo_ticketchng(\n"
" -- Do not change any column that begins with tkt_\n"
" tkt_id INTEGER REFERENCES ticket,\n"
" tkt_rid INTEGER REFERENCES blob,\n"
" tkt_mtime DATE,\n"
" -- Add as many fields as required below this line\n"
" login TEXT,\n"
" username TEXT,\n"
" mimetype TEXT,\n"
" icomment TEXT\n"
");\n"
"CREATE INDEX repo_ticketchng_idx1 ON repo_ticketchng(tkt_id, tkt_mtime);\n"
"CREATE TRIGGER repo_alert_trigger1\n"
"AFTER INSERT ON repo_event BEGIN\n"
" INSERT INTO repo_pending_alert(eventid)\n"
" SELECT printf('%.1c%d',new.type,new.objid) WHERE true\n"
" ON CONFLICT(eventId) DO NOTHING;\n"
"END;\n"
"CREATE TABLE repo_vcache(\n"
" vid INTEGER, -- check-in ID\n"
" fname TEXT, -- filename\n"
" rid INTEGER, -- artifact ID\n"
" PRIMARY KEY(vid,fname)\n"
") WITHOUT ROWID;\n"
"CREATE TABLE localdb_vvar(\n"
" name TEXT PRIMARY KEY NOT NULL,\n"
" value CLOB,\n"
" CHECK( typeof(name)='text' AND length(name)>=1 )\n"
");\n"
"CREATE TABLE localdb_vfile(\n"
" id INTEGER PRIMARY KEY,\n"
" vid INTEGER REFERENCES blob,\n"
" chnged INT DEFAULT 0,\n"
" deleted BOOLEAN DEFAULT 0,\n"
" isexe BOOLEAN,\n"
" islink BOOLEAN,\n"
" rid INTEGER,\n"
" mrid INTEGER,\n"
" mtime INTEGER,\n"
" pathname TEXT,\n"
" origname TEXT, mhash,\n"
" UNIQUE(pathname,vid)\n"
");\n"
"CREATE TABLE localdb_sqlite_stat1(tbl,idx,stat);\n"
"CREATE TABLE localdb_vcache(\n"
" vid INTEGER, -- check-in ID\n"
" fname TEXT, -- filename\n"
" rid INTEGER, -- artifact ID\n"
" PRIMARY KEY(vid,fname)\n"
") WITHOUT ROWID;\n"
"CREATE TABLE localdb_stash(\n"
" stashid INTEGER PRIMARY KEY,\n"
" vid INTEGER,\n"
" hash TEXT,\n"
" comment TEXT,\n"
" ctime TIMESTAMP\n"
");\n"
"CREATE TABLE localdb_stashfile(\n"
" stashid INTEGER REFERENCES stash,\n"
" isAdded BOOLEAN,\n"
" isRemoved BOOLEAN,\n"
" isExec BOOLEAN,\n"
" isLink BOOLEAN,\n"
" rid INTEGER,\n"
" hash TEXT,\n"
" origname TEXT,\n"
" newname TEXT,\n"
" delta BLOB,\n"
" PRIMARY KEY(newname, stashid)\n"
");\n"
"CREATE TABLE localdb_vmerge(\n"
" id INTEGER REFERENCES vfile,\n"
" merge INTEGER,\n"
" mhash TEXT\n"
");\n"
"CREATE UNIQUE INDEX localdb_vmergex1 ON localdb_vmerge(id,mhash);\n"
"CREATE TRIGGER localdb_vmerge_ck1 AFTER INSERT ON localdb_vmerge\n"
"WHEN new.mhash IS NULL BEGIN\n"
" SELECT raise(FAIL,\n"
" 'trying to update a newer checkout with an older version of Fossil');\n"
"END;\n"
"CREATE TABLE configdb_global_config(\n"
" name TEXT PRIMARY KEY,\n"
" value TEXT\n"
");\n"
"CREATE TABLE configdb_sqlite_stat1(tbl,idx,stat);\n"
;
#ifdef __linux__
#include <sys/types.h>
#include <unistd.h>
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
FILE *in;
char z[200];
sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
in = fopen(z, "rb");
if( in==0 ) return;
while( fgets(z, sizeof(z), in)!=0 ){
static const struct {
const char *zPattern;
const char *zDesc;
} aTrans[] = {
{ "rchar: ", "Bytes received by read():" },
{ "wchar: ", "Bytes sent to write():" },
{ "syscr: ", "Read() system calls:" },
{ "syscw: ", "Write() system calls:" },
{ "read_bytes: ", "Bytes rcvd from storage:" },
{ "write_bytes: ", "Bytes sent to storage:" },
{ "cancelled_write_bytes: ", "Cancelled write bytes:" },
};
int i;
for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
int n = (int)strlen(aTrans[i].zPattern);
if( strncmp(aTrans[i].zPattern, z, n)==0 ){
fprintf(out, "-- %-28s %s", aTrans[i].zDesc, &z[n]);
break;
}
}
}
fclose(in);
}
#endif
/*
** Return the value of a hexadecimal digit. Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
if( c>='0' && c<='9' ) return c - '0';
if( c>='a' && c<='f' ) return c - 'a' + 10;
if( c>='A' && c<='F' ) return c - 'A' + 10;
return -1;
}
/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static int integerValue(const char *zArg){
sqlite3_int64 v = 0;
static const struct { char *zSuffix; int iMult; } aMult[] = {
{ "KiB", 1024 },
{ "MiB", 1024*1024 },
{ "GiB", 1024*1024*1024 },
{ "KB", 1000 },
{ "MB", 1000000 },
{ "GB", 1000000000 },
{ "K", 1000 },
{ "M", 1000000 },
{ "G", 1000000000 },
};
int i;
int isNeg = 0;
if( zArg[0]=='-' ){
isNeg = 1;
zArg++;
}else if( zArg[0]=='+' ){
zArg++;
}
if( zArg[0]=='0' && zArg[1]=='x' ){
int x;
zArg += 2;
while( (x = hexDigitValue(zArg[0]))>=0 ){
v = (v<<4) + x;
zArg++;
}
}else{
while( isdigit(zArg[0]) ){
v = v*10 + zArg[0] - '0';
zArg++;
}
}
for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
v *= aMult[i].iMult;
break;
}
}
if( v>0x7fffffff ){
printf("ERROR: parameter too large - max 2147483648\n");
exit(1);
}
return (int)(isNeg? -v : v);
}
int main(int argc, char **argv){
const char *zCmd = 0;
int i;
int bAutovac = 0;
int showStats = 0;
const char *zDbName = "./startup.db";
int nHeap = 0;
int mnHeap = 0;
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]!='-' ){
if( zCmd ){
usage(argv[0]);
}
zCmd = z;
continue;
}
if( z[1]=='-' ) z++;
if( strcmp(z, "-autovacuum")==0 ){
bAutovac = 1;
}else
if( strcmp(z, "-dbname")==0 ){
if( i==argc-1 ){
printf("ERROR: missing argument on \"%s\"\n", argv[0]);
exit(1);
}
zDbName = argv[++i];
}else
if( strcmp(z,"-heap")==0 ){
if( i>=argc-2 ){
printf("ERROR: missing arguments on %s\n", argv[i]);
exit(1);
}
nHeap = integerValue(argv[i+1]);
mnHeap = integerValue(argv[i+2]);
i += 2;
}else
if( strcmp(z,"-stats")==0 ){
showStats = 1;
}else
{
printf("ERROR: unknown option \"%s\"\n", argv[i]);
usage(argv[0]);
}
}
if( zCmd==0 ){
printf("ERROR: no COMMAND specified\n");
usage(argv[0]);
}
if( strcmp(zCmd, "run")==0 ){
sqlite3 *db;
int rc;
char *zErr = 0;
void *pHeap = 0;
if( nHeap>0 ){
pHeap = malloc( nHeap );
if( pHeap==0 ){
printf("ERROR: cannot allocate %d-byte heap\n", nHeap);
exit(1);
}
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
if( rc ){
printf("ERROR: heap configuration failed: %d\n", rc);
exit(1);
}
}
rc = sqlite3_open(zDbName, &db);
if( rc ){
printf("SQLite error: %s\n", sqlite3_errmsg(db));
}else{
sqlite3_exec(db, "PRAGMA synchronous", 0, 0, &zErr);
}
if( zErr ){
printf("ERROR: %s\n", zErr);
sqlite3_free(zErr);
}
if( showStats ){
int iCur, iHi;
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
printf("-- Lookaside Slots Used: %d (max %d)\n", iCur,iHi);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
printf("-- Successful lookasides: %d\n", iHi);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
printf("-- Lookaside size faults: %d\n", iHi);
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
printf("-- Lookaside OOM faults: %d\n", iHi);
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
printf("-- Pager Heap Usage: %d bytes\n", iCur);
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
printf("-- Page cache hits: %d\n", iCur);
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
printf("-- Page cache misses: %d\n", iCur);
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
printf("-- Page cache writes: %d\n", iCur);
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
printf("-- Schema Heap Usage: %d bytes\n", iCur);
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
printf("-- Statement Heap Usage: %d bytes\n", iCur);
}
sqlite3_close(db);
free(pHeap);
/* Global memory usage statistics printed after the database connection
** has closed. Memory usage should be zero at this point. */
if( showStats ){
int iCur, iHi;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
printf("-- Memory Used (bytes): %d (max %d)\n", iCur,iHi);
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
printf("-- Outstanding Allocations: %d (max %d)\n", iCur,iHi);
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi);
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
printf("-- Largest Allocation: %d bytes\n",iHi);
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
printf("-- Largest Pcache Allocation: %d bytes\n",iHi);
#ifdef __linux__
displayLinuxIoStats(stdout);
#endif
}
return 0;
}
if( strcmp(zCmd, "init")==0 ){
sqlite3 *db;
char *zAux;
char *zErr = 0;
int rc;
unlink(zDbName);
zAux = sqlite3_mprintf("%s-journal", zDbName);
unlink(zAux);
sqlite3_free(zAux);
zAux = sqlite3_mprintf("%s-wal", zDbName);
unlink(zAux);
sqlite3_free(zAux);
rc = sqlite3_open(zDbName, &db);
if( rc ){
printf("SQLite error: %s\n", sqlite3_errmsg(db));
}else{
sqlite3_exec(db, "BEGIN", 0, 0, 0);
sqlite3_exec(db, zTestSchema, 0, 0, &zErr);
sqlite3_exec(db, "COMMIT", 0, 0, 0);
}
if( zErr ){
printf("ERROR: %s\n", zErr);
sqlite3_free(zErr);
}
sqlite3_close(db);
return 0;
}
}
+1 -4
View File
@@ -1689,12 +1689,9 @@ proc crashsql {args} {
set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
set f [open crash.tcl w]
puts $f "sqlite3_initialize ; sqlite3_shutdown"
puts $f "catch { install_malloc_faultsim 1 }"
puts $f "sqlite3_crash_enable 1 $dfltvfs"
puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
puts $f "autoinstall_test_functions"
# This block sets the cache size of the main database to 10
# pages. This is done in case the build is configured to omit
@@ -1722,7 +1719,7 @@ proc crashsql {args} {
}
close $f
set r [catch {
exec [info nameofexec] crash.tcl >@stdout 2>@stdout
exec [info nameofexec] crash.tcl >@stdout
} msg]
# Windows/ActiveState TCL returns a slightly different
-79
View File
@@ -251,83 +251,4 @@ do_test trace3-11.2 {
set ::stmtlist(record)
} {/^-?\d+$/}
#-------------------------------------------------------------------------
reset_db
do_test 12.1.0 {
set ::STMT [sqlite3_prepare_v2 $DB \
"SELECT ?1 || ?1 || ?1 || ?2 || ?3 || ?4 || ? || ?1 || ?" -1 TAIL
]
sqlite3_bind_parameter_count $::STMT
} {6}
do_test 12.1.1 {
sqlite3_bind_text $STMT 1 "A" 1
sqlite3_bind_text $STMT 2 "B" 1
sqlite3_bind_text $STMT 3 "C" 1
sqlite3_bind_text $STMT 4 "D" 1
sqlite3_bind_text $STMT 5 "E" 1
sqlite3_bind_text $STMT 6 "F" 1
sqlite3_expanded_sql $STMT
} {SELECT 'A' || 'A' || 'A' || 'B' || 'C' || 'D' || 'E' || 'A' || 'F'}
do_test 12.1.2 {
sqlite3_step $STMT
sqlite3_column_text $STMT 0
} {AAABCDEAF}
do_test 12.1.3 {
sqlite3_finalize $STMT
} {SQLITE_OK}
do_test 12.2.0 {
execsql {
CREATE TABLE nameFtsFuzzySearchTable(
word, distance, langid, score, top, scope
);
}
set ::STMT [sqlite3_prepare_v2 $DB {
SELECT
substr(word,1,length(?1)-1) AS term,
distance,
langid,
score
FROM
nameFtsFuzzySearchTable
WHERE
word MATCH (?1) AND abs(?1) = abs(term)
AND top = ?2 AND distance > ?3 AND scope = ?4 AND langid = ?
GROUP BY term, langid
HAVING (1.0 - ((distance / 100.0) / CAST( length(?1) - 1 AS REAL ))) >= ?
} -1 TAIL]
sqlite3_bind_parameter_count $::STMT
} {6}
do_test 12.1.1 {
sqlite3_bind_text $STMT 1 "A" 1
sqlite3_bind_text $STMT 2 "B" 1
sqlite3_bind_text $STMT 3 "C" 1
sqlite3_bind_text $STMT 4 "D" 1
sqlite3_bind_text $STMT 5 "E" 1
sqlite3_bind_text $STMT 6 "F" 1
sqlite3_expanded_sql $STMT
} {
SELECT
substr(word,1,length('A')-1) AS term,
distance,
langid,
score
FROM
nameFtsFuzzySearchTable
WHERE
word MATCH ('A') AND abs('A') = abs(term)
AND top = 'B' AND distance > 'C' AND scope = 'D' AND langid = 'E'
GROUP BY term, langid
HAVING (1.0 - ((distance / 100.0) / CAST( length('A') - 1 AS REAL ))) >= 'F'
}
do_test 12.1.2 {
sqlite3_finalize $STMT
} {SQLITE_OK}
finish_test
-329
View File
@@ -1,329 +0,0 @@
# 2020-12-16
#
# 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. The
# focus of this file is flattening UNION ALL sub-queries.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionall
do_execsql_test 1.0 {
CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
CREATE TABLE t1_c(e INTEGER PRIMARY KEY, f TEXT);
INSERT INTO t1_a VALUES(1, 'one'), (4, 'four');
INSERT INTO t1_b VALUES(2, 'two'), (5, 'five');
INSERT INTO t1_c VALUES(3, 'three'), (6, 'six');
CREATE VIEW t1 AS
SELECT a, b FROM t1_a UNION ALL
SELECT c, d FROM t1_b UNION ALL
SELECT e, f FROM t1_c;
CREATE TABLE i1(x);
INSERT INTO i1 VALUES(2), (5), (6), (1);
}
do_execsql_test 1.1 {
SELECT a, b FROM (
SELECT a, b FROM t1_a UNION ALL
SELECT c, d FROM t1_b UNION ALL
SELECT e, f FROM t1_c
) ORDER BY a
} {
1 one 2 two 3 three 4 four 5 five 6 six
}
do_execsql_test 1.2 {
SELECT a, b FROM t1 ORDER BY a
} {
1 one 2 two 3 three 4 four 5 five 6 six
}
do_execsql_test 1.3 {
SELECT a, b FROM i1, t1 WHERE a=x ORDER BY a
} {1 one 2 two 5 five 6 six}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1.0 {
CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(1, 'ONE');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(2, 'TWO');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(3, 'THREE');
}
do_execsql_test 2.1.1 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<3
)
SELECT * FROM (
SELECT 0 AS i UNION ALL SELECT i FROM s UNION ALL SELECT 0
), t1 WHERE x=i;
} {
1 1 one 1 1 ONE 2 2 two 2 2 TWO 3 3 three 3 3 THREE
}
do_catchsql_test 2.1.2 {
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<3 UNION ALL SELECT 4
)
SELECT * FROM s, t1 WHERE x=i;
} {1 {circular reference: s}}
do_execsql_test 2.2.0 {
CREATE TABLE t2_a(k INTEGER PRIMARY KEY, v TEXT);
CREATE TABLE t2_b(k INTEGER PRIMARY KEY, v TEXT);
CREATE VIEW t2 AS
SELECT * FROM t2_a
UNION ALL
SELECT * FROM t2_b;
CREATE TRIGGER t2_insert INSTEAD OF INSERT ON t2 BEGIN
INSERT INTO t2_a SELECT new.k, new.v WHERE (new.k%2)==0;
INSERT INTO t2_b SELECT new.k, new.v WHERE (new.k%2)==1;
END;
INSERT INTO t2 VALUES(5, 'v'), (4, 'iv'), (3, 'iii'), (2, 'ii');
}
do_execsql_test 2.2.1 {
SELECT * FROM t1, t2 WHERE x=k;
} {
2 two 2 ii 2 TWO 2 ii 3 three 3 iii 3 THREE 3 iii
}
do_execsql_test 2.2.2 {
SELECT * FROM t1 LEFT JOIN t2 ON (x=k);
} {
1 one {} {}
1 ONE {} {}
2 two 2 ii 2 TWO 2 ii 3 three 3 iii 3 THREE 3 iii
}
do_execsql_test 2.2.3 {
SELECT x1.*, x2.* FROM t2 AS x1, t2 AS x2 WHERE x1.k=x2.k+1
} {
4 iv 3 iii
3 iii 2 ii
5 v 4 iv
}
do_execsql_test 2.2.4 {
SELECT * FROM t1, t2 WHERE x=k ORDER BY y;
} {
3 THREE 3 iii
2 TWO 2 ii
3 three 3 iii
2 two 2 ii
}
do_execsql_test 2.2.5 {
SELECT * FROM t1, t2 WHERE x=k ORDER BY y||'';
} {
3 THREE 3 iii
2 TWO 2 ii
3 three 3 iii
2 two 2 ii
}
do_execsql_test 2.2.6 {
SELECT * FROM t1, t2 WHERE x=k ORDER BY v
} {
2 two 2 ii
2 TWO 2 ii
3 three 3 iii
3 THREE 3 iii
}
do_execsql_test 2.2.7 {
SELECT * FROM t1, t2 WHERE x=k ORDER BY v||''
} {
2 two 2 ii
2 TWO 2 ii
3 three 3 iii
3 THREE 3 iii
}
do_execsql_test 2.2.8 {
SELECT * FROM t1, t2 WHERE x=k ORDER BY k,v||''
} {
2 two 2 ii
2 TWO 2 ii
3 three 3 iii
3 THREE 3 iii
}
do_execsql_test 2.2.9a {
SELECT * FROM t1, t2 ORDER BY +k
} {
1 one 2 ii 1 ONE 2 ii 2 two 2 ii
2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii
1 one 3 iii 1 ONE 3 iii 2 two 3 iii
2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii
1 one 4 iv 1 ONE 4 iv 2 two 4 iv
2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv
1 one 5 v 1 ONE 5 v 2 two 5 v
2 TWO 5 v 3 three 5 v 3 THREE 5 v
}
do_execsql_test 2.2.9b {
SELECT * FROM t1, t2 ORDER BY k
} {
1 one 2 ii 1 ONE 2 ii 2 two 2 ii
2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii
1 one 3 iii 1 ONE 3 iii 2 two 3 iii
2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii
1 one 4 iv 1 ONE 4 iv 2 two 4 iv
2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv
1 one 5 v 1 ONE 5 v 2 two 5 v
2 TWO 5 v 3 three 5 v 3 THREE 5 v
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE TABLE t1(c INTEGER PRIMARY KEY, d TEXT);
INSERT INTO t1 VALUES(1,2);
CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
INSERT INTO t3_a VALUES(2,'ii');
CREATE TABLE t3_b(k INTEGER PRIMARY KEY, v TEXT);
CREATE VIEW t3 AS
SELECT * FROM t3_a
UNION ALL
SELECT * FROM t3_b;
} {}
do_execsql_test 3.1 {
SELECT * FROM t1, t3 ORDER BY k;
} {1 2 2 ii}
reset_db
do_execsql_test 4.0 {
CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
INSERT INTO t1_a VALUES(123, 't1_a');
CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
CREATE VIEW t1 AS
SELECT a, b FROM t1_a
UNION ALL
SELECT c, d FROM t1_b;
CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
INSERT INTO t3_a VALUES(456, 't3_a');
CREATE TABLE t3_b(k INTEGER PRIMARY KEY, v TEXT);
CREATE VIEW t3 AS
SELECT * FROM t3_a
UNION ALL
SELECT * FROM t3_b;
}
do_execsql_test 4.1 {
SELECT * FROM t1, t3 ORDER BY k;
} {123 t1_a 456 t3_a}
do_execsql_test 4.2 {
SELECT * FROM (SELECT * FROM t1, t3) ORDER BY k;
} {123 t1_a 456 t3_a}
do_execsql_test 4.3 {
SELECT * FROM (SELECT * FROM t1, t3), (
SELECT max(a) OVER () FROM t1
UNION ALL
SELECT min(a) OVER () FROM t1
)
ORDER BY k;
} {
123 t1_a 456 t3_a 123
123 t1_a 456 t3_a 123
}
do_execsql_test 4.3 {
SELECT * FROM (SELECT * FROM t1, t3), (
SELECT group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a),
group_concat(a) OVER (ORDER BY a)
FROM t1
)
ORDER BY k;
} {
123 t1_a 456 t3_a 123 123 123 123 123 123 123 123 123
}
do_execsql_test 4.3 {
SELECT * FROM (SELECT * FROM t1, t3) AS o, (
SELECT * FROM t1 LEFT JOIN t3 ON a=k
);
} {
123 t1_a 456 t3_a 123 t1_a {} {}
}
# 2020-12-30: dbsqlfuzz find
reset_db
do_execsql_test 5.1 {
CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);
INSERT INTO t1_a VALUES(1,'one');
INSERT INTO t1_a VALUES(0,NULL);
CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);
INSERT INTO t1_b VALUES(2,'two');
INSERT INTO t1_b VALUES(5,'five');
CREATE TABLE t1_c(e INTEGER PRIMARY KEY, f TEXT);
INSERT INTO t1_c VALUES(3,'three');
INSERT INTO t1_c VALUES(6,'six');
CREATE TABLE t2(k,v);
INSERT INTO t2 VALUES(5,'v');
INSERT INTO t2 VALUES(4,'iv');
INSERT INTO t2 VALUES(3,'iii');
INSERT INTO t2 VALUES(2,'ii');
CREATE TABLE t3_a(k INTEGER PRIMARY KEY, v TEXT);
INSERT INTO t3_a VALUES(2,'ii');
INSERT INTO t3_a VALUES(4,'iv');
CREATE TABLE t3_b(k INTEG5R PRIMARY KEY, v TEXT);
INSERT INTO t3_b VALUES(NULL,'iii');
INSERT INTO t3_b VALUES(NULL,'v');
CREATE VIEW t1 AS
SELECT a, b FROM t1_a UNION ALL
SELECT c, d FROM t1_b UNION ALL
SELECT e, f FROM t1_c;
CREATE VIEW t3 AS
SELECT * FROM t3_a
UNION ALL
SELECT * FROM t3_b;
CREATE TRIGGER t3_insert INSTEAD OF INSERT ON t3 BEGIN
INSERT INTO t3_a SELECT new.k, new.v WHERE (new.k%2)==0;
INSERT INTO t3_b SELECT new.k, new.v WHERE (new.k%2)==1;
END;
} {}
do_execsql_test 5.10 {
SELECT *, '+' FROM t1 LEFT JOIN t2 ON (a NOT IN(SELECT v FROM t1, t3 WHERE a=k)=NOT EXISTS(SELECT 1 FROM t1 LEFT JOIN t3 ON (a=k)));
} {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +}
do_execsql_test 5.20 {
SELECT *, '+' FROM t1 LEFT JOIN t3 ON (a NOT IN(SELECT v FROM t1 LEFT JOIN t2 ON (a=k))=k);
} {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +}
finish_test
-39
View File
@@ -1,39 +0,0 @@
# 2020-12-22
#
# 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. The
# focus of this file is flattening UNION ALL sub-queries.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionall2
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS SELECT * FROM t1, t2;
CREATE VIEW v2 AS SELECT * FROM t1, t2;
CREATE VIEW vA AS
SELECT * FROM v1, (
SELECT * FROM t1 LEFT JOIN t2 ON (a=c)
)
UNION ALL
SELECT * FROM v1, v2
}
do_execsql_test 1.1 {
SELECT 1 FROM vA, vA, vA, vA, vA, vA, vA, vA, vA, vA
}
finish_test
-36
View File
@@ -1,36 +0,0 @@
# 2020-12-16
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix unionallfault
do_execsql_test 1.0 {
CREATE TABLE t1(x,y,z);
CREATE TABLE t3(x,y,z);
}
faultsim_save_and_close
do_faultsim_test 1 -faults oom-t* -prep {
faultsim_restore_and_reopen
} -body {
execsql {
SELECT * FROM t1, (
SELECT x FROM t1 UNION ALL SELECT y FROM t1
), t3
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
-397
View File
@@ -1,397 +0,0 @@
# 2020-12-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.
#
#***********************************************************************
#
# Test cases for generalized UPSERT
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix upsert5
foreach {tn sql} {
1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) }
2 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) }
3 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE, e UNIQUE) WITHOUT ROWID}
4 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INTEGER PRIMARY KEY, b) }
5 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INT PRIMARY KEY, b) }
6 { CREATE TABLE t1(e UNIQUE, d UNIQUE, c UNIQUE, a INT PRIMARY KEY, b) WITHOUT ROWID}
} {
reset_db
execsql $sql
do_execsql_test 1.$tn.100 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,4,5)
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.101 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,5)
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.102 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,5)
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 d 3 4 5}
do_execsql_test 1.$tn.103 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 e 3 4 5}
do_execsql_test 1.$tn.200 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.201 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.202 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,3,4,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.203 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.204 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.210 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.211 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 d 3 4 5}
do_execsql_test 1.$tn.212 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.213 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 e 3 4 5}
do_execsql_test 1.$tn.214 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e'
ON CONFLICT(a) DO UPDATE SET b='a';
SELECT a,b,c,d,e FROM t1;
} {1 e 3 4 5}
do_execsql_test 1.$tn.215 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e'
ON CONFLICT(a) DO UPDATE SET b='a';
SELECT a,b,c,d,e FROM t1;
} {1 e 3 4 5}
do_execsql_test 1.$tn.216 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(e) DO UPDATE SET b='e'
ON CONFLICT(a) DO UPDATE SET b='a';
SELECT a,b,c,d,e FROM t1;
} {1 a 3 4 5}
do_execsql_test 1.$tn.300 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a1'
ON CONFLICT(a) DO UPDATE SET b='a2'
ON CONFLICT(a) DO UPDATE SET b='a3'
ON CONFLICT(a) DO UPDATE SET b='a4'
ON CONFLICT(a) DO UPDATE SET b='a5'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 a1 3 4 5}
do_execsql_test 1.$tn.301 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT(a) DO UPDATE SET b='a1'
ON CONFLICT(a) DO UPDATE SET b='a2'
ON CONFLICT(a) DO UPDATE SET b='a3'
ON CONFLICT(a) DO UPDATE SET b='a4'
ON CONFLICT(a) DO UPDATE SET b='a5'
ON CONFLICT(e) DO UPDATE SET b='e';
SELECT a,b,c,d,e FROM t1;
} {1 e 3 4 5}
do_execsql_test 1.$tn.400 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.401 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.402 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.403 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.404 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.405 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 d 3 4 5}
do_execsql_test 1.$tn.410 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.411 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.412 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,95)
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.413 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.420 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO NOTHING
ON CONFLICT(d) DO NOTHING
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.421 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO NOTHING
ON CONFLICT(d) DO NOTHING
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 x 3 4 5}
do_execsql_test 1.$tn.422 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,4,95)
ON CONFLICT(c) DO NOTHING
ON CONFLICT(d) DO NOTHING
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 2 3 4 5}
do_execsql_test 1.$tn.423 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
ON CONFLICT(c) DO NOTHING
ON CONFLICT(d) DO NOTHING
ON CONFLICT DO UPDATE set b='x';
SELECT a,b,c,d,e FROM t1;
} {1 2 3 4 5}
do_execsql_test 1.$tn.500 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 2 3 4 5}
do_execsql_test 1.$tn.501 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,93,94,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 2 3 4 5}
do_execsql_test 1.$tn.502 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 2 3 4 5}
do_execsql_test 1.$tn.503 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,94,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.504 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(91,NULL,3,4,95)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 c 3 4 5}
do_execsql_test 1.$tn.505 {
DELETE FROM t1;
INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
INSERT INTO t1(a,b,c,d,e) VALUES(1,NULL,93,4,5)
ON CONFLICT(c) DO UPDATE SET b='c'
ON CONFLICT(d) DO UPDATE SET b='d'
ON CONFLICT DO NOTHING;
SELECT a,b,c,d,e FROM t1;
} {1 d 3 4 5}
}
finish_test
+1 -1
View File
@@ -56,7 +56,7 @@ do_test vacuum2-2.1 {
}
hexio_get_int [hexio_read test.db 24 4]
} [expr {[hexio_get_int [hexio_read test.db 24 4]]+3}]
do_test vacuum2-2.2 {
do_test vacuum2-2.1 {
execsql {
VACUUM
}
-112
View File
@@ -1,112 +0,0 @@
# 2016-08-19
#
# 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 a test for VACUUM on attached databases.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vacuum6
# If the VACUUM statement is disabled in the current build, skip all
# the tests in this file.
#
ifcapable !vacuum {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(1, 1);
} {}
do_execsql_test 1.1 {
VACUUM
}
reset_db
do_execsql_test 1.2 {
CREATE TABLE t1(x,b);
CREATE INDEX x1 ON t1(x);
CREATE INDEX x2 ON t1(x);
CREATE INDEX x3 ON t1(x);
INSERT INTO t1 SELECT 2,'';
VACUUM;
}
#-------------------------------------------------------------------------
#
reset_db
foreach {tn sz} {1 400 2 4000 3 9999} {
reset_db
do_execsql_test 2.$tn.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
)
INSERT INTO t1 SELECT i, randomblob($sz) FROM s;
}
do_execsql_test 2.$tn.2 {
vacuum;
}
do_execsql_test 2.$tn.3 {
PRAGMA integrity_check;
} {ok}
}
reset_db
do_execsql_test 3.0 {
PRAGMA page_size = 1024;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(2, randomblob(1200));
} {}
do_execsql_test 3.1 {
PRAGMA page_size = 512;
VACUUM;
}
do_execsql_test 3.2 {
PRAGMA integrity_check
} {ok}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
CREATE TABLE tx(a, b);
CREATE INDEX i1 ON tx(b);
WITH s(i) AS (
SELECT 8000 UNION ALL SELECT i+1 FROM s WHERE i<10000
)
INSERT INTO tx SELECT i, randomblob(i) FROM s;
SELECT sum(length(b)) FROM tx;
} {18009000}
foreach {tn pgsz av} {
1 2048 0
2 1024 1
3 65536 0
4 8192 1
5 512 0
6 4096 1
} {
do_execsql_test 4.1.$tn.1 "
PRAGMA page_size = $pgsz;
PRAGMA auto_vacuum = $av;
"
do_execsql_test 4.1.$tn.2 VACUUM
integrity_check 4.1.$tn.3
}
finish_test
+1 -8
View File
@@ -146,23 +146,16 @@ proc xWrite {method file args} {
incr ::cnt -1
if {$::cnt==0} {
sqlite3_memdebug_fail 1 -repeat 0
# For this test to pass, the following statement must call malloc() at
# least once. Even if the lookaside is enabled.
set ::xwrite_stmt_res [catchsql { SELECT hex(randomblob(4000)) }]
catchsql { SELECT 'a big long string!' }
sqlite3_interrupt db
}
}
return SQLITE_OK
}
set ::xwrite_stmt_res ""
do_catchsql_test 3.2 {
PRAGMA wal_checkpoint
} {1 {out of memory}}
do_test 3.2.2 {
set ::xwrite_stmt_res
} {1 {out of memory}}
unset ::xwrite_stmt_res
#-------------------------------------------------------------------------
#
+8 -7
View File
@@ -26,13 +26,14 @@ do_eqp_test 110 {
SELECT * FROM t1, v4 WHERE t1.a=?1 AND v4.a=t1.a;
} {
QUERY PLAN
`--COMPOUND QUERY
|--LEFT-MOST SUBQUERY
| |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
| `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
`--UNION ALL
|--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
`--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
|--MATERIALIZE xxxxxx
| `--COMPOUND QUERY
| |--LEFT-MOST SUBQUERY
| | `--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
| `--UNION ALL
| `--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
|--SCAN SUBQUERY xxxxxx
`--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
}
# The scan of the t1 table goes first since that enables the ORDER BY
+6 -6
View File
@@ -401,7 +401,7 @@ struct lemon {
struct symbol *errsym; /* The error symbol */
struct symbol *wildcard; /* Token that matches anything */
char *name; /* Name of the generated parser */
char *arg; /* Declaration of the 3rd argument to parser */
char *arg; /* Declaration of the 3th argument to parser */
char *ctx; /* Declaration of 2nd argument to constructor */
char *tokentype; /* Type of terminal symbols in the parser stack */
char *vartype; /* The default type of non-terminal symbols */
@@ -1027,7 +1027,7 @@ PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
struct state *newstp; /* A pointer to a successor state */
/* Each configuration becomes complete after it contributes to a successor
/* Each configuration becomes complete after it contibutes to a successor
** state. Initially, all configurations are incomplete */
for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
@@ -1887,7 +1887,7 @@ static char *merge(
**
** Return Value:
** A pointer to the head of a sorted list containing the elements
** originally in list.
** orginally in list.
**
** Side effects:
** The "next" pointers for elements in list are changed.
@@ -3513,7 +3513,7 @@ void ReportOutput(struct lemon *lemp)
}
/* Search for the file "name" which is in the same directory as
** the executable */
** the exacutable */
PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
{
const char *pathlist;
@@ -3868,7 +3868,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
lhsdirect = 1;
}else if( rp->rhsalias[0]==0 ){
/* The left-most RHS symbol has no value. LHS direct is ok. But
** we have to call the destructor on the RHS symbol first. */
** we have to call the distructor on the RHS symbol first. */
lhsdirect = 1;
if( has_destructor(rp->rhs[0],lemp) ){
append_str(0,0,0,0);
@@ -4849,7 +4849,7 @@ void ReportTable(
** yyRuleInfoNRhs[].
**
** Note: This code depends on the fact that rules are number
** sequentially beginning with 0.
** sequentually beginning with 0.
*/
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
+53 -48
View File
@@ -718,6 +718,55 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yymsp[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
/* The call to yyStackOverflow() above pops the stack until it is
** empty, causing the main parser loop to exit. So the return value
** is never used and does not matter. */
return 0;
}
yymsp = yypParser->yytos;
}
#endif
}
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -876,56 +925,12 @@ void Parse(
}
#endif
while(1){ /* Exit by "break" */
assert( yypParser->yytos>=yypParser->yystack );
do{
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
if( yyTraceFILE ){
int yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yypParser->yytos[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
assert( yypParser->yyhwm ==
(int)(yypParser->yytos - yypParser->yystack));
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
yyStackOverflow(yypParser);
break;
}
#else
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
break;
}
}
#endif
}
yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor ParseCTX_PARAM);
yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
yyminor ParseCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
@@ -1038,7 +1043,7 @@ void Parse(
break;
#endif
}
}
}while( yypParser->yytos>yypParser->yystack );
#ifndef NDEBUG
if( yyTraceFILE ){
yyStackEntry *i;
+4 -14
View File
@@ -381,14 +381,6 @@ static void reorder(int *pFrom){
reorder(&aKeywordTable[i].iNext);
}
/* Parameter to the hash function
*/
#define HASH_OP ^
#define HASH_CC '^'
#define HASH_C0 4
#define HASH_C1 3
#define HASH_C2 1
/*
** This routine does the work. The generated code is printed on standard
** output.
@@ -419,9 +411,8 @@ int main(int argc, char **argv){
assert( p->len<sizeof(p->zOrigName) );
memcpy(p->zOrigName, p->zName, p->len+1);
totalLen += p->len;
p->hash = (charMap(p->zName[0])*HASH_C0) HASH_OP
(charMap(p->zName[p->len-1])*HASH_C1) HASH_OP
(p->len*HASH_C2);
p->hash = (charMap(p->zName[0])*4) ^
(charMap(p->zName[p->len-1])*3) ^ (p->len*1);
p->id = i+1;
}
@@ -657,9 +648,8 @@ int main(int argc, char **argv){
printf(" int i, j;\n");
printf(" const char *zKW;\n");
printf(" if( n>=2 ){\n");
printf(" i = ((charMap(z[0])*%d) %c", HASH_C0, HASH_CC);
printf(" (charMap(z[n-1])*%d) %c", HASH_C1, HASH_CC);
printf(" n*%d) %% %d;\n", HASH_C2, bestSize);
printf(" i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n",
bestSize);
printf(" for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){\n");
printf(" if( aKWLen[i]!=n ) continue;\n");
printf(" zKW = &zKWText[aKWOffset[i]];\n");