Compare commits

..

2 Commits

Author SHA1 Message Date
dan e8814cc83c Fix problems in the previous commit.
FossilOrigin-Name: 74ad80eb745c708bdbbbf24cbbbf50971e84182f
2017-01-21 16:21:24 +00:00
dan 0fbee29700 Add extra (somewhat inefficient) trace callbacks for triggers if SQLITE_TRACE_TRIGGER is defined.
FossilOrigin-Name: ffda1d1e1c858abd02f0c07b906cfac5ad075498
2017-01-21 15:58:42 +00:00
95 changed files with 986 additions and 4419 deletions
+2 -12
View File
@@ -1177,18 +1177,8 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4
dbselftest$(TEXE): $(TOP)/test/dbselftest.c sqlite3.c
$(LTLINK) $(DBSELFTEST_OPT) -o $@ $(TOP)/test/dbselftest.c sqlite3.c $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
+13 -42
View File
@@ -24,13 +24,6 @@ USE_AMALGAMATION = 1
USE_FULLWARN = 0
!ENDIF
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
# compiling.
#
!IFNDEF USE_FATAL_WARN
USE_FATAL_WARN = 0
!ENDIF
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
# has no effect if (any) optimizations are enabled.
#
@@ -500,12 +493,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF
# Check if warnings should be treated as errors when compiling.
#
!IF $(USE_FATAL_WARN)!=0
TCC = $(TCC) -WX
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
@@ -745,7 +732,6 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_DEBUG=1
!ENDIF
@@ -1513,10 +1499,6 @@ FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
DBSELFTEST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0
# Standard options to testfixture.
#
@@ -1559,7 +1541,7 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset)?_[^@]*)(?:@\d+)?$$" \1 \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \
| sort >> sqlite3.def
# <</block2>>
@@ -1586,9 +1568,6 @@ sourcetest: srcck1.exe sqlite3.c
fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
@@ -2185,54 +2164,46 @@ testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(ST_COMPILE_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
kvtest.exe: $(TOP)\test\kvtest.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
$(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
dbselftest.exe: $(TOP)\test\dbselftest.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(DBSELFTEST_COMPILE_OPTS) $(TOP)\test\dbselftest.c $(SQLITE3C)
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
moreclean: clean
+1 -1
View File
@@ -1 +1 @@
3.18.0
3.17.0
+1 -14
View File
@@ -24,13 +24,6 @@ TOP = .
USE_FULLWARN = 0
!ENDIF
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
# compiling.
#
!IFNDEF USE_FATAL_WARN
USE_FATAL_WARN = 0
!ENDIF
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
# has no effect if (any) optimizations are enabled.
#
@@ -461,12 +454,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF
# Check if warnings should be treated as errors when compiling.
#
!IF $(USE_FATAL_WARN)!=0
TCC = $(TCC) -WX
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
@@ -950,7 +937,7 @@ Replace.exe:
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
Vendored
+9 -9
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.18.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.17.0.
#
#
# 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.18.0'
PACKAGE_STRING='sqlite 3.18.0'
PACKAGE_VERSION='3.17.0'
PACKAGE_STRING='sqlite 3.17.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1463,7 +1463,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.18.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.17.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.18.0:";;
short | recursive ) echo "Configuration of sqlite 3.17.0:";;
esac
cat <<\_ACEOF
@@ -1652,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.18.0
sqlite configure 3.17.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2071,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.18.0, which was
It was created by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12151,7 +12151,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.18.0, which was
This file was extended by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12217,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.18.0
sqlite config.status 3.17.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+18 -40
View File
@@ -492,7 +492,6 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
assert( p->pSegments==0 );
/* Free any prepared statements held */
sqlite3_finalize(p->pSeekStmt);
for(i=0; i<SizeofArray(p->aStmt); i++){
sqlite3_finalize(p->aStmt[i]);
}
@@ -1364,9 +1363,9 @@ static int fts3InitVtab(
p->pTokenizer = pTokenizer;
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
p->bHasDocsize = (isFts4 && bNoDocsize==0);
p->bHasStat = (u8)isFts4;
p->bFts4 = (u8)isFts4;
p->bDescIdx = (u8)bDescIdx;
p->bHasStat = isFts4;
p->bFts4 = isFts4;
p->bDescIdx = bDescIdx;
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->zContentTbl = zContent;
p->zLanguageid = zLanguageid;
@@ -1681,26 +1680,6 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
return SQLITE_OK;
}
/*
** Finalize the statement handle at pCsr->pStmt.
**
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
** pointer there instead of finalizing it.
*/
static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
if( pCsr->bSeekStmt ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
if( p->pSeekStmt==0 ){
p->pSeekStmt = pCsr->pStmt;
sqlite3_reset(pCsr->pStmt);
pCsr->pStmt = 0;
}
pCsr->bSeekStmt = 0;
}
sqlite3_finalize(pCsr->pStmt);
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
@@ -1708,7 +1687,7 @@ static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
fts3CursorFinalizeStmt(pCsr);
sqlite3_finalize(pCsr->pStmt);
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
@@ -1726,23 +1705,20 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
**
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
** it. If an error occurs, return an SQLite error code.
**
** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
*/
static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
int rc = SQLITE_OK;
if( pCsr->pStmt==0 ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
char *zSql;
if( p->pSeekStmt ){
pCsr->pStmt = p->pSeekStmt;
p->pSeekStmt = 0;
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
*ppStmt = pCsr->pStmt;
return rc;
}
@@ -1754,7 +1730,9 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
sqlite3_stmt *pStmt = 0;
rc = fts3CursorSeekStmt(pCsr, &pStmt);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
@@ -3212,7 +3190,7 @@ static int fts3FilterMethod(
assert( iIdx==nVal );
/* In case the cursor has been used before, clear it now. */
fts3CursorFinalizeStmt(pCsr);
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
@@ -3280,7 +3258,7 @@ static int fts3FilterMethod(
rc = SQLITE_NOMEM;
}
}else if( eSearch==FTS3_DOCID_SEARCH ){
rc = fts3CursorSeekStmt(pCsr);
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
}
@@ -3444,7 +3422,7 @@ static int fts3SetHasStat(Fts3Table *p){
if( rc==SQLITE_OK ){
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
rc = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat;
if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
}
sqlite3_free(zSql);
}else{
-2
View File
@@ -230,7 +230,6 @@ struct Fts3Table {
** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[40];
sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */
char *zReadExprlist;
char *zWriteExprlist;
@@ -300,7 +299,6 @@ struct Fts3Cursor {
i16 eSearch; /* Search strategy (see below) */
u8 isEof; /* True if at End Of Results */
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
u8 bSeekStmt; /* True if pStmt is a seek */
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
Fts3Expr *pExpr; /* Parsed MATCH query string */
int iLangid; /* Language being queried for */
+1 -3
View File
@@ -30,9 +30,7 @@ typedef short i16;
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
#ifndef ArraySize
# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif
#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#define testcase(x)
#define ALWAYS(x) 1
+1 -1
View File
@@ -1601,7 +1601,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
int n;
sqlite3Fts5Dequote(z);
n = (int)strlen(z);
+1 -1
View File
@@ -152,7 +152,7 @@ foreach {tn expr res} {
1 {abc} {"abc"}
2 {one} {"one"|"i"|"1"}
3 {3} {"3"|"iii"|"three"}
4 {3*} {"3" *}
4 {3*} {"3"|"iii"|"three" *}
} {
do_execsql_test 4.1.$tn {
SELECT fts5_expr($expr, 'tokenize=tclnum')
-39
View File
@@ -262,44 +262,5 @@ do_execsql_test 8.3 {
brown dog fox jump lazi over quick the
}
#-------------------------------------------------------------------------
# Check that the FTS5_TOKENIZE_PREFIX flag is passed to the tokenizer
# implementation.
#
reset_db
proc tcl_create {args} { return "tcl_tokenize" }
sqlite3_fts5_create_tokenizer db tcl tcl_create
set ::flags [list]
proc tcl_tokenize {tflags text} {
lappend ::flags $tflags
foreach {w iStart iEnd} [fts5_tokenize_split $text] {
sqlite3_fts5_token $w $iStart $iEnd
}
}
do_execsql_test 9.1.1 {
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=tcl);
INSERT INTO t1 VALUES('abc');
INSERT INTO t1 VALUES('xyz');
} {}
do_test 9.1.2 { set ::flags } {document document}
set ::flags [list]
do_execsql_test 9.2.1 { SELECT * FROM t1('abc'); } {abc}
do_test 9.2.2 { set ::flags } {query}
set ::flags [list]
do_execsql_test 9.3.1 { SELECT * FROM t1('ab*'); } {abc}
do_test 9.3.2 { set ::flags } {prefixquery}
set ::flags [list]
do_execsql_test 9.4.1 { SELECT * FROM t1('"abc xyz" *'); } {}
do_test 9.4.2 { set ::flags } {prefixquery}
set ::flags [list]
do_execsql_test 9.5.1 { SELECT * FROM t1('"abc xyz*"'); } {}
do_test 9.5.2 { set ::flags } {query}
finish_test
+23 -21
View File
@@ -493,36 +493,38 @@ static void icuLoadCollation(
** Register the ICU extension functions with database db.
*/
int sqlite3IcuInit(sqlite3 *db){
static const struct IcuScalar {
struct IcuScalar {
const char *zName; /* Function name */
unsigned char nArg; /* Number of arguments */
unsigned short enc; /* Optimal text encoding */
unsigned char iContext; /* sqlite3_user_data() context */
int nArg; /* Number of arguments */
int enc; /* Optimal text encoding */
void *pContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
{"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
};
int rc = SQLITE_OK;
int i;
for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
const struct IcuScalar *p = &scalars[i];
struct IcuScalar *p = &scalars[i];
rc = sqlite3_create_function(
db, p->zName, p->nArg, p->enc,
p->iContext ? (void*)db : (void*)0,
p->xFunc, 0, 0
db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
);
}
+1 -1
View File
@@ -22,7 +22,7 @@
** how JSONB might improve on that.)
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
#if !defined(SQLITEINT_H)
#if !defined(_SQLITEINT_H_)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
-407
View File
@@ -1,407 +0,0 @@
/*
** 2017-01-27
**
** 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 SQLite extension implements a functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha1(X)
** sha1_query(Y)
**
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
** X is NULL.
**
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
/******************************************************************************
** The Hash Engine
*/
/* Context for the SHA1 hash */
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
unsigned int state[5];
unsigned int count[2];
unsigned char buffer[64];
};
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
* GCC by itself only generates left rotates. Use right rotates if
* possible to be kinder to dinky implementations with iterative rotate
* instructions.
*/
#define SHA_ROT(op, x, k) \
({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)
#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
|(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
^block[(i+2)&15]^block[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
* determined at run-time.
*/
#define Rl0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
unsigned int qq[5]; /* a, b, c, d, e; */
static int one = 1;
unsigned int block[16];
memcpy(block, buffer, 64);
memcpy(qq,state,5*sizeof(unsigned int));
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
/* Copy p->state[] to working vars */
/*
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
*/
/* 4 rounds of 20 operations each. Loop unrolled. */
if( 1 == *(unsigned char*)&one ){
Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
}else{
Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
}
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
#undef a
#undef b
#undef c
#undef d
#undef e
}
/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
/* SHA1 initialization constants */
p->state[0] = 0x67452301;
p->state[1] = 0xEFCDAB89;
p->state[2] = 0x98BADCFE;
p->state[3] = 0x10325476;
p->state[4] = 0xC3D2E1F0;
p->count[0] = p->count[1] = 0;
}
/* Add new content to the SHA1 hash */
static void hash_step(
SHA1Context *p, /* Add content to this context */
const unsigned char *data, /* Data to be added */
unsigned int len /* Number of bytes in data */
){
unsigned int i, j;
j = p->count[0];
if( (p->count[0] += len << 3) < j ){
p->count[1] += (len>>29)+1;
}
j = (j >> 3) & 63;
if( (j + len) > 63 ){
(void)memcpy(&p->buffer[j], data, (i = 64-j));
SHA1Transform(p->state, p->buffer);
for(; i + 63 < len; i += 64){
SHA1Transform(p->state, &data[i]);
}
j = 0;
}else{
i = 0;
}
(void)memcpy(&p->buffer[j], &data[i], len - i);
}
/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
SHA1Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
hash_step(p, (unsigned char*)zBuf, n);
}
/* Add padding and compute the message digest. Render the
** message digest as lower-case hexadecimal and put it into
** zOut[]. zOut[] must be at least 41 bytes long. */
static void hash_finish(
SHA1Context *p, /* The SHA1 context to finish and render */
char *zOut /* Store hexadecimal hash here */
){
unsigned int i;
unsigned char finalcount[8];
unsigned char digest[20];
static const char zEncode[] = "0123456789abcdef";
for (i = 0; i < 8; i++){
finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
hash_step(p, (const unsigned char *)"\200", 1);
while ((p->count[0] & 504) != 448){
hash_step(p, (const unsigned char *)"\0", 1);
}
hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++){
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
for(i=0; i<20; i++){
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
zOut[i*2+1] = zEncode[digest[i] & 0xf];
}
zOut[i*2]= 0;
}
/* End of the hashing logic
*****************************************************************************/
/*
** Implementation of the sha1(X) function.
**
** Return a lower-case hexadecimal rendering of the SHA1 hash of the
** argument X. If X is a BLOB, it is hashed as is. For all other
** types of input, X is converted into a UTF-8 string and the string
** is hash without the trailing 0x00 terminator. The hash of a NULL
** value is NULL.
*/
static void sha1Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA1Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
char zOut[44];
assert( argc==1 );
if( eType==SQLITE_NULL ) return;
hash_init(&cx);
if( eType==SQLITE_BLOB ){
hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
}else{
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs. Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/
static void sha1QueryFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
sqlite3_stmt *pStmt = 0;
int nCol; /* Number of columns in the result set */
int i; /* Loop counter */
int rc;
int n;
const char *z;
SHA1Context cx;
char zOut[44];
assert( argc==1 );
if( zSql==0 ) return;
hash_init(&cx);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
zSql, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
if( !sqlite3_stmt_readonly(pStmt) ){
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
nCol = sqlite3_column_count(pStmt);
z = sqlite3_sql(pStmt);
n = (int)strlen(z);
hash_step_vformat(&cx,"S%d:",n);
hash_step(&cx,(unsigned char*)z,n);
/* Compute a hash over the result of the query */
while( SQLITE_ROW==sqlite3_step(pStmt) ){
hash_step(&cx,(const unsigned char*)"R",1);
for(i=0; i<nCol; i++){
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_NULL: {
hash_step(&cx, (const unsigned char*)"N",1);
break;
}
case SQLITE_INTEGER: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
memcpy(&u, &v, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'I';
hash_step(&cx, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
double r = sqlite3_column_double(pStmt,i);
memcpy(&u, &r, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'F';
hash_step(&cx,x,9);
break;
}
case SQLITE_TEXT: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_text(pStmt, i);
hash_step_vformat(&cx,"T%d:",n2);
hash_step(&cx, z2, n2);
break;
}
case SQLITE_BLOB: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
hash_step_vformat(&cx,"B%d:",n2);
hash_step(&cx, z2, n2);
break;
}
}
}
}
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_sha_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
sha1Func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
sha1QueryFunc, 0, 0);
}
return rc;
}
+106 -311
View File
@@ -68,7 +68,6 @@
#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
@@ -117,16 +116,13 @@ struct Rtree {
sqlite3 *db; /* Host database connection */
int iNodeSize; /* Size in bytes of each node in the node table */
u8 nDim; /* Number of dimensions */
u8 nDim2; /* Twice the number of dimensions */
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
u32 nBusy; /* Current number of users of this structure */
int nBusy; /* Current number of users of this structure */
i64 nRowEst; /* Estimated number of rows in this table */
u32 nCursor; /* Number of open cursors */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
@@ -136,10 +132,8 @@ struct Rtree {
RtreeNode *pDeleted;
int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */
/* Blob I/O on xxx_node */
sqlite3_blob *pNodeBlob;
/* Statements to read/write/delete a record from xxx_node */
sqlite3_stmt *pReadNode;
sqlite3_stmt *pWriteNode;
sqlite3_stmt *pDeleteNode;
@@ -368,58 +362,6 @@ struct RtreeMatchArg {
# define MIN(x,y) ((x) > (y) ? (y) : (x))
#endif
/* What version of GCC is being used. 0 means GCC is not being used .
** Note that the GCC_VERSION macro will also be set correctly when using
** clang, since clang works hard to be gcc compatible. So the gcc
** optimizations will also work when compiling with clang.
*/
#ifndef GCC_VERSION
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif
#endif
/* The testcase() macro should already be defined in the amalgamation. If
** it is not, make it a no-op.
*/
#ifndef SQLITE_AMALGAMATION
# define testcase(X)
#endif
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
** at run-time.
*/
#ifndef SQLITE_BYTEORDER
#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)
# define SQLITE_BYTEORDER 1234
#elif defined(sparc) || defined(__ppc__)
# define SQLITE_BYTEORDER 4321
#else
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
#endif
#endif
/* What version of MSVC is being used. 0 means MSVC is not being used */
#ifndef MSVC_VERSION
#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
# define MSVC_VERSION _MSC_VER
#else
# define MSVC_VERSION 0
#endif
#endif
/*
** Functions to deserialize a 16 bit integer, 32 bit real number and
** 64 bit integer. The deserialized value is returned.
@@ -428,36 +370,14 @@ static int readInt16(u8 *p){
return (p[0]<<8) + p[1];
}
static void readCoord(u8 *p, RtreeCoord *pCoord){
assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
pCoord->u = _byteswap_ulong(*(u32*)p);
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
pCoord->u = __builtin_bswap32(*(u32*)p);
#elif SQLITE_BYTEORDER==4321
pCoord->u = *(u32*)p;
#else
pCoord->u = (
(((u32)p[0]) << 24) +
(((u32)p[1]) << 16) +
(((u32)p[2]) << 8) +
(((u32)p[3]) << 0)
);
#endif
}
static i64 readInt64(u8 *p){
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u64 x;
memcpy(&x, p, 8);
return (i64)_byteswap_uint64(x);
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u64 x;
memcpy(&x, p, 8);
return (i64)__builtin_bswap64(x);
#elif SQLITE_BYTEORDER==4321
i64 x;
memcpy(&x, p, 8);
return x;
#else
return (
(((i64)p[0]) << 56) +
(((i64)p[1]) << 48) +
@@ -468,7 +388,6 @@ static i64 readInt64(u8 *p){
(((i64)p[6]) << 8) +
(((i64)p[7]) << 0)
);
#endif
}
/*
@@ -476,43 +395,23 @@ static i64 readInt64(u8 *p){
** 64 bit integer. The value returned is the number of bytes written
** to the argument buffer (always 2, 4 and 8 respectively).
*/
static void writeInt16(u8 *p, int i){
static int writeInt16(u8 *p, int i){
p[0] = (i>> 8)&0xFF;
p[1] = (i>> 0)&0xFF;
return 2;
}
static int writeCoord(u8 *p, RtreeCoord *pCoord){
u32 i;
assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
assert( sizeof(RtreeCoord)==4 );
assert( sizeof(u32)==4 );
#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
i = __builtin_bswap32(pCoord->u);
memcpy(p, &i, 4);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
i = _byteswap_ulong(pCoord->u);
memcpy(p, &i, 4);
#elif SQLITE_BYTEORDER==4321
i = pCoord->u;
memcpy(p, &i, 4);
#else
i = pCoord->u;
p[0] = (i>>24)&0xFF;
p[1] = (i>>16)&0xFF;
p[2] = (i>> 8)&0xFF;
p[3] = (i>> 0)&0xFF;
#endif
return 4;
}
static int writeInt64(u8 *p, i64 i){
#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
i = (i64)__builtin_bswap64((u64)i);
memcpy(p, &i, 8);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
i = (i64)_byteswap_uint64((u64)i);
memcpy(p, &i, 8);
#elif SQLITE_BYTEORDER==4321
memcpy(p, &i, 8);
#else
p[0] = (i>>56)&0xFF;
p[1] = (i>>48)&0xFF;
p[2] = (i>>40)&0xFF;
@@ -521,7 +420,6 @@ static int writeInt64(u8 *p, i64 i){
p[5] = (i>>16)&0xFF;
p[6] = (i>> 8)&0xFF;
p[7] = (i>> 0)&0xFF;
#endif
return 8;
}
@@ -604,17 +502,6 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
return pNode;
}
/*
** Clear the Rtree.pNodeBlob object
*/
static void nodeBlobReset(Rtree *pRtree){
if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
sqlite3_blob *pBlob = pRtree->pNodeBlob;
pRtree->pNodeBlob = 0;
sqlite3_blob_close(pBlob);
}
}
/*
** Obtain a reference to an r-tree node.
*/
@@ -624,8 +511,9 @@ static int nodeAcquire(
RtreeNode *pParent, /* Either the parent node or NULL */
RtreeNode **ppNode /* OUT: Acquired node */
){
int rc = SQLITE_OK;
RtreeNode *pNode = 0;
int rc;
int rc2 = SQLITE_OK;
RtreeNode *pNode;
/* Check if the requested node is already in the hash table. If so,
** increase its reference count and return it.
@@ -641,45 +529,28 @@ static int nodeAcquire(
return SQLITE_OK;
}
if( pRtree->pNodeBlob ){
sqlite3_blob *pBlob = pRtree->pNodeBlob;
pRtree->pNodeBlob = 0;
rc = sqlite3_blob_reopen(pBlob, iNode);
pRtree->pNodeBlob = pBlob;
if( rc ){
nodeBlobReset(pRtree);
if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
}
}
if( pRtree->pNodeBlob==0 ){
char *zTab = sqlite3_mprintf("%s_node", pRtree->zName);
if( zTab==0 ) return SQLITE_NOMEM;
rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0,
&pRtree->pNodeBlob);
sqlite3_free(zTab);
}
if( rc ){
nodeBlobReset(pRtree);
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
rc = SQLITE_NOMEM;
}else{
pNode->pParent = pParent;
pNode->zData = (u8 *)&pNode[1];
pNode->nRef = 1;
pNode->iNode = iNode;
pNode->isDirty = 0;
pNode->pNext = 0;
rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
pRtree->iNodeSize, 0);
nodeReference(pParent);
sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
rc = sqlite3_step(pRtree->pReadNode);
if( rc==SQLITE_ROW ){
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){
pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
rc2 = SQLITE_NOMEM;
}else{
pNode->pParent = pParent;
pNode->zData = (u8 *)&pNode[1];
pNode->nRef = 1;
pNode->iNode = iNode;
pNode->isDirty = 0;
pNode->pNext = 0;
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
nodeReference(pParent);
}
}
}
rc = sqlite3_reset(pRtree->pReadNode);
if( rc==SQLITE_OK ) rc = rc2;
/* If the root node was just loaded, set pRtree->iDepth to the height
** of the r-tree structure. A height of zero means all data is stored on
@@ -731,7 +602,7 @@ static void nodeOverwriteCell(
int ii;
u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
p += writeInt64(p, pCell->iRowid);
for(ii=0; ii<pRtree->nDim2; ii++){
for(ii=0; ii<(pRtree->nDim*2); ii++){
p += writeCoord(p, &pCell->aCoord[ii]);
}
pNode->isDirty = 1;
@@ -865,16 +736,13 @@ static void nodeGetCell(
){
u8 *pData;
RtreeCoord *pCoord;
int ii = 0;
int ii;
pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
pCoord = pCell->aCoord;
do{
readCoord(pData, &pCoord[ii]);
readCoord(pData+4, &pCoord[ii+1]);
pData += 8;
ii += 2;
}while( ii<pRtree->nDim2 );
for(ii=0; ii<pRtree->nDim*2; ii++){
readCoord(&pData[ii*4], &pCoord[ii]);
}
}
@@ -925,9 +793,7 @@ static void rtreeReference(Rtree *pRtree){
static void rtreeRelease(Rtree *pRtree){
pRtree->nBusy--;
if( pRtree->nBusy==0 ){
pRtree->inWrTrans = 0;
pRtree->nCursor = 0;
nodeBlobReset(pRtree);
sqlite3_finalize(pRtree->pReadNode);
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -965,7 +831,6 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
if( !zCreate ){
rc = SQLITE_NOMEM;
}else{
nodeBlobReset(pRtree);
rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
}
@@ -981,7 +846,6 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
@@ -989,7 +853,6 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
rc = SQLITE_OK;
pRtree->nCursor++;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
@@ -1022,13 +885,10 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
Rtree *pRtree = (Rtree *)(cur->pVtab);
int ii;
RtreeCursor *pCsr = (RtreeCursor *)cur;
assert( pRtree->nCursor>0 );
freeCursorConstraints(pCsr);
sqlite3_free(pCsr->aPoint);
for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
sqlite3_free(pCsr);
pRtree->nCursor--;
nodeBlobReset(pRtree);
return SQLITE_OK;
}
@@ -1051,22 +911,15 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
** false. a[] is the four bytes of the on-disk record to be decoded.
** Store the results in "r".
**
** There are five versions of this macro. The last one is generic. The
** other four are various architectures-specific optimizations.
** There are three versions of this macro, one each for little-endian and
** big-endian processors and a third generic implementation. The endian-
** specific implementations are much faster and are preferred if the
** processor endianness is known at compile-time. The SQLITE_BYTEORDER
** macro is part of sqliteInt.h and hence the endian-specific
** implementation will only be used if this module is compiled as part
** of the amalgamation.
*/
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = _byteswap_ulong(*(u32*)a); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = __builtin_bswap32(*(u32*)a); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==1234
#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
@@ -1074,7 +927,7 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
((c.u&0xff)<<24)|((c.u&0xff00)<<8); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==4321
#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
@@ -1101,10 +954,10 @@ static int rtreeCallbackConstraint(
sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */
int *peWithin /* OUT: visibility of the cell */
){
int i; /* Loop counter */
sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */
int nCoord = pInfo->nCoord; /* No. of coordinates */
int rc; /* Callback return code */
RtreeCoord c; /* Translator union */
sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */
assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
@@ -1114,41 +967,13 @@ static int rtreeCallbackConstraint(
pInfo->iRowid = readInt64(pCellData);
}
pCellData += 8;
#ifndef SQLITE_RTREE_INT_ONLY
if( eInt==0 ){
switch( nCoord ){
case 10: readCoord(pCellData+36, &c); aCoord[9] = c.f;
readCoord(pCellData+32, &c); aCoord[8] = c.f;
case 8: readCoord(pCellData+28, &c); aCoord[7] = c.f;
readCoord(pCellData+24, &c); aCoord[6] = c.f;
case 6: readCoord(pCellData+20, &c); aCoord[5] = c.f;
readCoord(pCellData+16, &c); aCoord[4] = c.f;
case 4: readCoord(pCellData+12, &c); aCoord[3] = c.f;
readCoord(pCellData+8, &c); aCoord[2] = c.f;
default: readCoord(pCellData+4, &c); aCoord[1] = c.f;
readCoord(pCellData, &c); aCoord[0] = c.f;
}
}else
#endif
{
switch( nCoord ){
case 10: readCoord(pCellData+36, &c); aCoord[9] = c.i;
readCoord(pCellData+32, &c); aCoord[8] = c.i;
case 8: readCoord(pCellData+28, &c); aCoord[7] = c.i;
readCoord(pCellData+24, &c); aCoord[6] = c.i;
case 6: readCoord(pCellData+20, &c); aCoord[5] = c.i;
readCoord(pCellData+16, &c); aCoord[4] = c.i;
case 4: readCoord(pCellData+12, &c); aCoord[3] = c.i;
readCoord(pCellData+8, &c); aCoord[2] = c.i;
default: readCoord(pCellData+4, &c); aCoord[1] = c.i;
readCoord(pCellData, &c); aCoord[0] = c.i;
}
for(i=0; i<nCoord; i++, pCellData += 4){
RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]);
}
if( pConstraint->op==RTREE_MATCH ){
int eWithin = 0;
rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo,
nCoord, aCoord, &eWithin);
if( eWithin==0 ) *peWithin = NOT_WITHIN;
nCoord, aCoord, &i);
if( i==0 ) *peWithin = NOT_WITHIN;
*prScore = RTREE_ZERO;
}else{
pInfo->aCoord = aCoord;
@@ -1184,7 +1009,6 @@ static void rtreeNonleafConstraint(
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ );
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
switch( p->op ){
case RTREE_LE:
case RTREE_LT:
@@ -1225,7 +1049,6 @@ static void rtreeLeafConstraint(
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ );
pCellData += 8 + p->iCoord*4;
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
RTREE_DECODE_COORD(eInt, pCellData, xN);
switch( p->op ){
case RTREE_LE: if( xN <= p->u.rValue ) return; break;
@@ -1294,7 +1117,7 @@ static int rtreeSearchPointCompare(
}
/*
** Interchange two search points in a cursor.
** Interchange to search points in a cursor.
*/
static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){
RtreeSearchPoint t = p->aPoint[i];
@@ -1542,7 +1365,7 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO;
p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
if( p==0 ) return SQLITE_NOMEM;
p->eWithin = (u8)eWithin;
p->eWithin = eWithin;
p->id = x.id;
p->iCell = x.iCell;
RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
@@ -1601,6 +1424,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else{
if( rc ) return rc;
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
@@ -1729,7 +1553,7 @@ static int rtreeFilter(
p->id = iNode;
p->eWithin = PARTLY_WITHIN;
rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
p->iCell = (u8)iCell;
p->iCell = iCell;
RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
}else{
pCsr->atEOF = 1;
@@ -1762,7 +1586,7 @@ static int rtreeFilter(
if( rc!=SQLITE_OK ){
break;
}
p->pInfo->nCoord = pRtree->nDim2;
p->pInfo->nCoord = pRtree->nDim*2;
p->pInfo->anQueue = pCsr->anQueue;
p->pInfo->mxLevel = pRtree->iDepth + 1;
}else{
@@ -1777,7 +1601,7 @@ static int rtreeFilter(
}
if( rc==SQLITE_OK ){
RtreeSearchPoint *pNew;
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1);
if( pNew==0 ) return SQLITE_NOMEM;
pNew->id = 1;
pNew->iCell = 0;
@@ -1795,6 +1619,19 @@ static int rtreeFilter(
return rc;
}
/*
** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
** extension is currently being used by a version of SQLite too old to
** support estimatedRows. In that case this function is a no-op.
*/
static void setEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
#if SQLITE_VERSION_NUMBER>=3008002
if( sqlite3_libversion_number()>=3008002 ){
pIdxInfo->estimatedRows = nRow;
}
#endif
}
/*
** Rtree virtual table module xBestIndex method. There are three
** table scan strategies to choose from (in order from most to
@@ -1874,7 +1711,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
** a single row.
*/
pIdxInfo->estimatedCost = 30.0;
pIdxInfo->estimatedRows = 1;
setEstimatedRows(pIdxInfo, 1);
return SQLITE_OK;
}
@@ -1892,7 +1729,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
break;
}
zIdxStr[iIdx++] = op;
zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
zIdxStr[iIdx++] = p->iColumn - 1 + '0';
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
pIdxInfo->aConstraintUsage[ii].omit = 1;
}
@@ -1906,7 +1743,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
nRow = pRtree->nRowEst >> (iIdx/2);
pIdxInfo->estimatedCost = (double)6.0 * (double)nRow;
pIdxInfo->estimatedRows = nRow;
setEstimatedRows(pIdxInfo, nRow);
return rc;
}
@@ -1916,26 +1753,9 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
*/
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
RtreeDValue area = (RtreeDValue)1;
assert( pRtree->nDim>=1 && pRtree->nDim<=5 );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
switch( pRtree->nDim ){
case 5: area = p->aCoord[9].f - p->aCoord[8].f;
case 4: area *= p->aCoord[7].f - p->aCoord[6].f;
case 3: area *= p->aCoord[5].f - p->aCoord[4].f;
case 2: area *= p->aCoord[3].f - p->aCoord[2].f;
default: area *= p->aCoord[1].f - p->aCoord[0].f;
}
}else
#endif
{
switch( pRtree->nDim ){
case 5: area = p->aCoord[9].i - p->aCoord[8].i;
case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
default: area *= p->aCoord[1].i - p->aCoord[0].i;
}
int ii;
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
}
return area;
}
@@ -1945,12 +1765,11 @@ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
** of the objects size in each dimension.
*/
static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
RtreeDValue margin = 0;
int ii = pRtree->nDim2 - 2;
do{
RtreeDValue margin = (RtreeDValue)0;
int ii;
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
ii -= 2;
}while( ii>=0 );
}
return margin;
}
@@ -1958,19 +1777,17 @@ static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
** Store the union of cells p1 and p2 in p1.
*/
static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
int ii = 0;
int ii;
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
do{
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
ii += 2;
}while( ii<pRtree->nDim2 );
}
}else{
do{
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
ii += 2;
}while( ii<pRtree->nDim2 );
}
}
}
@@ -1981,7 +1798,7 @@ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
int ii;
int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
for(ii=0; ii<pRtree->nDim2; ii+=2){
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
RtreeCoord *a1 = &p1->aCoord[ii];
RtreeCoord *a2 = &p2->aCoord[ii];
if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
@@ -2016,7 +1833,7 @@ static RtreeDValue cellOverlap(
for(ii=0; ii<nCell; ii++){
int jj;
RtreeDValue o = (RtreeDValue)1;
for(jj=0; jj<pRtree->nDim2; jj+=2){
for(jj=0; jj<(pRtree->nDim*2); jj+=2){
RtreeDValue x1, x2;
x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
@@ -3072,7 +2889,7 @@ static int rtreeUpdate(
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
assert( nData<=(pRtree->nDim2 + 3) );
assert( nData<=(pRtree->nDim*2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
@@ -3162,27 +2979,6 @@ constraint:
return rc;
}
/*
** Called when a transaction starts.
*/
static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
assert( pRtree->inWrTrans==0 );
pRtree->inWrTrans++;
return SQLITE_OK;
}
/*
** Called when a transaction completes (either by COMMIT or ROLLBACK).
** The sqlite3_blob object should be released at this point.
*/
static int rtreeEndTransaction(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
pRtree->inWrTrans = 0;
nodeBlobReset(pRtree);
return SQLITE_OK;
}
/*
** The xRename method for rtree module virtual tables.
*/
@@ -3204,7 +3000,6 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
return rc;
}
/*
** This function populates the pRtree->nRowEst variable with an estimate
** of the number of rows in the virtual table. If possible, this is based
@@ -3264,15 +3059,15 @@ static sqlite3_module rtreeModule = {
rtreeColumn, /* xColumn - read data */
rtreeRowid, /* xRowid - read data */
rtreeUpdate, /* xUpdate - write data */
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeEndTransaction, /* xRollback - rollback transaction */
0, /* xBegin - begin transaction */
0, /* xSync - sync transaction */
0, /* xCommit - commit transaction */
0, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0 /* xRollbackTo */
};
static int rtreeSqlInit(
@@ -3284,9 +3079,10 @@ static int rtreeSqlInit(
){
int rc = SQLITE_OK;
#define N_STATEMENT 8
#define N_STATEMENT 9
static const char *azSql[N_STATEMENT] = {
/* Write the xxx_node table */
/* Read and write the xxx_node table */
"SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
@@ -3324,14 +3120,15 @@ static int rtreeSqlInit(
}
}
appStmt[0] = &pRtree->pWriteNode;
appStmt[1] = &pRtree->pDeleteNode;
appStmt[2] = &pRtree->pReadRowid;
appStmt[3] = &pRtree->pWriteRowid;
appStmt[4] = &pRtree->pDeleteRowid;
appStmt[5] = &pRtree->pReadParent;
appStmt[6] = &pRtree->pWriteParent;
appStmt[7] = &pRtree->pDeleteParent;
appStmt[0] = &pRtree->pReadNode;
appStmt[1] = &pRtree->pWriteNode;
appStmt[2] = &pRtree->pDeleteNode;
appStmt[3] = &pRtree->pReadRowid;
appStmt[4] = &pRtree->pWriteRowid;
appStmt[5] = &pRtree->pDeleteRowid;
appStmt[6] = &pRtree->pReadParent;
appStmt[7] = &pRtree->pWriteParent;
appStmt[8] = &pRtree->pDeleteParent;
rc = rtreeQueryStat1(db, pRtree);
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
@@ -3469,10 +3266,9 @@ static int rtreeInit(
pRtree->base.pModule = &rtreeModule;
pRtree->zDb = (char *)&pRtree[1];
pRtree->zName = &pRtree->zDb[nDb+1];
pRtree->nDim = (u8)((argc-4)/2);
pRtree->nDim2 = pRtree->nDim*2;
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
pRtree->eCoordType = (u8)eCoordType;
pRtree->nDim = (argc-4)/2;
pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
pRtree->eCoordType = eCoordType;
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
@@ -3545,8 +3341,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
memset(&node, 0, sizeof(RtreeNode));
memset(&tree, 0, sizeof(Rtree));
tree.nDim = (u8)sqlite3_value_int(apArg[0]);
tree.nDim2 = tree.nDim*2;
tree.nDim = sqlite3_value_int(apArg[0]);
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
@@ -3559,7 +3354,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
nodeGetCell(&tree, &node, ii, &cell);
sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
nCell = (int)strlen(zCell);
for(jj=0; jj<tree.nDim2; jj++){
for(jj=0; jj<tree.nDim*2; jj++){
#ifndef SQLITE_RTREE_INT_ONLY
sqlite3_snprintf(512-nCell,&zCell[nCell], " %g",
(double)cell.aCoord[jj].f);
+1 -1
View File
@@ -109,7 +109,7 @@ do_corruption_tests rtreeA-1.1 {
}
do_execsql_test rtreeA-1.2.0 { DROP TABLE t1_node } {}
do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
do_corruption_tests rtreeA-1.2 -error "SQL logic error or missing database" {
1 "SELECT * FROM t1"
2 "SELECT * FROM t1 WHERE rowid=5"
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
+111 -147
View File
@@ -20,61 +20,46 @@ ifcapable !session {finish_test; return}
set testprefix session1
# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
# with regular rowid tables.
#
foreach {tn trailing} {
1 ""
2 " WITHOUT ROWID "
} {
eval [string map [list %WR% $trailing] {
db close
forcedelete test.db test.db2
reset_db
do_execsql_test $tn.1.0 {
CREATE TABLE t1(x PRIMARY KEY, y) %WR%;
do_execsql_test 1.0 {
CREATE TABLE t1(x PRIMARY KEY, y);
INSERT INTO t1 VALUES('abc', 'def');
}
#-------------------------------------------------------------------------
# Test creating, attaching tables to and deleting session objects.
#
do_test $tn.1.1 { sqlite3session S db main } {S}
do_test $tn.1.2 { S delete } {}
do_test $tn.1.3 { sqlite3session S db main } {S}
do_test $tn.1.4 { S attach t1 } {}
do_test $tn.1.5 { S delete } {}
do_test $tn.1.6 { sqlite3session S db main } {S}
do_test $tn.1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
do_test $tn.1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
do_test $tn.1.9 { S delete } {}
do_test $tn.1.10 {
do_test 1.1 { sqlite3session S db main } {S}
do_test 1.2 { S delete } {}
do_test 1.3 { sqlite3session S db main } {S}
do_test 1.4 { S attach t1 } {}
do_test 1.5 { S delete } {}
do_test 1.6 { sqlite3session S db main } {S}
do_test 1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
do_test 1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
do_test 1.9 { S delete } {}
do_test 1.10 {
sqlite3session S db main
S attach t1
execsql { INSERT INTO t1 VALUES('ghi', 'jkl') }
} {}
do_test $tn.1.11 { S delete } {}
if {$tn==1} {
do_test $tn.1.12 {
sqlite3session S db main
S attach t1
execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
execsql { DELETE FROM t1 WHERE rowid = 2 }
} {}
do_test $tn.1.13 {
S changeset
S delete
} {}
}
do_test 1.11 { S delete } {}
do_test 1.12 {
sqlite3session S db main
S attach t1
execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
execsql { DELETE FROM t1 WHERE rowid = 2 }
} {}
do_test 1.13 {
S changeset
S delete
} {}
#-------------------------------------------------------------------------
# Simple changeset tests. Also test the sqlite3changeset_invert()
# function.
#
do_test $tn.2.1.1 {
do_test 2.1.1 {
execsql { DELETE FROM t1 }
sqlite3session S db main
S attach t1
@@ -82,36 +67,36 @@ do_test $tn.2.1.1 {
execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
} {}
do_changeset_test $tn.2.1.2 S {
do_changeset_test 2.1.2 S {
{INSERT t1 0 X. {} {i 1 t Sukhothai}}
{INSERT t1 0 X. {} {i 2 t Ayutthaya}}
{INSERT t1 0 X. {} {i 3 t Thonburi}}
}
do_changeset_invert_test $tn.2.1.3 S {
do_changeset_invert_test 2.1.3 S {
{DELETE t1 0 X. {i 1 t Sukhothai} {}}
{DELETE t1 0 X. {i 2 t Ayutthaya} {}}
{DELETE t1 0 X. {i 3 t Thonburi} {}}
}
do_test $tn.2.1.4 { S delete } {}
do_test 2.1.4 { S delete } {}
do_test $tn.2.2.1 {
do_test 2.2.1 {
sqlite3session S db main
S attach t1
execsql { DELETE FROM t1 WHERE 1 }
} {}
do_changeset_test $tn.2.2.2 S {
do_changeset_test 2.2.2 S {
{DELETE t1 0 X. {i 1 t Sukhothai} {}}
{DELETE t1 0 X. {i 2 t Ayutthaya} {}}
{DELETE t1 0 X. {i 3 t Thonburi} {}}
}
do_changeset_invert_test $tn.2.2.3 S {
do_changeset_invert_test 2.2.3 S {
{INSERT t1 0 X. {} {i 1 t Sukhothai}}
{INSERT t1 0 X. {} {i 2 t Ayutthaya}}
{INSERT t1 0 X. {} {i 3 t Thonburi}}
}
do_test $tn.2.2.4 { S delete } {}
do_test 2.2.4 { S delete } {}
do_test $tn.2.3.1 {
do_test 2.3.1 {
execsql { DELETE FROM t1 }
sqlite3session S db main
execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
@@ -125,7 +110,7 @@ do_test $tn.2.3.1 {
}
} {}
do_changeset_test $tn.2.3.2 S {
do_changeset_test 2.3.2 S {
{INSERT t1 0 X. {} {i 10 t Sukhothai}}
{DELETE t1 0 X. {i 1 t Sukhothai} {}}
{UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}}
@@ -133,24 +118,24 @@ do_changeset_test $tn.2.3.2 S {
{INSERT t1 0 X. {} {i 20 t Thapae}}
}
do_changeset_invert_test $tn.2.3.3 S {
do_changeset_invert_test 2.3.3 S {
{DELETE t1 0 X. {i 10 t Sukhothai} {}}
{INSERT t1 0 X. {} {i 1 t Sukhothai}}
{UPDATE t1 0 X. {i 2 t Surin} {{} {} t Ayutthaya}}
{INSERT t1 0 X. {} {i 3 t Thonburi}}
{DELETE t1 0 X. {i 20 t Thapae} {}}
}
do_test $tn.2.3.4 { S delete } {}
do_test 2.3.4 { S delete } {}
do_test $tn.2.4.1 {
do_test 2.4.1 {
sqlite3session S db main
S attach t1
execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
execsql { DELETE FROM t1 WHERE x = 100 }
} {}
do_changeset_test $tn.2.4.2 S {}
do_changeset_invert_test $tn.2.4.3 S {}
do_test $tn.2.4.4 { S delete } {}
do_changeset_test 2.4.2 S {}
do_changeset_invert_test 2.4.3 S {}
do_test 2.4.4 { S delete } {}
#-------------------------------------------------------------------------
# Test the application of simple changesets. These tests also test that
@@ -204,16 +189,16 @@ proc do_db2_test {testname sql {result {}}} {
# Test INSERT changesets.
#
do_test $tn.3.1.0 {
execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) %WR% } db2
do_test 3.1.0 {
execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) } db2
execsql {
CREATE TABLE t1(a PRIMARY KEY, b) %WR%;
CREATE TABLE t1(a PRIMARY KEY, b);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
} db
} {}
do_db2_test $tn.3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
do_conflict_test $tn.3.1.2 -tables t1 -sql {
do_db2_test 3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
do_conflict_test 3.1.2 -tables t1 -sql {
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
INSERT INTO t1 VALUES(5, 'five');
@@ -225,34 +210,34 @@ do_conflict_test $tn.3.1.2 -tables t1 -sql {
{INSERT t1 CONSTRAINT {i 8 n {}}}
}
do_db2_test $tn.3.1.3 "SELECT * FROM t1 ORDER BY a" {
3 three 4 four 5 five 6 VI 7 seven
do_db2_test 3.1.3 "SELECT * FROM t1" {
6 VI 3 three 4 four 5 five 7 seven
}
do_execsql_test $tn.3.1.4 "SELECT * FROM t1" {
do_execsql_test 3.1.4 "SELECT * FROM t1" {
1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 {}
}
# Test DELETE changesets.
#
do_execsql_test $tn.3.2.1 {
do_execsql_test 3.2.1 {
PRAGMA foreign_keys = on;
CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
CREATE TABLE t2(a PRIMARY KEY, b);
CREATE TABLE t3(c, d REFERENCES t2);
INSERT INTO t2 VALUES(1, 'one');
INSERT INTO t2 VALUES(2, 'two');
INSERT INTO t2 VALUES(3, 'three');
INSERT INTO t2 VALUES(4, 'four');
}
do_db2_test $tn.3.2.2 {
do_db2_test 3.2.2 {
PRAGMA foreign_keys = on;
CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
CREATE TABLE t2(a PRIMARY KEY, b);
CREATE TABLE t3(c, d REFERENCES t2);
INSERT INTO t2 VALUES(1, 'one');
INSERT INTO t2 VALUES(2, 'two');
INSERT INTO t2 VALUES(4, 'five');
INSERT INTO t3 VALUES('i', 1);
}
do_conflict_test $tn.3.2.3 -tables t2 -sql {
do_conflict_test 3.2.3 -tables t2 -sql {
DELETE FROM t2 WHERE a = 1;
DELETE FROM t2 WHERE a = 2;
DELETE FROM t2 WHERE a = 3;
@@ -262,26 +247,26 @@ do_conflict_test $tn.3.2.3 -tables t2 -sql {
{DELETE t2 DATA {i 4 t four} {i 4 t five}}
{FOREIGN_KEY 1}
}
do_execsql_test $tn.3.2.4 "SELECT * FROM t2" {}
do_db2_test $tn.3.2.5 "SELECT * FROM t2" {4 five}
do_execsql_test 3.2.4 "SELECT * FROM t2" {}
do_db2_test 3.2.5 "SELECT * FROM t2" {4 five}
# Test UPDATE changesets.
#
do_execsql_test $tn.3.3.1 {
CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c))%WR%;
do_execsql_test 3.3.1 {
CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c));
INSERT INTO t4 VALUES(1, 2, 3);
INSERT INTO t4 VALUES(4, 5, 6);
INSERT INTO t4 VALUES(7, 8, 9);
INSERT INTO t4 VALUES(10, 11, 12);
}
do_db2_test $tn.3.3.2 {
CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c))%WR%;
do_db2_test 3.3.2 {
CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c));
INSERT INTO t4 VALUES(0, 2, 3);
INSERT INTO t4 VALUES(4, 5, 7);
INSERT INTO t4 VALUES(7, 8, 9);
INSERT INTO t4 VALUES(10, 11, 12);
}
do_conflict_test $tn.3.3.3 -tables t4 -sql {
do_conflict_test 3.3.3 -tables t4 -sql {
UPDATE t4 SET a = -1 WHERE b = 2;
UPDATE t4 SET a = -1 WHERE b = 5;
UPDATE t4 SET a = NULL WHERE c = 9;
@@ -291,8 +276,8 @@ do_conflict_test $tn.3.3.3 -tables t4 -sql {
{UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}}
{UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}}
}
do_db2_test $tn.3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
do_execsql_test $tn.3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
do_db2_test 3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
do_execsql_test 3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
#-------------------------------------------------------------------------
# This next block of tests verifies that values returned by the conflict
@@ -312,16 +297,16 @@ proc xConflict {args} {
return $::conflict_return
}
foreach {tn2 conflict_return after} {
foreach {tn conflict_return after} {
1 OMIT {1 2 value1 4 5 7 10 x x}
2 REPLACE {1 2 value1 4 5 value2 10 8 9}
} {
test_reset
do_test $tn.4.$tn2.1 {
do_test 4.$tn.1 {
foreach db {db db2} {
execsql {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a))%WR%;
CREATE TABLE t1(a, b, c, PRIMARY KEY(a));
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
@@ -333,7 +318,7 @@ foreach {tn2 conflict_return after} {
} db2
} {}
do_conflict_test $tn.4.$tn2.2 -tables t1 -sql {
do_conflict_test 4.$tn.2 -tables t1 -sql {
UPDATE t1 SET c = 'value1' WHERE a = 1; -- no conflict
UPDATE t1 SET c = 'value2' WHERE a = 4; -- DATA conflict
UPDATE t1 SET a = 10 WHERE a = 7; -- CONFLICT conflict
@@ -342,19 +327,19 @@ foreach {tn2 conflict_return after} {
{UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}}
}
do_db2_test $tn.4.$tn2.3 "SELECT * FROM t1 ORDER BY a" $after
do_db2_test 4.$tn.3 "SELECT * FROM t1 ORDER BY a" $after
}
foreach {tn2 conflict_return} {
foreach {tn conflict_return} {
1 OMIT
2 REPLACE
} {
test_reset
do_test $tn.5.$tn2.1 {
do_test 5.$tn.1 {
# Create an identical schema in both databases.
set schema {
CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y))%WR%;
CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y));
}
execsql $schema db
execsql $schema db2
@@ -369,7 +354,7 @@ foreach {tn2 conflict_return} {
} {}
do_conflict_test $tn.5.$tn2.2 -tables {{'foolish name'}} -sql {
do_conflict_test 5.$tn.2 -tables {{'foolish name'}} -sql {
INSERT INTO "'foolish name'" VALUES('one', 'two', 2);
} -conflicts {
{INSERT {'foolish name'} CONFLICT {t one t two i 2} {t one t two t i}}
@@ -377,14 +362,14 @@ foreach {tn2 conflict_return} {
set res(REPLACE) {one one ii one two 2 two two ii}
set res(OMIT) {one one ii one two i two two ii}
do_db2_test $tn.5.$tn2.3 {
do_db2_test 5.$tn.3 {
SELECT * FROM "'foolish name'" ORDER BY x, y
} $res($conflict_return)
do_test $tn.5.$tn2.1 {
do_test 5.$tn.1 {
set schema {
CREATE TABLE d1("z""z" PRIMARY KEY, y)%WR%;
CREATE TABLE d1("z""z" PRIMARY KEY, y);
INSERT INTO d1 VALUES(1, 'one');
INSERT INTO d1 VALUES(2, 'two');
}
@@ -397,7 +382,7 @@ foreach {tn2 conflict_return} {
} {}
do_conflict_test $tn.5.$tn2.2 -tables d1 -sql {
do_conflict_test 5.$tn.2 -tables d1 -sql {
DELETE FROM d1 WHERE "z""z" = 2;
} -conflicts {
{DELETE d1 DATA {i 2 t two} {i 2 t TWO}}
@@ -405,7 +390,7 @@ foreach {tn2 conflict_return} {
set res(REPLACE) {1 one}
set res(OMIT) {1 one 2 TWO}
do_db2_test $tn.5.$tn2.3 "SELECT * FROM d1" $res($conflict_return)
do_db2_test 5.$tn.3 "SELECT * FROM d1" $res($conflict_return)
}
#-------------------------------------------------------------------------
@@ -413,10 +398,10 @@ foreach {tn2 conflict_return} {
#
test_reset
set schema {
CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b)%WR%;
CREATE TABLE t2(a, b PRIMARY KEY)%WR%;
CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b);
CREATE TABLE t2(a, b PRIMARY KEY);
}
do_test $tn.6.0 {
do_test 6.0 {
execsql $schema db
execsql $schema db2
execsql {
@@ -426,7 +411,7 @@ do_test $tn.6.0 {
} {}
set conflict_return ""
do_conflict_test $tn.6.1 -tables {t1 t2} -sql {
do_conflict_test 6.1 -tables {t1 t2} -sql {
INSERT INTO t1 VALUES('1', '2');
INSERT INTO t1 VALUES('A', 'B');
INSERT INTO t2 VALUES('A', 'B');
@@ -434,8 +419,8 @@ do_conflict_test $tn.6.1 -tables {t1 t2} -sql {
{INSERT t1 CONFLICT {t A t B} {t a t b}}
}
do_db2_test $tn.6.2 "SELECT * FROM t1 ORDER BY a" {1 2 a b}
do_db2_test $tn.6.3 "SELECT * FROM t2 ORDER BY a" {A B a b}
do_db2_test 6.2 "SELECT * FROM t1" {a b 1 2}
do_db2_test 6.3 "SELECT * FROM t2" {a b A B}
#-------------------------------------------------------------------------
# Test that session objects are not confused by changes to table in
@@ -444,10 +429,10 @@ do_db2_test $tn.6.3 "SELECT * FROM t2 ORDER BY a" {A B a b}
catch { db2 close }
drop_all_tables
forcedelete test.db2
do_iterator_test $tn.7.1 * {
do_iterator_test 7.1 * {
ATTACH 'test.db2' AS aux;
CREATE TABLE main.t1(x PRIMARY KEY, y)%WR%;
CREATE TABLE aux.t1(x PRIMARY KEY, y)%WR%;
CREATE TABLE main.t1(x PRIMARY KEY, y);
CREATE TABLE aux.t1(x PRIMARY KEY, y);
INSERT INTO main.t1 VALUES('one', 1);
INSERT INTO main.t1 VALUES('two', 2);
@@ -461,10 +446,10 @@ do_iterator_test $tn.7.1 * {
#-------------------------------------------------------------------------
# Test the sqlite3session_isempty() function.
#
do_test $tn.8.1 {
do_test 8.1 {
execsql {
CREATE TABLE t5(x PRIMARY KEY, y)%WR%;
CREATE TABLE t6(x PRIMARY KEY, y)%WR%;
CREATE TABLE t5(x PRIMARY KEY, y);
CREATE TABLE t6(x PRIMARY KEY, y);
INSERT INTO t5 VALUES('a', 'b');
INSERT INTO t6 VALUES('a', 'b');
}
@@ -473,20 +458,20 @@ do_test $tn.8.1 {
S isempty
} {1}
do_test $tn.8.2 {
do_test 8.2 {
execsql { DELETE FROM t5 }
S isempty
} {0}
do_test $tn.8.3 {
do_test 8.3 {
S delete
sqlite3session S db main
S attach t5
execsql { DELETE FROM t5 }
S isempty
} {1}
do_test $tn.8.4 { S delete } {}
do_test 8.4 { S delete } {}
do_test $tn.8.5 {
do_test 8.5 {
sqlite3session S db main
S attach t5
S attach t6
@@ -494,7 +479,7 @@ do_test $tn.8.5 {
S isempty
} {0}
do_test $tn.8.6 {
do_test 8.6 {
S delete
sqlite3session S db main
S attach t5
@@ -502,20 +487,20 @@ do_test $tn.8.6 {
execsql { INSERT INTO t6 VALUES(1, 2) }
S isempty
} {0}
do_test $tn.8.7 { S delete } {}
do_test 8.7 { S delete } {}
#-------------------------------------------------------------------------
#
do_execsql_test $tn.9.1 {
CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g)%WR%;
do_execsql_test 9.1 {
CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g);
INSERT INTO t7 VALUES(1, 1, 1, 1, 1, 1, 1);
}
do_test $tn.9.2 {
do_test 9.2 {
sqlite3session S db main
S attach *
execsql { UPDATE t7 SET b=2, d=2 }
} {}
do_changeset_test $tn.9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
do_changeset_test 9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
S delete
catch { db2 close }
@@ -524,9 +509,9 @@ catch { db2 close }
#
reset_db
set tblname [string repeat tblname123 100]
do_test $tn.10.1.1 {
do_test 10.1.1 {
execsql "
CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
CREATE TABLE $tblname (a PRIMARY KEY, b);
INSERT INTO $tblname VALUES('xyz', 'def');
"
sqlite3session S db main
@@ -537,18 +522,18 @@ do_test $tn.10.1.1 {
"
} {}
breakpoint
do_changeset_test $tn.10.1.2 S "
do_changeset_test 10.1.2 S "
{INSERT $tblname 0 X. {} {t uvw t abc}}
{DELETE $tblname 0 X. {t xyz t def} {}}
"
do_test $tn.10.1.4 { S delete } {}
do_test 10.1.4 { S delete } {}
#---------------------------------------------------------------
reset_db
do_execsql_test $tn.11.1 {
do_execsql_test 11.1 {
CREATE TABLE t1(a, b);
}
do_test $tn.11.2 {
do_test 11.2 {
sqlite3session S db main
S attach t1
execsql {
@@ -565,9 +550,9 @@ S delete
#
reset_db
set tblname [string repeat tblname123 100]
do_test $tn.10.1.1 {
do_test 10.1.1 {
execsql "
CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
CREATE TABLE $tblname (a PRIMARY KEY, b);
INSERT INTO $tblname VALUES('xyz', 'def');
"
sqlite3session S db main
@@ -578,44 +563,23 @@ do_test $tn.10.1.1 {
"
} {}
breakpoint
do_changeset_test $tn.10.1.2 S "
do_changeset_test 10.1.2 S "
{INSERT $tblname 0 X. {} {t uvw t abc}}
{DELETE $tblname 0 X. {t xyz t def} {}}
"
do_test $tn.10.1.4 { S delete } {}
do_test 10.1.4 { S delete } {}
#-------------------------------------------------------------------------
# Test the effect of updating a column from 0.0 to 0.0.
#
reset_db
do_execsql_test $tn.11.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL)%WR%;
do_execsql_test 11.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL);
INSERT INTO t1 VALUES(1, 0.0);
}
do_iterator_test $tn.11.2 * {
do_iterator_test 11.2 * {
UPDATE t1 SET b = 0.0;
} {
}
reset_db
do_execsql_test $tn.12.1 {
CREATE TABLE t1(r INTEGER PRIMARY KEY, a, b)%WR%;
CREATE INDEX i1 ON t1(a);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 1, 2);
INSERT INTO t1 VALUES(3, 1, 3);
}
do_iterator_test $tn.12.2 * {
UPDATE t1 SET b='one' WHERE a=1;
} {
{UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}}
{UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}}
{UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}}
}
}]
}
finish_test
+1 -4
View File
@@ -63,10 +63,7 @@ do_test 1.2.1 {
INSERT INTO t1 VALUES(7, 8);
}
set ::log
} {}
do_test 1.2.2 {
db2 eval { SELECT * FROM t1 }
} {5 6 {} 7 8 {}}
} {SQLITE_SCHEMA {sqlite3changeset_apply(): table t1 has 3 columns, expected 2}}
do_test 1.3.0 {
execsql {
+6 -7
View File
@@ -33,11 +33,16 @@ proc do_changeset_invert_test {tn session res} {
proc do_conflict_test {tn args} {
proc xConflict {args} {
lappend ::xConflict $args
return ""
}
proc bgerror {args} { set ::background_error $args }
set O(-tables) [list]
set O(-sql) [list]
set O(-conflicts) [list]
set O(-policy) "OMIT"
array set V $args
foreach key [array names V] {
@@ -45,12 +50,6 @@ proc do_conflict_test {tn args} {
}
array set O $args
proc xConflict {args} [subst -nocommands {
lappend ::xConflict [set args]
return $O(-policy)
}]
proc bgerror {args} { set ::background_error $args }
sqlite3session S db main
foreach t $O(-tables) { S attach $t }
execsql $O(-sql)
-360
View File
@@ -1,360 +0,0 @@
/*
** 2017 January 31
**
** 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 the source code for a standalone program used to
** test the performance of the sessions module. Compile and run:
**
** ./session_speed_test -help
**
** for details.
*/
#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>
/*************************************************************************
** Start of generic command line parser.
*/
#define CMDLINE_BARE 0
#define CMDLINE_INTEGER 1
#define CMDLINE_STRING 2
#define CMDLINE_BOOLEAN 3
typedef struct CmdLineOption CmdLineOption;
struct CmdLineOption {
const char *zText; /* Name of command line option */
const char *zHelp; /* Help text for option */
int eType; /* One of the CMDLINE_* values */
int iOff; /* Offset of output variable */
};
#define CMDLINE_INT32(x,y,z) {x, y, CMDLINE_INTEGER, z}
#define CMDLINE_BOOL(x,y,z) {x, y, CMDLINE_BOOLEAN, z}
#define CMDLINE_TEXT(x,y,z) {x, y, CMDLINE_STRING, z}
#define CMDLINE_NONE(x,y,z) {x, y, CMDLINE_BARE, z}
static void option_requires_argument_error(CmdLineOption *pOpt){
fprintf(stderr, "Option requires a%s argument: %s\n",
pOpt->eType==CMDLINE_INTEGER ? "n integer" :
pOpt->eType==CMDLINE_STRING ? " string" : " boolean",
pOpt->zText
);
exit(1);
}
static void ambiguous_option_error(const char *zArg){
fprintf(stderr, "Option is ambiguous: %s\n", zArg);
exit(1);
}
static void unknown_option_error(
const char *zArg,
CmdLineOption *aOpt,
const char *zHelp
){
int i;
fprintf(stderr, "Unknown option: %s\n", zArg);
fprintf(stderr, "\nOptions are:\n");
fprintf(stderr, " % -30sEcho command line options\n", "-cmdline:verbose");
for(i=0; aOpt[i].zText; i++){
int eType = aOpt[i].eType;
char *zOpt = sqlite3_mprintf("%s %s", aOpt[i].zText,
eType==CMDLINE_BARE ? "" :
eType==CMDLINE_INTEGER ? "N" :
eType==CMDLINE_BOOLEAN ? "BOOLEAN" : "TEXT"
);
fprintf(stderr, " % -30s%s\n", zOpt, aOpt[i].zHelp);
sqlite3_free(zOpt);
}
if( zHelp ){
fprintf(stderr, "\n%s\n", zHelp);
}
exit(1);
}
static int get_integer_option(CmdLineOption *pOpt, const char *zArg){
int i = 0;
int iRet = 0;
int bSign = 1;
if( zArg[0]=='-' ){
bSign = -1;
i = 1;
}
while( zArg[i] ){
if( zArg[i]<'0' || zArg[i]>'9' ) option_requires_argument_error(pOpt);
iRet = iRet*10 + (zArg[i] - '0');
i++;
}
return (iRet*bSign);
}
static int get_boolean_option(CmdLineOption *pOpt, const char *zArg){
if( 0==sqlite3_stricmp(zArg, "true") ) return 1;
if( 0==sqlite3_stricmp(zArg, "1") ) return 1;
if( 0==sqlite3_stricmp(zArg, "0") ) return 0;
if( 0==sqlite3_stricmp(zArg, "false") ) return 0;
option_requires_argument_error(pOpt);
return 0;
}
static void parse_command_line(
int argc,
char **argv,
int iStart,
CmdLineOption *aOpt,
void *pStruct,
const char *zHelp
){
char *pOut = (char*)pStruct;
int bVerbose = 0;
int iArg;
for(iArg=iStart; iArg<argc; iArg++){
const char *zArg = argv[iArg];
int nArg = strlen(zArg);
int nMatch = 0;
int iOpt;
for(iOpt=0; aOpt[iOpt].zText; iOpt++){
CmdLineOption *pOpt = &aOpt[iOpt];
if( 0==sqlite3_strnicmp(pOpt->zText, zArg, nArg) ){
if( nMatch ){
ambiguous_option_error(zArg);
}
nMatch++;
if( pOpt->eType==CMDLINE_BARE ){
*(int*)(&pOut[pOpt->iOff]) = 1;
}else{
iArg++;
if( iArg==argc ){
option_requires_argument_error(pOpt);
}
switch( pOpt->eType ){
case CMDLINE_INTEGER:
*(int*)(&pOut[pOpt->iOff]) = get_integer_option(pOpt, argv[iArg]);
break;
case CMDLINE_STRING:
*(const char**)(&pOut[pOpt->iOff]) = argv[iArg];
break;
case CMDLINE_BOOLEAN:
*(int*)(&pOut[pOpt->iOff]) = get_boolean_option(pOpt, argv[iArg]);
break;
}
}
}
}
if( nMatch==0 && 0==sqlite3_strnicmp("-cmdline:verbose", zArg, nArg) ){
bVerbose = 1;
nMatch = 1;
}
if( nMatch==0 ){
unknown_option_error(zArg, aOpt, zHelp);
}
}
if( bVerbose ){
int iOpt;
fprintf(stdout, "Options are: ");
for(iOpt=0; aOpt[iOpt].zText; iOpt++){
CmdLineOption *pOpt = &aOpt[iOpt];
if( pOpt->eType!=CMDLINE_BARE || *(int*)(&pOut[pOpt->iOff]) ){
fprintf(stdout, "%s ", pOpt->zText);
}
switch( pOpt->eType ){
case CMDLINE_INTEGER:
fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
break;
case CMDLINE_BOOLEAN:
fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff]));
break;
case CMDLINE_STRING:
fprintf(stdout, "%s ", *(const char**)(&pOut[pOpt->iOff]));
break;
}
}
fprintf(stdout, "\n");
}
}
/*
** End of generic command line parser.
*************************************************************************/
static void abort_due_to_error(int rc){
fprintf(stderr, "Error: %d\n");
exit(-1);
}
static void execsql(sqlite3 *db, const char *zSql){
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
}
static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *p){
return SQLITE_CHANGESET_ABORT;
}
static void run_test(
sqlite3 *db,
sqlite3 *db2,
int nRow,
const char *zSql
){
sqlite3_session *pSession = 0;
sqlite3_stmt *pStmt = 0;
int rc;
int i;
int nChangeset;
void *pChangeset;
/* Attach a session object to database db */
rc = sqlite3session_create(db, "main", &pSession);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
/* Configure the session to capture changes on all tables */
rc = sqlite3session_attach(pSession, 0);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
/* Prepare the SQL statement */
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
/* Open a transaction */
execsql(db, "BEGIN");
/* Execute the SQL statement nRow times */
for(i=0; i<nRow; i++){
sqlite3_bind_int(pStmt, 1, i);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
}
sqlite3_finalize(pStmt);
/* Extract a changeset from the sessions object */
rc = sqlite3session_changeset(pSession, &nChangeset, &pChangeset);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
execsql(db, "COMMIT");
/* Apply the changeset to the second db */
rc = sqlite3changeset_apply(db2, nChangeset, pChangeset, 0, xConflict, 0);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
/* Cleanup */
sqlite3_free(pChangeset);
sqlite3session_delete(pSession);
}
int main(int argc, char **argv){
struct Options {
int nRow;
int bWithoutRowid;
int bInteger;
int bAll;
const char *zDb;
};
struct Options o = { 2500, 0, 0, 0, "session_speed_test.db" };
CmdLineOption aOpt[] = {
CMDLINE_INT32( "-rows", "number of rows in test",
offsetof(struct Options, nRow) ),
CMDLINE_BOOL("-without-rowid", "use WITHOUT ROWID tables",
offsetof(struct Options, bWithoutRowid) ),
CMDLINE_BOOL("-integer", "use integer data (instead of text/blobs)",
offsetof(struct Options, bInteger) ),
CMDLINE_NONE("-all", "Run all 4 combos of -without-rowid and -integer",
offsetof(struct Options, bAll) ),
CMDLINE_TEXT("-database", "prefix for database files to use",
offsetof(struct Options, zDb) ),
{0, 0, 0, 0}
};
const char *azCreate[] = {
"CREATE TABLE t1(a PRIMARY KEY, b, c, d)",
"CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID",
};
const char *azInsert[] = {
"INSERT INTO t1 VALUES("
"printf('%.8d',?), randomblob(50), randomblob(50), randomblob(50))",
"INSERT INTO t1 VALUES(?, random(), random(), random())"
};
const char *azUpdate[] = {
"UPDATE t1 SET d = randomblob(50) WHERE a = printf('%.8d',?)",
"UPDATE t1 SET d = random() WHERE a = ?"
};
const char *azDelete[] = {
"DELETE FROM t1 WHERE a = printf('%.8d',?)",
"DELETE FROM t1 WHERE a = ?"
};
int rc;
sqlite3 *db;
sqlite3 *db2;
char *zDb2;
int bWithoutRowid;
int bInteger;
parse_command_line(argc, argv, 1, aOpt, (void*)&o,
"This program creates two new, empty, databases each containing a single\n"
"table. It then does the following:\n\n"
" 1. Inserts -rows rows into the first database\n"
" 2. Updates each row in the first db\n"
" 3. Delete each row from the first db\n\n"
"The modifications made by each step are captured in a changeset and\n"
"applied to the second database.\n"
);
zDb2 = sqlite3_mprintf("%s2", o.zDb);
for(bWithoutRowid=0; bWithoutRowid<2; bWithoutRowid++){
for(bInteger=0; bInteger<2; bInteger++){
if( o.bAll || (o.bWithoutRowid==bWithoutRowid && o.bInteger==bInteger) ){
fprintf(stdout, "Testing %s data with %s table\n",
bInteger ? "integer" : "blob/text",
bWithoutRowid ? "WITHOUT ROWID" : "rowid"
);
/* Open new database handles on two empty databases */
unlink(o.zDb);
rc = sqlite3_open(o.zDb, &db);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
unlink(zDb2);
rc = sqlite3_open(zDb2, &db2);
if( rc!=SQLITE_OK ) abort_due_to_error(rc);
/* Create the schema in both databases. */
execsql(db, azCreate[o.bWithoutRowid]);
execsql(db2, azCreate[o.bWithoutRowid]);
/* Run the three tests */
run_test(db, db2, o.nRow, azInsert[o.bInteger]);
run_test(db, db2, o.nRow, azUpdate[o.bInteger]);
run_test(db, db2, o.nRow, azDelete[o.bInteger]);
/* Close the db handles */
sqlite3_close(db);
sqlite3_close(db2);
}
}
}
return 0;
}
-216
View File
@@ -1,216 +0,0 @@
# 2017 February 04
#
# 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.
#
#***********************************************************************
#
# Tests for the sessions module. Specifically, that a changeset can
# be applied after ALTER TABLE ADD COLUMN has been used to add
# columns to tables.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionat
db close
sqlite3_shutdown
test_sqlite3_log log
proc log {code msg} { lappend ::log $code $msg }
proc reset_test {} {
catch { db close }
catch { db2 close }
forcedelete test.db test.db2
sqlite3 db test.db
sqlite3 db2 test.db2
}
# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
# with regular rowid tables.
#
# ?.1.*: Test that PK inconsistencies are detected if one or more of the PK
# columns are not present in the changeset.
#
# ?.2.*: Test that it is not possible to apply a changeset with N columns
# to a db with fewer than N columns.
#
# ?.3.*: Test some INSERT, UPDATE and DELETE operations that do not
# require conflict handling.
#
# ?.4.*: Test some INSERT, UPDATE and DELETE operations that do require
# conflict handling.
#
# ?.5.*: Test that attempting to concat two changesets with different
# numbers of columns for the same table is an error.
#
foreach {tn trailing} {
sessionat-ipk ""
sessionat-wor " WITHOUT ROWID "
} {
eval [string map [list %WR% $trailing] {
reset_test
#-----------------------------------------------------------------------
do_execsql_test $tn.1.0 {
CREATE TABLE t1(a, b, PRIMARY KEY(a)) %WR%;
}
do_execsql_test -db db2 $tn.1.1 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) %WR%;
}
do_test $tn.1.2 {
set ::log {}
do_then_apply_sql { INSERT INTO t1 VALUES('one', 'two') }
set ::log
} [list \
SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}
]
do_execsql_test $tn.1.3 { SELECT * FROM t1 } {one two}
do_execsql_test -db db2 $tn.1.4 { SELECT * FROM t1 } {}
#-----------------------------------------------------------------------
do_execsql_test $tn.2.0 {
CREATE TABLE t2(x, y, z, PRIMARY KEY(x)) %WR%;
}
do_execsql_test -db db2 $tn.2.1 {
CREATE TABLE t2(x, y, PRIMARY KEY(x)) %WR%;
}
do_test $tn.2.2 {
db cache flush
set ::log {}
do_then_apply_sql { INSERT INTO t2 VALUES(1, 2, 3) }
set ::log
} [list SQLITE_SCHEMA \
{sqlite3changeset_apply(): table t2 has 2 columns, expected 3 or more}
]
do_execsql_test $tn.2.3 { SELECT * FROM t2 } {1 2 3}
do_execsql_test -db db2 $tn.2.4 { SELECT * FROM t2 } {}
#-----------------------------------------------------------------------
do_execsql_test $tn.3.0 {
CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%;
}
do_execsql_test -db db2 $tn.3.1 {
CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%;
}
do_test $tn.3.2 {
do_then_apply_sql {
INSERT INTO t3 VALUES(1, 2);
INSERT INTO t3 VALUES(3, 4);
INSERT INTO t3 VALUES(5, 6);
};
db2 eval {SELECT * FROM t3}
} {1 2 D 3 4 D 5 6 D}
do_test $tn.3.3 {
do_then_apply_sql {
UPDATE t3 SET a=45 WHERE b=4;
DELETE FROM t3 WHERE a=5;
};
db2 eval {SELECT * FROM t3}
} {1 2 D 45 4 D}
#-----------------------------------------------------------------------
# 4.1: INSERT statements
# 4.2: DELETE statements
# 4.3: UPDATE statements
#
do_execsql_test $tn.4.1.0 {
CREATE TABLE t4(x INTEGER PRIMARY KEY, y) %WR%;
}
do_execsql_test -db db2 $tn.4.1.1 {
CREATE TABLE t4(x INTEGER PRIMARY KEY, y, z) %WR%;
INSERT INTO t4 VALUES(1, 2, 3);
INSERT INTO t4 VALUES(4, 5, 6);
}
do_conflict_test $tn.4.1.2 -tables t4 -sql {
INSERT INTO t4 VALUES(10, 20);
INSERT INTO t4 VALUES(4, 11);
} -conflicts {
{INSERT t4 CONFLICT {i 4 i 11} {i 4 i 5}}
}
do_execsql_test -db db2 $tn.4.1.3 {
SELECT * FROM t4 ORDER BY x
} {1 2 3 4 5 6 10 20 {}}
do_conflict_test $tn.4.1.4 -policy REPLACE -tables t4 -sql {
INSERT INTO t4 VALUES(1, 11);
} -conflicts {
{INSERT t4 CONFLICT {i 1 i 11} {i 1 i 2}}
}
do_execsql_test -db db2 $tn.4.1.5 {
SELECT * FROM t4 ORDER BY x
} {1 11 {} 4 5 6 10 20 {}}
do_execsql_test $tn.4.2.0 {
DELETE FROM t4;
INSERT INTO t4 VALUES(1, 'A');
INSERT INTO t4 VALUES(2, 'B');
INSERT INTO t4 VALUES(3, 'C');
INSERT INTO t4 VALUES(4, 'D');
}
do_execsql_test -db db2 $tn.4.2.1 {
DELETE FROM t4;
INSERT INTO t4 VALUES(1, 'A', 'a');
INSERT INTO t4 VALUES(3, 'C', 'c');
INSERT INTO t4 VALUES(4, 'E', 'd');
}
do_conflict_test $tn.4.2.2 -tables t4 -sql {
DELETE FROM t4 WHERE x=2;
DELETE FROM t4 WHERE x=4;
} -conflicts {
{DELETE t4 NOTFOUND {i 2 t B}}
{DELETE t4 DATA {i 4 t D} {i 4 t E}}
}
do_execsql_test $tn.4.3.0 {
CREATE TABLE t5(a, b, c PRIMARY KEY) %WR%;
INSERT INTO t5 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4);
}
do_execsql_test -db db2 $tn.4.3.1 {
CREATE TABLE t5(a, b, c PRIMARY KEY, d CHECK(b!=10)) %WR%;
INSERT INTO t5 VALUES (2,2,2,2), (3,8,3,3), (4,4,4,4);
}
do_conflict_test $tn.4.3.2 -tables t5 -sql {
UPDATE t5 SET a=4 WHERE c=1;
UPDATE t5 SET b=9 WHERE c=3;
UPDATE t5 SET b=10 WHERE c=2;
} -conflicts {
{UPDATE t5 NOTFOUND {i 1 {} {} i 1} {i 4 {} {} {} {}}}
{UPDATE t5 DATA {{} {} i 3 i 3} {{} {} i 9 {} {}} {i 3 i 8 i 3}}
{UPDATE t5 CONSTRAINT {{} {} i 2 i 2} {{} {} i 10 {} {}}}
}
#-----------------------------------------------------------------------
do_execsql_test $tn.5.0 {
CREATE TABLE t6(a, b, c, PRIMARY KEY(a, b)) %WR%;
}
do_execsql_test -db db2 $tn.5.1 {
CREATE TABLE t6(a, b, c, d, e, PRIMARY KEY(a, b)) %WR%;
}
do_test $tn.5.2 {
set c1 [sql_exec_changeset db {
INSERT INTO t6 VALUES(1, 1, 1);
INSERT INTO t6 VALUES(2, 2, 2);
}]
set c2 [sql_exec_changeset db2 {
INSERT INTO t6 VALUES(3, 3, 3, 3, 3);
INSERT INTO t6 VALUES(4, 4, 4, 4, 4);
}]
list [catch { sqlite3changeset_concat $c1 $c2} msg] $msg
} {1 SQLITE_SCHEMA}
}]
}
finish_test
-57
View File
@@ -1,57 +0,0 @@
# 2017 Jan 31
#
# 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.
#
#***********************************************************************
#
# The focus of this file is testing the session module. Specifically,
# testing support for WITHOUT ROWID tables.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionwor
proc test_reset {} {
catch { db close }
catch { db2 close }
forcedelete test.db test.db2
sqlite3 db test.db
sqlite3 db2 test.db2
}
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
}
do_iterator_test 1.1 t1 {
INSERT INTO t1 VALUES('one', 'two');
} {
{INSERT t1 0 X. {} {t one t two}}
}
do_iterator_test 1.2 t1 {
UPDATE t1 SET b='three'
} {
{UPDATE t1 0 X. {t one t two} {{} {} t three}}
}
do_iterator_test 1.3 t1 {
DELETE FROM t1;
} {
{DELETE t1 0 X. {t one t three} {}}
}
finish_test
+12 -27
View File
@@ -3028,7 +3028,7 @@ int sqlite3changeset_conflict(
if( !pIter->pConflict ){
return SQLITE_MISUSE;
}
if( iVal<0 || iVal>=pIter->nCol ){
if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){
return SQLITE_RANGE;
}
*ppValue = sqlite3_column_value(pIter->pConflict, iVal);
@@ -3495,13 +3495,7 @@ static int sessionInsertRow(
sessionAppendStr(&buf, "INSERT INTO main.", &rc);
sessionAppendIdent(&buf, zTab, &rc);
sessionAppendStr(&buf, "(", &rc);
for(i=0; i<p->nCol; i++){
if( i!=0 ) sessionAppendStr(&buf, ", ", &rc);
sessionAppendIdent(&buf, p->azCol[i], &rc);
}
sessionAppendStr(&buf, ") VALUES(?", &rc);
sessionAppendStr(&buf, " VALUES(?", &rc);
for(i=1; i<p->nCol; i++){
sessionAppendStr(&buf, ", ?", &rc);
}
@@ -4047,17 +4041,11 @@ static int sessionChangesetApply(
nTab = (int)strlen(zTab);
sApply.azCol = (const char **)zTab;
}else{
int nMinCol = 0;
int i;
sqlite3changeset_pk(pIter, &abPK, 0);
rc = sessionTableInfo(
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
for(i=0; i<sApply.nCol; i++){
if( sApply.abPK[i] ) nMinCol = i+1;
}
if( sApply.nCol==0 ){
schemaMismatch = 1;
@@ -4065,29 +4053,26 @@ static int sessionChangesetApply(
"sqlite3changeset_apply(): no such table: %s", zTab
);
}
else if( sApply.nCol<nCol ){
else if( sApply.nCol!=nCol ){
schemaMismatch = 1;
sqlite3_log(SQLITE_SCHEMA,
"sqlite3changeset_apply(): table %s has %d columns, "
"expected %d or more",
"sqlite3changeset_apply(): table %s has %d columns, expected %d",
zTab, sApply.nCol, nCol
);
}
else if( nCol<nMinCol || memcmp(sApply.abPK, abPK, nCol)!=0 ){
else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){
schemaMismatch = 1;
sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): "
"primary key mismatch for table %s", zTab
);
}
else{
sApply.nCol = nCol;
if((rc = sessionSelectRow(db, zTab, &sApply))
|| (rc = sessionUpdateRow(db, zTab, &sApply))
|| (rc = sessionDeleteRow(db, zTab, &sApply))
|| (rc = sessionInsertRow(db, zTab, &sApply))
){
break;
}
else if(
(rc = sessionSelectRow(db, zTab, &sApply))
|| (rc = sessionUpdateRow(db, zTab, &sApply))
|| (rc = sessionDeleteRow(db, zTab, &sApply))
|| (rc = sessionInsertRow(db, zTab, &sApply))
){
break;
}
nTab = sqlite3Strlen30(zTab);
}
+9 -16
View File
@@ -319,8 +319,7 @@ int sqlite3session_changeset(
** the from-table, a DELETE record is added to the session object.
**
** <li> For each row (primary key) that exists in both tables, but features
** different non-PK values in each, an UPDATE record is added to the
** session.
** different in each, an UPDATE record is added to the session.
** </ul>
**
** To clarify, if this function is called and then a changeset constructed
@@ -905,7 +904,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** <ul>
** <li> The table has the same name as the name recorded in the
** changeset, and
** <li> The table has at least as many columns as recorded in the
** <li> The table has the same number of columns as recorded in the
** changeset, and
** <li> The table has primary key columns in the same position as
** recorded in the changeset.
@@ -950,11 +949,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** If a row with matching primary key values is found, but one or more of
** the non-primary key fields contains a value different from the original
** row value stored in the changeset, the conflict-handler function is
** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the
** database table has more columns than are recorded in the changeset,
** only the values of those non-primary key fields are compared against
** the current database contents - any trailing database table columns
** are ignored.
** invoked with [SQLITE_CHANGESET_DATA] as the second argument.
**
** If no row with matching primary key values is found in the database,
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
@@ -969,9 +964,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** <dt>INSERT Changes<dd>
** For each INSERT change, an attempt is made to insert the new row into
** the database. If the changeset row contains fewer fields than the
** database table, the trailing fields are populated with their default
** values.
** the database.
**
** If the attempt to insert the row fails because the database already
** contains a row with the same primary key values, the conflict handler
@@ -989,13 +982,13 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** For each UPDATE change, this function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all modified non-primary key columns also match the values
** stored in the changeset the row is updated within the target database.
** stored in all non-primary key columns also match the values stored in
** the changeset the row is updated within the target database.
**
** If a row with matching primary key values is found, but one or more of
** the modified non-primary key fields contains a value different from an
** original row value stored in the changeset, the conflict-handler function
** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
** the non-primary key fields contains a value different from an original
** row value stored in the changeset, the conflict-handler function is
** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
** UPDATE changes only contain values for non-primary key fields that are
** to be modified, only those fields need to match the original values to
** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
+1 -1
View File
@@ -22,7 +22,7 @@
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
#ifndef SQLITEINT_H
#ifndef _SQLITEINT_H_
# include "sqliteInt.h"
#endif
+2 -12
View File
@@ -478,10 +478,6 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
DBSELFTEST_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
ST_OPT = -DSQLITE_THREADSAFE=0
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -896,14 +892,8 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
$(TOP)/test/wordcount.c sqlite3.c
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.c
$(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB)
kvtest$(EXE): $(TOP)/test/kvtest.c sqlite3.c
$(TCCX) -I. $(KV_OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB)
dbselftest$(EXE): $(TOP)/test/dbselftest.c sqlite3.c
$(TCCX) -I. $(DBSELFTEST_OPT) -o dbselftest$(EXE) $(TOP)/test/dbselftest.c sqlite3.c $(THREADLIB)
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
$(TCCX) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
+90 -102
View File
@@ -1,17 +1,17 @@
C The\sVDBE\scycle\scounts\sfor\sthe\ssqlite3_progress_handler()\scallback\sare\snow\ncumulative.\s\sLeftovers\sfrom\sthe\sprevious\sstatement\sare\sapplied\sto\sthe\snext\nstatement.
D 2017-02-21T14:04:40.431
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
C Fix\sproblems\sin\sthe\sprevious\scommit.
D 2017-01-21T16:21:24.115
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 3605fa447e4623f5ff4a6adc97b1fde9a257b8f2
F VERSION cddd8d88dc8202afa0ebc96da61fc4acbd1e96a5
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
F autoconf/Makefile.msc 3de603bcec5c07462801a20fd7dc1b871400af99
F autoconf/Makefile.msc b6d27f735911fd09a589d3c966936c47a5850c17
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac cacf2616abf6e4a569bde2ef365c143caeec40bc
@@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure b15d030a8ae2e672d76c97b6667dacb98934a467 x
F configure fcfa56d5d66668c9263dc007724f62acff06dc83 x
F configure.ac 605173e829ab64514ed89f9b53d0da1739d7b0a0
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
@@ -70,9 +70,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c c4d7eecb12de9749851bcab6e5ca616a5803047a
F ext/fts3/fts3.c e028eb13432f108d2e22cded019fc980700e4e00
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
F ext/fts3/fts3Int.h 89d0bd4595a0de384dac78e94b803de12586e8dd
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
F ext/fts3/fts3_expr.c dfd571a24412779ac01f25c01d888c6ef7b2d0ef
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
@@ -98,11 +98,11 @@ F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
F ext/fts5/fts5Int.h c629b24d2b92b99596f3b8e82289fddca06df6e1
F ext/fts5/fts5Int.h b2eda36e0f224365c8e23dc8f559311834f1c13f
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 33f0e8063ac7360bcd71c0ff0dcbacdc05fffe50
F ext/fts5/fts5_expr.c dc2cee9f56b1818b85df59304b8104a5dfb8ab60
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c f67032a9a529ba52a545e6e3ab970764199c05d4
F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2
@@ -184,11 +184,11 @@ F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6
F ext/fts5/test/fts5simple.test 5da9b15ed534eb0be9f279d8a2bb2e24d30e4e38
F ext/fts5/test/fts5simple2.test 00839031878f52391562594fdab0503e424ee071
F ext/fts5/test/fts5simple3.test 25faa8cb8ad470c6f01f670bcc1317c19a89f091
F ext/fts5/test/fts5synonym.test f964f9a98580dec06c995d4638ecb36eee60ae4a
F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48
F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e
F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test f64ab5fe48fa1317ff6315264bfe26e73cbdefde
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
F ext/fts5/test/fts5unicode2.test 529ac7e8648c943bc87bfed1e427128a2f3f9e33
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
@@ -202,7 +202,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
F ext/icu/icu.c 03ff6f90f3004a7e5a86205b581b2b7035ebf6e1
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
@@ -213,7 +213,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 552a7d730863419e05dc947265b28bd411680e2e
F ext/misc/json1.c e0797ef1bfa637429ceab9140ecba620809ee02a
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
@@ -222,7 +222,6 @@ F ext/misc/remember.c 8440f8d0b452c5cdefb62b57135ccd1267aa729d
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
@@ -264,7 +263,7 @@ F ext/rbu/sqlite3rbu.c bb0de6cdbdb14a7d55a097238a434b7e99caf318
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 3f3a595dba485e340246fa2c8ba330a6b9768b00
F ext/rtree/rtree.c 078fc27417b48aaebe988621bf96ef0e1645b201
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 42dadfc7b44a436cd74a1bebc0b9b689e4eaf7ec
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -275,7 +274,7 @@ F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
F ext/rtree/rtreeA.test ac8b503931f2f397cc3c3303354e1e085dcadb86
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test c0a9c67f2efa98b6fae12acb8a28348d231a481d
F ext/rtree/rtreeD.test bdfaaf26df8b4eea7364039aca9150bc1e1f8825
@@ -288,9 +287,9 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
F ext/session/session1.test c8a50e0e8581dc1a00e832aa59bb61f180404d44
F ext/session/session1.test e5125b216d1e8c91e0984b361b0b68529e7c5dfb
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
F ext/session/session4.test 457b02bdc349eb01151e54de014df77abd3c08c8
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
@@ -303,22 +302,19 @@ F ext/session/sessionD.test d4744c78334162851d2a2f285c7e603e31b49aa2
F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26
F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
F ext/session/session_common.tcl 7776eda579773113b30c7abfd4545c445228cb73
F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
F ext/session/sessionat.test b25d61d663ebc795506bf74079dc4ba0092fad25
F ext/session/session_common.tcl 9b696a341cf1d3744823715ed92bb19749b6c3d4
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920
F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
F ext/session/sqlite3session.c c61a43396368ec00dc127f7bc647e9bd6a4ee5fb
F ext/session/sqlite3session.h 9345166bd8f80562145586cf817f707de5ecada2
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 08e0b151abb46353c677ac4974b50c6077f85eee
F main.mk 8f620f3418d7252a3f428f5aacf674b5507807a8
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -331,23 +327,23 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c ac7a5d7e3cee07d074697904e00e4a8ab7b2b4f5
F src/analyze.c 317dbaf31c16050582b09bf4f323b4e0f1813251
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c 3ae66974881e74df9909093818b4c3428f8d7982
F src/btree.c e6b8f39d7dd1ad65f1747956de36f2595172a23d
F src/btree.h e6d352808956ec163a17f832193a3e198b3fb0ac
F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
F src/build.c 9e799f1edd910dfa8a0bc29bd390d35d310596af
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c a9984df73898c042a5cfc8f9d8e7723d02bc35c9
F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
F src/expr.c 8a29e9b72d4b642189999c41782cd6c5bc43512f
F src/delete.c 8a444fea8340989d6b1be2e122c55bfc61ce69be
F src/expr.c f06f41e5e5daca10fb090e70a2502dcc0dbc992b
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
@@ -356,13 +352,13 @@ F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3ed64afc49c0a2221e397b9f65d231ffbef506fe
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
F src/insert.c 05e47e2de7b712a3a4148cd469e5f60873f5ef13
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258
F src/main.c e207b81542d13b9f13d61e78ca441f9781f055b0
F src/malloc.c d0a1474236486165bcb349af82e2a6560178bf7b
F src/malloc.c fc1b9f445290f2145da48fc08730c26e6082b640
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c fd7cd6fe21d46fe0a4186367dd8dc26d87b787eb
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
@@ -372,44 +368,44 @@ F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
F src/mutex_w32.c a898fa969823b100c0f5fdc57e54c9a1e419ab4d
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y af8830094f4aecb91cb69721f3601ad10c36abc4
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/pager.c 9dc72d23eebbdf992bd69f2ab954d0d3a27c7340
F src/pager.h d1e944291030351f362a0a7da9b5c3e34e603e39
F src/parse.y 29153738a7322054359320eb00b5a4cd44389f20
F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 7831956012f5d764761fbd023e59b0ffc08f5e8d
F src/pragma.c 0e7a7c6f1c6fd8ff50c0fff65b8bb80174bc49c5
F src/pragma.h 61aa5389118594bebb28120a6720401aee34ce1a
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
F src/printf.c ff10a9b9902cd2afe5f655f3013c6307d969b1fd
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f
F src/shell.c bf976d5301be9d8a4c52852c97909cc9a41ee20d
F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966
F src/select.c 3856db523b942062bca8722ba03b61c324ff94d6
F src/shell.c 0344f71dc008df2433ae10175f59ad432c428810
F src/sqlite.h.in e71655293c9bde26939496f3aac9d1821d2c07a2
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 15f78048a1c8cbe0027a69d60ed3c92e9e7eb27e
F src/sqliteInt.h 525c061ae9aafc8d4720a018d82f0936d9eee5ab
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 6c2151b6d8d98e183a04466d40df8889c0574d79
F src/tclsqlite.c 418f5e5e0840425a7e5b33f3600dccd378a57549
F src/test1.c 8a98191a1da8e100f77cdb5cc716df67d405028d
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c 121060d2e79a4f5047eb12b5135b23a6a7a5af01
F src/test6.c 55aa2775c154415dcf4ed7cd1e19a193122b3a02
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
@@ -417,10 +413,10 @@ F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
F src/test_blob.c f65ac717da2618691cf9dad094e6da0219dcd208
F src/test_blob.c 6a4c7920d1d9c6cc0f7aa50c89c4f80016aeda83
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 83179ea845479b5be9a651d014649e3f2722a1fe
F src/test_delete.c af7eab5702f853fb1c62a5f7665e2234cf1ae17b
F src/test_delete.c 8499d4d323f2ec8e28301deb3d6ddd8eef8b8139
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
F src/test_fs.c e16cbe68d3b107e00a907c20a9a02629870eb69b
@@ -454,31 +450,31 @@ F src/test_windirent.c 17f91f5f2aa1bb7328abb49414c363b5d2a9d3ff
F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 25ccc63ae2c4163933221f3181c9982b47cd08d2
F src/tokenize.c 5c2f516876fc27fbd7753913f032f49eb89e83b5
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
F src/update.c b356b29d04c71f33c779f2cb557cf953819bdd7a
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
F src/vdbe.c aab9f3ca2d1e4ecc052232697393305e2fbf256b
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1
F src/vdbeaux.c 4122458d33318ab039c4b5da1ca4e7c9221c38e4
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/util.c a88b0466fddf445ce752226d4698ca3faada620a
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
F src/vdbe.c 132f552033f72820c27a100861fa83254358cbcd
F src/vdbe.h b0866e4191f096f1c987a84b042c3599bdf5423b
F src/vdbeInt.h 4cad10b68ed052104a997454540ea71ceb2888e1
F src/vdbeapi.c d6ebaa465f070eb1af8ba4e7b34583ece87bdd24
F src/vdbeaux.c 35c9a9908174e5a26c96d15e1f98214814a39147
F src/vdbeblob.c 824f360105b8cd43c2ec8c4611fd3b162a3a3eed
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790
F src/vtab.c c4bbe0f870f52036553f8098aee0703997f0577a
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 01baf58b72f3ddb7793cdee2871f751e3e09b35e
F src/whereInt.h c0b092180f04608d80c258174b0a14a1f9c8d02f
F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
F src/where.c bc71775e23d23334e8f449aa31012d692dc09cb2
F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d
F src/wherecode.c e04ac8f24c3ac8621df6c3be3ac8c7d4fa893745
F src/whereexpr.c 35ad025389a632a3987a35617c878be3b3d70dc6
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -607,7 +603,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
F test/corruptC.test 46ec43bd90a02fd7b37ad8a7a949c55aa5717f89
F test/corruptC.test 4ef10844eba5213bd262f4d96784d7fcda114afe
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
@@ -635,8 +631,7 @@ F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
F test/date.test a6a5a48b90907bca9fbcc79a30be5a715c1ab2fc
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbselftest.c b2e6cfac59066dbcb7334b66304bb15a5508dd42
F test/dbfuzz.c 8cc2bdb818b4483a052f9f80f96be74cbd9a6e1d
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
@@ -676,7 +671,6 @@ F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
F test/e_walhook.test 4c0613a0c76e7a9d5c4c211e1b4cbcc1143914df
F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
@@ -685,7 +679,7 @@ F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
@@ -838,8 +832,7 @@ F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/hook.test 3a01b876691f9151d3e44562354f7d663ff90fce
F test/icu.test 73956798bace8982909c00476b216714a6d0559a
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
@@ -853,7 +846,7 @@ F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
@@ -868,7 +861,7 @@ F test/index6.test b4fc812290067a578b98bb2667b676db89e202a7
F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
F test/indexexpr1.test 038b3befa74e5a75126b6e9dd2ae5df61c1c7cf7
F test/indexexpr1.test 7d243fac508b4a99fb900ffe34eb488312cfce84
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
@@ -905,7 +898,7 @@ F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5
F test/kvtest.c 9e428931f0733b5ba65b6b5abd95b27320e875a3
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
@@ -929,7 +922,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test 192d0b5ee1d023a07d5164c34cf47d010da73da1
F test/malloc5.test 02ed7c5313f0a68d95f2dfca8c8962132bd1f04b
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@@ -1016,13 +1009,13 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 46ad98770d3c04ce2418cab2cc527647bfe961a7
F test/permutations.test cd0b7bc04bf5e50d3a993d24c834d591f7d4f5fe
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@@ -1138,7 +1131,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 7b1ab42b097b484c18d99e1d1c71a6a0c9c87a7a
F test/speedtest1.c 02fe15bb784c5276a083ffe9969cc51e0bce7644
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1158,7 +1151,7 @@ F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test 699251cb99651415218a891384510a685c7ab012
F test/tabfunc01.test 8b2ef53caa37854864c89e1e57e8a10efd4f5e43
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1170,7 +1163,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 67835ac17e90055f24a9cf52e5c5bce0dd511c74
F test/tester.tcl 4ce5afd5e192db4cae178e1a983b060e0f08c5d6
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1206,7 +1199,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
F test/tkt-78e04e52ea.test 1b2e6bf4f1d9887b216b6da774e5f25915ec8118
F test/tkt-78e04e52ea.test 813779f8888f3ca226df656c4eef078f9635f3c9
F test/tkt-7a31705a7e6.test e75a2bba4eec801b92c8040eb22096ac6d35e844
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
@@ -1361,7 +1354,7 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
F test/update2.test 81772e5c9b93d1006d66d65e9a1327281bdec4e8
F test/update2.test 7f72ef307d58be09a8ef61db23a7ef60e5af019d
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
@@ -1375,7 +1368,7 @@ F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab
F test/vtab1.test ed4a576231d8a36e70fd18e2b79b621b31e7f22a
F test/vtab1.test 7c4b81abd88361ada9cbe414c459efca26be6bda
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1390,7 +1383,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
F test/vtabH.test 5f9253eb9e41ba9fe94f4aa3e9230191893d7764
F test/vtabH.test a2912cd3ea3386aecc3cb74ebfdfcc4e6d4b7dd3
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
@@ -1481,16 +1474,14 @@ F tool/fuzzershell.c dbf6c26eef936ec78cb0707570de3a4308b2507e
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 5ccba178a8e8a4b21e1c9232944d23973da38ad7
F tool/lempar.c db1bdb4821f2d8fbd76e577cf3ab18642c8d08d1
F tool/lempar.c 320d630b44da693407684c64d9fa91a163419dac
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22
F tool/mkmsvcmin.tcl 95b37e202cbed873aa8ffdbb493b9db45927be2b
F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@@ -1498,7 +1489,7 @@ F tool/mkpragmatab.tcl ebb4bfcd2f8010e0a3934b6118db4b5f2f5edf5c
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
F tool/mksqlite3h.tcl b9836752c3d08f9fab2dfc0017ca9fd5d90ac863
F tool/mksqlite3h.tcl c006c4e5da57c649b24b689511dcd270dd7b0249
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
@@ -1516,7 +1507,7 @@ F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
F tool/speed-check.sh 65ac2f5b00771b9dcefb95bebae1aab76c537ea3
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1556,10 +1547,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1589db012ef1389bf84399fccf96d143b2ac4c0f
R 5142727fa68f4d8f31618eaf0dc5d893
T *branch * cumulative-progress-count
T *sym-cumulative-progress-count *
T -sym-trunk *
U drh
Z 77af1e5e5bb5d81b67cd1fb30eb348ef
P ffda1d1e1c858abd02f0c07b906cfac5ad075498
R c37bc6770e2789d7f8851d61fd232055
U dan
Z a07b3b8a92ddc391359da9de406f8455
+1 -1
View File
@@ -1 +1 @@
7a62fc6abcfe1459123c09eae48976dadaa2d4b3
74ad80eb745c708bdbbbf24cbbbf50971e84182f
-6
View File
@@ -797,12 +797,6 @@ static const FuncDef statPushFuncdef = {
** The content to returned is determined by the parameter J
** which is one of the STAT_GET_xxxx values defined above.
**
** The stat_get(P,J) function is not available to generic SQL. It is
** inserted as part of a manually constructed bytecode program. (See
** the callStatGet() routine below.) It is guaranteed that the P
** parameter will always be a poiner to a Stat4Accum object, never a
** NULL.
**
** If neither STAT3 nor STAT4 are enabled, then J is always
** STAT_GET_STAT1 and is hence omitted and this routine becomes
** a one-parameter function, stat_get(P), that always returns the
+68 -88
View File
@@ -4038,12 +4038,7 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
sqlite3BtreeEnter(p);
if( op==SAVEPOINT_ROLLBACK ){
rc = saveAllCursors(pBt, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
}
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
if( rc==SQLITE_OK ){
if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
pBt->nPage = 0;
@@ -4429,6 +4424,7 @@ static int copyPayload(
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
** 2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -4436,13 +4432,13 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the current cursor entry uses one or more overflow pages
** this function may allocate space for and lazily populate
** the overflow page-list cache array (BtCursor.aOverflow).
** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily
** populates the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it must be
** Once an overflow page-list cache has been allocated, it may be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
@@ -4464,17 +4460,21 @@ static int accessPayload(
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
unsigned char * const pBufStart = pBuf;
int bEnd; /* True if reading to end of data */
#endif
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
#ifdef SQLITE_DIRECT_OVERFLOW_READ
bEnd = offset+amt==pCur->info.nPayload;
#endif
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
@@ -4493,7 +4493,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -4509,13 +4509,14 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
@@ -4530,25 +4531,29 @@ static int accessPayload(
}
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}else{
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( pCur->aOverflow[offset/ovflSize] ){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
}
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( (pCur->curFlags & BTCF_ValidOvfl)!=0
&& pCur->aOverflow[offset/ovflSize]
){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
assert( rc==SQLITE_OK && amt>0 );
while( nextPage ){
/* If required, populate the overflow page-list cache. */
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
pCur->aOverflow[iIdx] = nextPage;
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
pCur->aOverflow[iIdx] = nextPage;
}
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -4556,7 +4561,11 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
**
** Note that the aOverflow[] array must be allocated because eOp!=2
** here. If eOp==2, then offset==0 and this branch is never taken.
*/
assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
assert( pCur->pBtree->db==pBt->db );
if( pCur->aOverflow[iIdx+1] ){
@@ -4570,7 +4579,7 @@ static int accessPayload(
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
#ifdef SQLITE_DIRECT_OVERFLOW_READ
sqlite3_file *fd; /* File from which to do direct overflow read */
sqlite3_file *fd;
#endif
int a = amt;
if( a + offset > ovflSize ){
@@ -4582,25 +4591,27 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) there is no open write-transaction, and
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
** 6) at least 4 bytes have already been read into the output buffer
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
** 7) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( eOp==0 /* (1) */
if( (eOp&0x01)==0 /* (1) */
&& offset==0 /* (2) */
&& pBt->inTransaction==TRANS_READ /* (3) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
&& 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
&& &pBuf[-4]>=pBufStart /* (6) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
&& &pBuf[-4]>=pBufStart /* (7) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* due to (6) */
assert( aWrite>=pBufStart ); /* hence (7) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
@@ -4611,27 +4622,27 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
(eOp==0 ? PAGER_GET_READONLY : 0)
((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
}
amt -= a;
if( amt==0 ) return rc;
pBuf += a;
}
if( amt==0 ) break;
if( rc ) break;
iIdx++;
}
}
if( rc==SQLITE_OK && amt>0 ){
return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */
return SQLITE_CORRUPT_BKPT;
}
return rc;
}
@@ -4660,34 +4671,21 @@ int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
** This variant of sqlite3BtreePayload() works even if the cursor has not
** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
** interface.
*/
#ifndef SQLITE_OMIT_INCRBLOB
static SQLITE_NOINLINE int accessPayloadChecked(
BtCursor *pCur,
u32 offset,
u32 amt,
void *pBuf
){
int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
int rc;
if ( pCur->eState==CURSOR_INVALID ){
return SQLITE_ABORT;
}
assert( cursorOwnsBtShared(pCur) );
rc = btreeRestoreCursorPosition(pCur);
return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
}
int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
if( pCur->eState==CURSOR_VALID ){
assert( cursorOwnsBtShared(pCur) );
return accessPayload(pCur, offset, amt, pBuf, 0);
}else{
return accessPayloadChecked(pCur, offset, amt, pBuf);
rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
rc = accessPayload(pCur, offset, amt, pBuf, 0);
}
return rc;
}
#endif /* SQLITE_OMIT_INCRBLOB */
@@ -4776,7 +4774,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur, pCur->curPagerFlags);
}
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
@@ -5093,26 +5091,9 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
return SQLITE_OK;
}
if( pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
*pRes = -1;
return SQLITE_OK;
}
/* If the requested key is one more than the previous key, then
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this ase, only a little more slowely */
if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, pRes);
if( rc ) return rc;
if( *pRes==0 ){
getCellInfo(pCur);
if( pCur->info.nKey==intKey ){
return SQLITE_OK;
}
}
}
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
}
}
@@ -5248,8 +5229,7 @@ int sqlite3BtreeMovetoUnpacked(
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
pCur->curFlags &= ~BTCF_ValidOvfl;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -6163,7 +6143,7 @@ static int fillInCell(
** Use a call to btreeParseCellPtr() to verify that the values above
** were computed correctly.
*/
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
{
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
+4 -2
View File
@@ -692,9 +692,11 @@ struct IntegrityCk {
*/
#if SQLITE_BYTEORDER==4321
# define get2byteAligned(x) (*(u16*)(x))
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& GCC_VERSION>=4008000
# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& defined(_MSC_VER) && _MSC_VER>=1300
# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
#else
# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
+1 -1
View File
@@ -57,7 +57,7 @@ static const char * const azCompileOpt[] = {
#if SQLITE_COVERAGE_TEST
"COVERAGE_TEST",
#endif
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
"DEBUG",
#endif
#if SQLITE_DEFAULT_LOCKING_MODE
+1 -3
View File
@@ -715,9 +715,7 @@ void sqlite3GenerateRowDelete(
u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
if( pParse->nested==0 ){
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
}
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
if( eMode!=ONEPASS_OFF ){
sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
}
+31 -56
View File
@@ -231,7 +231,7 @@ static char comparisonAffinity(Expr *pExpr){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( aff==0 ){
}else if( NEVER(aff==0) ){
aff = SQLITE_AFF_BLOB;
}
return aff;
@@ -967,13 +967,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
i64 i;
int bOk;
if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
i = z[1]-'0'; /* The common case of ?N for a single digit N */
bOk = 1;
}else{
bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
}
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
x = (ynVar)i;
testcase( i==0 );
testcase( i==1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
@@ -983,7 +978,6 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
return;
}
x = (ynVar)i;
if( x>pParse->nVar ){
pParse->nVar = (int)x;
doAdd = 1;
@@ -1418,41 +1412,33 @@ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
}
return pNew;
}
Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
Select *pRet = 0;
Select *pNext = 0;
Select **pp = &pRet;
Select *p;
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
Select *pNew, *pPrior;
assert( db!=0 );
for(p=pDup; p; p=p->pPrior){
Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
if( pNew==0 ) break;
pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
pNew->op = p->op;
pNew->pNext = pNext;
pNew->pPrior = 0;
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
sqlite3SelectSetName(pNew, p->zSelName);
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
}
return pRet;
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
if( pNew==0 ) return 0;
pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
pNew->op = p->op;
pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = 0;
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
sqlite3SelectSetName(pNew, p->zSelName);
return pNew;
}
#else
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -2367,7 +2353,7 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
char *zRet;
assert( pExpr->op==TK_IN );
zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
zRet = sqlite3DbMallocZero(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
@@ -3272,7 +3258,7 @@ void sqlite3ExprCodeGetColumnToReg(
void sqlite3ExprCacheClear(Parse *pParse){
int i;
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("CLEAR\n");
}
@@ -4680,17 +4666,6 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
return 0;
}
/*
** Like sqlite3ExprCompare() except COLLATE operators at the top-level
** are ignored.
*/
int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
return sqlite3ExprCompare(
sqlite3ExprSkipCollate(pA),
sqlite3ExprSkipCollate(pB),
iTab);
}
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
+7 -40
View File
@@ -1527,9 +1527,6 @@ void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
VdbeComment((v, "for %s", pIdx->zName));
#ifdef SQLITE_ENABLE_NULL_TRIM
if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);
#endif
/* In an UPDATE operation, if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table and there has been no change the
@@ -1671,28 +1668,6 @@ void sqlite3GenerateConstraintChecks(
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
** to be the number of columns in table pTab that must not be NULL-trimmed.
**
** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
*/
void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
u16 i;
/* Records with omitted columns are only allowed for schema format
** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
if( pTab->pSchema->file_format<2 ) return;
for(i=pTab->nCol-1; i>0; i--){
if( pTab->aCol[i].pDflt!=0 ) break;
if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
}
sqlite3VdbeChangeP5(v, i+1);
}
#endif
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
@@ -1736,30 +1711,22 @@ void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
pik_flags = 0;
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( update_flags==0 ){
sqlite3VdbeAddOp4(v, OP_InsertInt,
iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
);
sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
}
#endif
}
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
sqlite3VdbeChangeP5(v, pik_flags);
}
if( !HasRowid(pTab) ) return;
regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
@@ -1979,7 +1946,7 @@ static int xferOptimization(
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pDest) ){
if( pDest->tabFlags & TF_Virtual ){
return 0; /* tab1 must not be a virtual table */
}
#endif
@@ -2041,7 +2008,7 @@ static int xferOptimization(
return 0; /* source and destination must both be WITHOUT ROWID or not */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pSrc) ){
if( pSrc->tabFlags & TF_Virtual ){
return 0; /* tab2 must not be a virtual table */
}
#endif
+1 -2
View File
@@ -73,7 +73,7 @@ int sqlite3_exec(
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
if( azCols==0 ){
goto exec_out;
}
@@ -94,7 +94,6 @@ int sqlite3_exec(
goto exec_out;
}
}
azVals[i] = 0;
}
if( xCallback(pArg, nCol, azVals, azCols) ){
/* EVIDENCE-OF: R-38229-40159 If the callback function to
+6 -14
View File
@@ -219,20 +219,12 @@ static void sqlite3MallocAlarm(int nByte){
*/
static void mallocWithAlarm(int n, void **pp){
void *p;
int nFull;
int nFull = 0;
assert( sqlite3_mutex_held(mem0.mutex) );
assert( n>0 );
/* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
** implementation of malloc_good_size(), which must be called in debug
** mode and specifically when the DMD "Dark Matter Detector" is enabled
** or else a crash results. Hence, do not attempt to optimize out the
** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
nFull = sqlite3GlobalConfig.m.xRoundup(n);
if( nUsed >= mem0.alarmThreshold - nFull ){
mem0.nearlyFull = 1;
sqlite3MallocAlarm(nFull);
@@ -240,11 +232,11 @@ static void mallocWithAlarm(int n, void **pp){
mem0.nearlyFull = 0;
}
}
p = sqlite3GlobalConfig.m.xMalloc(nFull);
p = sqlite3GlobalConfig.m.xMalloc(n);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( p==0 && mem0.alarmThreshold>0 ){
sqlite3MallocAlarm(nFull);
p = sqlite3GlobalConfig.m.xMalloc(nFull);
p = sqlite3GlobalConfig.m.xMalloc(n);
}
#endif
if( p ){
@@ -418,7 +410,7 @@ int sqlite3MallocSize(void *p){
int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -479,7 +471,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){
}
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
/* Trash all content in the buffer being freed */
memset(p, 0xaa, db->lookaside.sz);
#endif
+2 -4
View File
@@ -125,9 +125,7 @@ static malloc_zone_t* _sqliteZone_;
*/
static void *sqlite3MemMalloc(int nByte){
#ifdef SQLITE_MALLOCSIZE
void *p;
testcase( ROUND8(nByte)==nByte );
p = SQLITE_MALLOC( nByte );
void *p = SQLITE_MALLOC( nByte );
if( p==0 ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
@@ -136,7 +134,7 @@ static void *sqlite3MemMalloc(int nByte){
#else
sqlite3_int64 *p;
assert( nByte>0 );
testcase( ROUND8(nByte)!=nByte );
nByte = ROUND8(nByte);
p = SQLITE_MALLOC( nByte+8 );
if( p ){
p[0] = nByte;
+8 -7
View File
@@ -87,7 +87,8 @@ void sqlite3MemoryBarrier(void){
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
#elif MSVC_VERSION>=1300
#elif !defined(SQLITE_DISABLE_INTRINSIC) && \
defined(_MSC_VER) && _MSC_VER>=1300
_ReadWriteBarrier();
#elif defined(MemoryBarrier)
MemoryBarrier();
@@ -298,8 +299,8 @@ static void winMutexEnter(sqlite3_mutex *p){
p->owner = tid;
p->nRef++;
if( p->trace ){
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
tid, p->id, p, p->trace, p->nRef));
OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
tid, p, p->trace, p->nRef));
}
#endif
}
@@ -341,8 +342,8 @@ static int winMutexTry(sqlite3_mutex *p){
#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
}
#endif
return rc;
@@ -370,8 +371,8 @@ static void winMutexLeave(sqlite3_mutex *p){
LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ){
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
tid, p->id, p, p->trace, p->nRef));
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
tid, p, p->trace, p->nRef));
}
#endif
}
+7 -45
View File
@@ -352,34 +352,7 @@ struct winVfsAppData {
******************************************************************************
*/
#ifndef SQLITE_WIN32_HEAP_CREATE
# define SQLITE_WIN32_HEAP_CREATE (TRUE)
#endif
/*
* This is the maximum possible initial size of the Win32-specific heap, in
* bytes.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
#endif
/*
* This is the extra space for the initial size of the Win32-specific heap,
* in bytes. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
#endif
/*
* Calculate the maximum legal cache size, in pages, based on the maximum
* possible initial heap size and the default page size, setting aside the
* needed extra space.
*/
#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
(SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
(SQLITE_DEFAULT_PAGE_SIZE))
# define SQLITE_WIN32_HEAP_CREATE (TRUE)
#endif
/*
@@ -388,36 +361,25 @@ struct winVfsAppData {
*/
#ifndef SQLITE_WIN32_CACHE_SIZE
# if SQLITE_DEFAULT_CACHE_SIZE>=0
# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# else
# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# endif
#endif
/*
* Make sure that the calculated cache size, in pages, cannot cause the
* initial size of the Win32-specific heap to exceed the maximum amount
* of memory that can be specified in the call to HeapCreate.
*/
#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
# undef SQLITE_WIN32_CACHE_SIZE
# define SQLITE_WIN32_CACHE_SIZE (2000)
#endif
/*
* The initial size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
(SQLITE_DEFAULT_PAGE_SIZE) + \
(SQLITE_WIN32_HEAP_INIT_EXTRA))
# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
(SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
#endif
/*
* The maximum size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
#endif
/*
@@ -425,7 +387,7 @@ struct winVfsAppData {
* zero for the default behavior.
*/
#ifndef SQLITE_WIN32_HEAP_FLAGS
# define SQLITE_WIN32_HEAP_FLAGS (0)
# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif
+6 -12
View File
@@ -814,20 +814,14 @@ static const unsigned char aJournalMagic[] = {
#define isOpen(pFd) ((pFd)->pMethods!=0)
/*
** Return true if this pager uses a write-ahead log to read page pgno.
** Return false if the pager reads pgno directly from the database.
** Return true if this pager uses a write-ahead log instead of the usual
** rollback journal. Otherwise false.
*/
#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
u32 iRead = 0;
int rc;
if( pPager->pWal==0 ) return 0;
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
return rc || iRead;
}
#endif
#ifndef SQLITE_OMIT_WAL
# define pagerUseWal(x) ((x)->pWal!=0)
int sqlite3PagerUseWal(Pager *pPager){
return (pPager->pWal!=0);
}
# define pagerUseWal(x) sqlite3PagerUseWal(x)
#else
# define pagerUseWal(x) 0
# define pagerRollbackWal(x) 0
+2 -4
View File
@@ -178,16 +178,14 @@ int sqlite3PagerSharedLock(Pager *pPager);
int sqlite3PagerWalCallback(Pager *pPager);
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
# ifdef SQLITE_DIRECT_OVERFLOW_READ
int sqlite3PagerUseWal(Pager *pPager, Pgno);
# endif
int sqlite3PagerUseWal(Pager *pPager);
# ifdef SQLITE_ENABLE_SNAPSHOT
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
int sqlite3PagerSnapshotRecover(Pager *pPager);
# endif
#else
# define sqlite3PagerUseWal(x,y) 0
# define sqlite3PagerUseWal(x) 0
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
+1 -14
View File
@@ -65,19 +65,6 @@
*/
#define YYPARSEFREENEVERNULL 1
/*
** In the amalgamation, the parse.c file generated by lemon and the
** tokenize.c file are concatenated. In that case, sqlite3RunParser()
** has access to the the size of the yyParser object and so the parser
** engine can be allocated from stack. In that case, only the
** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
** omitted.
*/
#ifdef SQLITE_AMALGAMATION
# define sqlite3Parser_ENGINEALWAYSONSTACK 1
#endif
/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc(). The default is size_t.
@@ -1000,7 +987,7 @@ expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y).
{spanBinaryExpr(pParse,@OP,&A,&Y);}
expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);}
%type likeop {Token}
likeop(A) ::= LIKE_KW|MATCH(A).
likeop(A) ::= LIKE_KW|MATCH(X). {A=X;/*A-overwrites-X*/}
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A=X; A.n|=0x80000000; /*A-overwrite-X*/}
expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] {
ExprList *pList;
+1 -1
View File
@@ -104,7 +104,7 @@ struct PCache {
**
** assert( sqlite3PcachePageSanity(pPg) );
*/
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
int sqlite3PcachePageSanity(PgHdr *pPg){
PCache *pCache;
assert( pPg!=0 );
+1 -1
View File
@@ -279,7 +279,7 @@ const char *sqlite3JournalModename(int eMode){
** Locate a pragma in the aPragmaName[] array.
*/
static const PragmaName *pragmaLocate(const char *zName){
int upr, lwr, mid = 0, rc;
int upr, lwr, mid, rc;
lwr = 0;
upr = ArraySize(aPragmaName)-1;
while( lwr<=upr ){
+42 -55
View File
@@ -15,7 +15,7 @@
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX 0 /* non-decimal integer types. %x %o */
#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 1 /* Floating point. %f */
#define etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
@@ -33,9 +33,8 @@
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
#define etINVALID 17 /* Any unrecognized conversion type */
#define etINVALID 16 /* Any unrecognized conversion type */
/*
@@ -59,8 +58,8 @@ typedef struct et_info { /* Information about each format field */
/*
** Allowed values for et_info.flags
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinite precision */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinity precision */
/*
@@ -70,7 +69,7 @@ typedef struct et_info { /* Information about each format field */
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etDECIMAL, 0, 0 },
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
@@ -79,7 +78,7 @@ static const et_info fmtinfo[] = {
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etDECIMAL, 0, 0 },
{ 'u', 10, 0, etRADIX, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -88,7 +87,7 @@ static const et_info fmtinfo[] = {
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
{ 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'i', 10, 1, etRADIX, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
@@ -180,13 +179,14 @@ void sqlite3VXPrintf(
int idx; /* A general purpose loop counter */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
etByte cThousand; /* Thousands separator for %d and %u */
etByte xtype = etINVALID; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
@@ -229,18 +229,17 @@ void sqlite3VXPrintf(
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_prefix = cThousand =
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
case '+': flag_prefix = '+'; break;
case ' ': flag_prefix = ' '; break;
case '+': flag_plussign = 1; break;
case ' ': flag_blanksign = 1; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
case ',': cThousand = ','; break;
default: done = 1; break;
}
}while( !done && (c=(*++fmt))!=0 );
@@ -310,11 +309,13 @@ void sqlite3VXPrintf(
flag_long = 1;
c = *++fmt;
if( c=='l' ){
flag_long = 2;
flag_longlong = 1;
c = *++fmt;
}else{
flag_longlong = 0;
}
}else{
flag_long = 0;
flag_long = flag_longlong = 0;
}
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
@@ -332,11 +333,15 @@ void sqlite3VXPrintf(
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
** flag_prefix '+' or ' ' or zero
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long 1 for "l", 2 for "ll"
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
@@ -346,24 +351,19 @@ void sqlite3VXPrintf(
*/
switch( xtype ){
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
flag_longlong = sizeof(char*)==sizeof(i64);
flag_long = sizeof(char*)==sizeof(long int);
/* Fall through into the next case */
case etORDINAL:
case etRADIX:
cThousand = 0;
/* Fall through into the next case */
case etDECIMAL:
case etRADIX:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( bArgList ){
v = getIntArg(pArgList);
}else if( flag_longlong ){
v = va_arg(ap,i64);
}else if( flag_long ){
if( flag_long==2 ){
v = va_arg(ap,i64) ;
}else{
v = va_arg(ap,long int);
}
v = va_arg(ap,long int);
}else{
v = va_arg(ap,int);
}
@@ -376,17 +376,17 @@ void sqlite3VXPrintf(
prefix = '-';
}else{
longvalue = v;
prefix = flag_prefix;
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
}else{
if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
}else if( flag_longlong ){
longvalue = va_arg(ap,u64);
}else if( flag_long ){
if( flag_long==2 ){
longvalue = va_arg(ap,u64);
}else{
longvalue = va_arg(ap,unsigned long int);
}
longvalue = va_arg(ap,unsigned long int);
}else{
longvalue = va_arg(ap,unsigned int);
}
@@ -396,11 +396,11 @@ void sqlite3VXPrintf(
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
}
if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
if( precision<etBUFSIZE-10 ){
nOut = etBUFSIZE;
zOut = buf;
}else{
nOut = precision + 10 + precision/3;
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
@@ -426,23 +426,8 @@ void sqlite3VXPrintf(
}while( longvalue>0 );
}
length = (int)(&zOut[nOut-1]-bufpt);
while( precision>length ){
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
length++;
}
if( cThousand ){
int nn = (length - 1)/3; /* Number of "," to insert */
int ix = (length - 1)%3 + 1;
bufpt -= nn;
for(idx=0; nn>0; idx++){
bufpt[idx] = bufpt[idx+nn];
ix--;
if( ix==0 ){
bufpt[++idx] = cThousand;
nn--;
ix = 3;
}
}
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
@@ -469,7 +454,9 @@ void sqlite3VXPrintf(
realvalue = -realvalue;
prefix = '-';
}else{
prefix = flag_prefix;
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );
+10 -18
View File
@@ -4186,15 +4186,7 @@ static int withExpand(
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
if( bMayRecursive ){
Select *pPrior = pSel->pPrior;
assert( pPrior->pWith==0 );
pPrior->pWith = pSel->pWith;
sqlite3WalkSelect(pWalker, pPrior);
pPrior->pWith = 0;
}else{
sqlite3WalkSelect(pWalker, pSel);
}
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
pParse->pWith = pWith;
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
@@ -4238,12 +4230,10 @@ static int withExpand(
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( pParse->pWith && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
assert( pParse->pWith==pWith );
pParse->pWith = pWith->pOuter;
}
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
assert( pParse->pWith==pWith );
pParse->pWith = pWith->pOuter;
}
}
#else
@@ -4293,8 +4283,8 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
if( p->pWith ){
sqlite3WithPush(pParse, p->pWith, 0);
if( pWalker->xSelectCallback2==selectPopWith ){
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
}
/* Make sure cursor numbers have been assigned to all entries in
@@ -4581,7 +4571,9 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
w.xSelectCallback2 = selectPopWith;
if( (pSelect->selFlags & SF_MultiValue)==0 ){
w.xSelectCallback2 = selectPopWith;
}
sqlite3WalkSelect(&w, pSelect);
}
+21 -9
View File
@@ -614,6 +614,7 @@ struct ShellState {
int autoExplain; /* Automatically turn on .explain mode */
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
int statsOn; /* True to display memory stats before each finalize */
int vmstepsOn; /* Display VM steps before each finalize */
int scanstatsOn; /* True to display scan stats before each finalize */
int countChanges; /* True to display change counts */
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
@@ -1997,6 +1998,12 @@ static int shell_exec(
display_stats(db, pArg, 0);
}
if( pArg && pArg->vmstepsOn && pStmt ){
int iCur = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_VM_STEP, 0);
FILE *out = pArg->traceOut ? pArg->traceOut : pArg->out;
raw_printf(out, "VM steps: %d\n", iCur);
}
/* print loop-counters if required */
if( pArg && pArg->scanstatsOn ){
display_scanstats(db, pArg);
@@ -2212,7 +2219,7 @@ static char zHelp[] =
" html HTML <table> code\n"
" insert SQL insert statements for TABLE\n"
" line One value per line\n"
" list Values delimited by \"|\"\n"
" list Values delimited by .separator strings\n"
" quote Escape answers as for SQL\n"
" tabs Tab-separated values\n"
" tcl TCL list elements\n"
@@ -4288,20 +4295,15 @@ static int do_meta_command(char *zLine, ShellState *p){
int c2 = zMode[0];
if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
p->mode = MODE_Line;
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
p->mode = MODE_Column;
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
p->mode = MODE_Html;
}else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
p->mode = MODE_Tcl;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
@@ -4614,7 +4616,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
sqlite3SelectTrace = (int)integerValue(azArg[1]);
sqlite3SelectTrace = integerValue(azArg[1]);
}else
#endif
@@ -5192,7 +5194,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}
}else
#endif /* !defined(SQLITE_UNTESTABLE) */
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
open_db(p, 0);
@@ -5229,6 +5230,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
#endif
}else
#endif /* !defined(SQLITE_UNTESTABLE) */
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
@@ -5302,7 +5304,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
const char *zDbName = nArg==2 ? azArg[1] : "main";
sqlite3_vfs *pVfs = 0;
sqlite3_vfs *pVfs;
if( p->db ){
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
if( pVfs ){
@@ -5344,6 +5346,16 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='v' && strncmp(azArg[0], "vmsteps", n)==0 ){
if( nArg==2 ){
p->vmstepsOn = booleanValue(azArg[1]);
}else{
raw_printf(stderr, "Usage: .vmsteps ?on|off?\n");
rc = 1;
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
+14 -31
View File
@@ -576,7 +576,7 @@ int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicates that a file cannot be deleted when open. The
** flag indicate that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
@@ -726,9 +726,6 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_ATOMIC64K]
** <li> [SQLITE_IOCAP_SAFE_APPEND]
** <li> [SQLITE_IOCAP_SEQUENTIAL]
** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE]
** </ul>
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -5417,7 +5414,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
** is not invoked when conflicting rows are deleted because of an
** is not invoked when duplication rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
@@ -6199,12 +6196,6 @@ typedef struct sqlite3_blob sqlite3_blob;
** [database connection] error code and message accessible via
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
** A BLOB referenced by sqlite3_blob_open() may be read using the
** [sqlite3_blob_read()] interface and modified by using
** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
** different row of the same table using the [sqlite3_blob_reopen()]
** interface. However, the column, table, or database of a [BLOB handle]
** cannot be changed after the [BLOB handle] is opened.
**
** ^(If the row that a BLOB handle points to is modified by an
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
@@ -6228,10 +6219,6 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
**
** See also: [sqlite3_blob_close()],
** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
*/
int sqlite3_blob_open(
sqlite3*,
@@ -6247,11 +6234,11 @@ int sqlite3_blob_open(
** CAPI3REF: Move a BLOB Handle to a New Row
** METHOD: sqlite3_blob
**
** ^This function is used to move an existing [BLOB handle] so that it points
** ^This function is used to move an existing blob handle so that it points
** to a different row of the same database table. ^The new row is identified
** by the rowid value passed as the second argument. Only the row can be
** changed. ^The database, table and column on which the blob handle is open
** remain the same. Moving an existing [BLOB handle] to a new row is
** remain the same. Moving an existing blob handle to a new row can be
** faster than closing the existing handle and opening a new one.
**
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
@@ -8180,7 +8167,7 @@ int sqlite3_db_cacheflush(sqlite3*);
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
** on a database table.
** on a [rowid table].
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
@@ -8189,9 +8176,9 @@ int sqlite3_db_cacheflush(sqlite3*);
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
** ^The preupdate hook only fires for changes to real database tables; the
** preupdate hook is not invoked for changes to [virtual tables] or to
** system tables like sqlite_master or sqlite_stat1.
** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
** tables.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
@@ -8205,16 +8192,12 @@ int sqlite3_db_cacheflush(sqlite3*);
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
**
** For an UPDATE or DELETE operation on a [rowid table], the sixth
** parameter passed to the preupdate callback is the initial [rowid] of the
** row being modified or deleted. For an INSERT operation on a rowid table,
** or any operation on a WITHOUT ROWID table, the value of the sixth
** parameter is undefined. For an INSERT or UPDATE on a rowid table the
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
** INSERT operations on rowid tables.
** ^The sixth parameter to the preupdate callback is the initial [rowid] of the
** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is
** undefined for SQLITE_INSERT changes.
** ^The seventh parameter to the preupdate callback is the final [rowid] of
** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is
** undefined for SQLITE_DELETE changes.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
+31 -52
View File
@@ -103,28 +103,19 @@
# define _LARGEFILE_SOURCE 1
#endif
/* The GCC_VERSION and MSVC_VERSION macros are used to
** conditionally include optimizations for each of these compilers. A
** value of 0 means that compiler is not being used. The
** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
** optimizations, and hence set all compiler macros to 0
**
** There was once also a CLANG_VERSION macro. However, we learn that the
** version numbers in clang are for "marketing" only and are inconsistent
** and unreliable. Fortunately, all versions of clang also recognize the
** gcc version numbers and have reasonable settings for gcc version numbers,
** so the GCC_VERSION macro will be set to a correct non-zero value even
** when compiling with clang.
*/
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
/* What version of GCC is being used. 0 means GCC is not being used */
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif
#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
# define MSVC_VERSION _MSC_VER
/* What version of CLANG is being used. 0 means CLANG is not being used */
#if defined(__clang__) && !defined(_WIN32)
# define CLANG_VERSION \
(__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
#else
# define MSVC_VERSION 0
# define CLANG_VERSION 0
#endif
/* Needed for various definitions... */
@@ -256,7 +247,6 @@
# include <intrin.h>
# pragma intrinsic(_byteswap_ushort)
# pragma intrinsic(_byteswap_ulong)
# pragma intrinsic(_byteswap_uint64)
# pragma intrinsic(_ReadWriteBarrier)
# else
# include <cmnintrin.h>
@@ -797,35 +787,32 @@ typedef INT16_TYPE LogEst;
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
** at run-time.
*/
#ifndef SQLITE_BYTEORDER
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)
# define SQLITE_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__)
# define SQLITE_BYTEORDER 4321
# else
# define SQLITE_BYTEORDER 0
# endif
#endif
#if SQLITE_BYTEORDER==4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
#elif SQLITE_BYTEORDER==1234
defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 1234
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
#else
#endif
#if (defined(sparc) || defined(__ppc__)) \
&& !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
#endif
#if !defined(SQLITE_BYTEORDER)
# ifdef SQLITE_AMALGAMATION
const int sqlite3one = 1;
# else
extern const int sqlite3one;
# endif
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
@@ -1391,7 +1378,6 @@ struct sqlite3 {
int (*xProgress)(void *); /* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
unsigned nProgressOps; /* Number of opcodes for progress callback */
unsigned iProgressCnt; /* Current progress counter value */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVTrans; /* Allocated size of aVTrans */
@@ -1849,7 +1835,6 @@ struct Table {
/* ... also used as column name list in a VIEW */
int tnum; /* Root BTree page for this table */
u32 nTabRef; /* Number of pointers to this Table */
u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
@@ -1857,6 +1842,7 @@ struct Table {
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
#endif
u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
@@ -1884,7 +1870,7 @@ struct Table {
#define TF_Ephemeral 0x02 /* An ephemeral table */
#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
/* available for reuse: 0x10 */
#define TF_Virtual 0x10 /* Is a virtual table */
#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */
#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */
@@ -1896,7 +1882,7 @@ struct Table {
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
# define IsVirtual(X) ((X)->nModuleArg)
# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
#else
# define IsVirtual(X) 0
#endif
@@ -2441,7 +2427,7 @@ struct Expr {
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
char *zSpan; /* Original text of the expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
@@ -2606,7 +2592,7 @@ struct SrcList {
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
/* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -3071,7 +3057,9 @@ struct AuthContext {
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#endif
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
@@ -3764,7 +3752,6 @@ void sqlite3Vacuum(Parse*,Token*);
int sqlite3RunVacuum(char**, sqlite3*, int);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Expr*, Expr*, int);
int sqlite3ExprCompareSkip(Expr*, Expr*, int);
int sqlite3ExprListCompare(ExprList*, ExprList*, int);
int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
@@ -3803,11 +3790,6 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*);
#ifdef SQLITE_ENABLE_NULL_TRIM
void sqlite3SetMakeRecordP5(Vdbe*,Table*);
#else
# define sqlite3SetMakeRecordP5(A,B)
#endif
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
void sqlite3BeginWriteOperation(Parse*, int, int);
@@ -4086,10 +4068,8 @@ char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
/*
** The interface to the LEMON-generated parser
*/
#ifndef SQLITE_AMALGAMATION
void *sqlite3ParserAlloc(void*(*)(u64));
void sqlite3ParserFree(void*, void(*)(void*));
#endif
void *sqlite3ParserAlloc(void*(*)(u64));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
int sqlite3ParserStackPeak(void*);
@@ -4199,7 +4179,6 @@ const char *sqlite3JournalModename(int);
#define sqlite3FkDropTable(a,b,c)
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
#define sqlite3FkReferences(a) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(sqlite3 *, Table*);
+4
View File
@@ -3405,6 +3405,10 @@ static int SQLITE_TCLAPI DbMain(
}
zErrMsg = 0;
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
if( p==0 ){
Tcl_SetResult(interp, (char *)"malloc failed", TCL_STATIC);
return TCL_ERROR;
}
memset(p, 0, sizeof(*p));
zFile = Tcl_GetStringFromObj(objv[2], 0);
zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
+2 -2
View File
@@ -161,13 +161,13 @@ static CrashGlobal g = {0, 0, SQLITE_DEFAULT_SECTOR_SIZE, 0, 0};
static int sqlite3CrashTestEnable = 0;
static void *crash_malloc(int nByte){
return (void *)Tcl_AttemptAlloc((size_t)nByte);
return (void *)Tcl_Alloc((size_t)nByte);
}
static void crash_free(void *p){
Tcl_Free(p);
}
static void *crash_realloc(void *p, int n){
return (void *)Tcl_AttemptRealloc(p, (size_t)n);
return (void *)Tcl_Realloc(p, (size_t)n);
}
/*
+1 -5
View File
@@ -239,11 +239,7 @@ static int SQLITE_TCLAPI test_blob_read(
}
if( nByte>0 ){
zBuf = (unsigned char *)Tcl_AttemptAlloc(nByte);
if( zBuf==0 ){
Tcl_AppendResult(interp, "out of memory", 0);
return TCL_ERROR;
}
zBuf = (unsigned char *)Tcl_Alloc(nByte);
}
rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
if( rc==SQLITE_OK ){
+1 -1
View File
@@ -80,7 +80,7 @@ static int sqlite3DeleteUnlinkIfExists(const char *zFile, int *pbExists){
** Delete the database file identified by the string argument passed to this
** function. The string must contain a filename, not an SQLite URI.
*/
SQLITE_API int sqlite3_delete_database(
int sqlite3_delete_database(
const char *zFile /* File to delete */
){
char *zBuf; /* Buffer to sprintf() filenames to */
-12
View File
@@ -481,9 +481,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int lastTokenParsed = -1; /* type of the previous token */
sqlite3 *db = pParse->db; /* The database connection */
int mxSqlLen; /* Max length of an SQL string */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
unsigned char zSpace[sizeof(yyParser)]; /* Space for parser engine object */
#endif
assert( zSql!=0 );
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -495,16 +492,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
i = 0;
assert( pzErrMsg!=0 );
/* sqlite3ParserTrace(stdout, "parser: "); */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
pEngine = zSpace;
sqlite3ParserInit(pEngine);
#else
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
if( pEngine==0 ){
sqlite3OomFault(db);
return SQLITE_NOMEM_BKPT;
}
#endif
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
@@ -556,11 +548,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
);
sqlite3_mutex_leave(sqlite3MallocMutex());
#endif /* YYDEBUG */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
sqlite3ParserFinalize(pEngine);
#else
sqlite3ParserFree(pEngine, sqlite3_free);
#endif
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM_BKPT;
}
+1 -1
View File
@@ -392,7 +392,7 @@ void sqlite3Update(
** be deleted as a result of REPLACE conflict handling. Any of these
** things might disturb a cursor being used to scan through the table
** or index, causing a single-pass approach to malfunction. */
flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
flags = WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE;
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
+14 -7
View File
@@ -1140,11 +1140,13 @@ u32 sqlite3Get4byte(const u8 *p){
u32 x;
memcpy(&x,p,4);
return x;
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
u32 x;
memcpy(&x,p,4);
return __builtin_bswap32(x);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& defined(_MSC_VER) && _MSC_VER>=1300
u32 x;
memcpy(&x,p,4);
return _byteswap_ulong(x);
@@ -1156,10 +1158,12 @@ u32 sqlite3Get4byte(const u8 *p){
void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
u32 x = __builtin_bswap32(v);
memcpy(p,&x,4);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& defined(_MSC_VER) && _MSC_VER>=1300
u32 x = _byteswap_ulong(v);
memcpy(p,&x,4);
#else
@@ -1275,7 +1279,8 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
int sqlite3AddInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_add_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
@@ -1295,7 +1300,8 @@ int sqlite3AddInt64(i64 *pA, i64 iB){
#endif
}
int sqlite3SubInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_sub_overflow(*pA, iB, pA);
#else
testcase( iB==SMALLEST_INT64+1 );
@@ -1310,7 +1316,8 @@ int sqlite3SubInt64(i64 *pA, i64 iB){
#endif
}
int sqlite3MulInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_mul_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
+2 -19
View File
@@ -98,25 +98,8 @@ static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
*/
void sqlite3Vacuum(Parse *pParse, Token *pNm){
Vdbe *v = sqlite3GetVdbe(pParse);
int iDb = 0;
if( v==0 ) return;
if( pNm ){
#ifndef SQLITE_BUG_COMPATIBLE_20160819
/* Default behavior: Report an error if the argument to VACUUM is
** not recognized */
iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
if( iDb<0 ) return;
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
** The buggy behavior is required for binary compatibility with some
** legacy applications. */
iDb = sqlite3FindDb(pParse->db, pNm);
if( iDb<0 ) iDb = 0;
#endif
}
if( iDb!=1 ){
int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0;
if( v && (iDb>=2 || iDb==0) ){
sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
sqlite3VdbeUsesBtree(v, iDb);
}
+57 -47
View File
@@ -583,6 +583,8 @@ int sqlite3VdbeExec(
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
int *aPermute = 0; /* Permutation of columns for OP_Compare */
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
#endif
@@ -597,6 +599,7 @@ int sqlite3VdbeExec(
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
@@ -605,9 +608,7 @@ int sqlite3VdbeExec(
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
u32 iPrior;
if( p->pc==0 && db->nVdbeActive==1 ) db->iProgressCnt = 0;
iPrior = db->iProgressCnt;
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
assert( 0 < db->nProgressOps );
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
}
@@ -959,6 +960,26 @@ case OP_Halt: {
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
#ifdef SQLITE_TRACE_TRIGGER
if( (db->mTrace & SQLITE_TRACE_STMT) && aOp[0].p4.z ){
int nTotal = nVmStep - pFrame->nVmStep;
char *zTrace;
assert( nTotal>=0 );
assert( db->xTrace );
zTrace = sqlite3_mprintf("%.*s%s completed (VM steps: total=%d self=%d)",
p->nFrame, " :",
aOp[0].p4.z, nTotal, nVmStep - pFrame->nVmStepAdj
);
if( zTrace ){
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, 0, zTrace);
sqlite3_free(zTrace);
}
if( p->pFrame ){
p->pFrame->nVmStepAdj += nTotal;
}
}
#endif
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
/* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
@@ -1680,7 +1701,9 @@ case OP_Function: {
#endif
MemSetTypeFlag(pCtx->pOut, MEM_Null);
pCtx->fErrorOrAux = 0;
db->lastRowid = lastRowid;
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
lastRowid = db->lastRowid; /* Remember rowid changes made by xSFunc */
/* If the function returned an error, throw an exception */
if( pCtx->fErrorOrAux ){
@@ -2136,8 +2159,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next
** instruction. The permutation is stored in the P4 operand.
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
@@ -2149,8 +2172,7 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
assert( pOp->p4.ai );
assert( pOp[1].opcode==OP_Compare );
assert( pOp[1].p5 & OPFLAG_PERMUTE );
aPermute = pOp->p4.ai + 1;
break;
}
@@ -2183,24 +2205,15 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
int *aPermute; /* The permutation */
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
aPermute = 0;
}else{
assert( pOp>aOp );
assert( pOp[-1].opcode==OP_Permutation );
assert( pOp[-1].p4type==P4_INTARRAY );
aPermute = pOp[-1].p4.ai + 1;
assert( aPermute!=0 );
}
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
n = pOp->p3;
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
@@ -2226,6 +2239,7 @@ case OP_Compare: {
break;
}
}
aPermute = 0;
break;
}
@@ -2782,20 +2796,6 @@ case OP_MakeRecord: {
}while( zAffinity[0] );
}
#ifdef SQLITE_ENABLE_NULL_TRIM
/* NULLs can be safely trimmed from the end of the record, as long as
** as the schema format is 2 or more and none of the omitted columns
** have a non-NULL default value. Also, the record must be left with
** at least one field. If P5>0 then it will be one more than the
** index of the right-most column with a non-NULL default value */
if( pOp->p5 ){
while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
pLast--;
nField--;
}
}
#endif
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
@@ -4385,7 +4385,7 @@ case OP_InsertInt: {
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
REGISTER_TRACE(pOp->p2, pData);
@@ -4401,13 +4401,14 @@ case OP_InsertInt: {
}
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->isTable );
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
assert( HasRowid(pTab) );
op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
}else{
pTab = 0; /* Not needed. Silence a compiler warning. */
pTab = 0; /* Not needed. Silence a comiler warning. */
zDb = 0; /* Not needed. Silence a compiler warning. */
}
@@ -4419,11 +4420,10 @@ case OP_InsertInt: {
){
sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
}
if( pOp->p5 & OPFLAG_ISNOOP ) break;
#endif
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey;
if( pData->flags & MEM_Null ){
x.pData = 0;
x.nData = 0;
@@ -4532,11 +4532,8 @@ case OP_Delete: {
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
if( db->xPreUpdateCallback && pOp->p4.pTab ){
assert( !(opflags & OPFLAG_ISUPDATE)
|| HasRowid(pTab)==0
|| (aMem[pOp->p3].flags & MEM_Int)
);
if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){
assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
@@ -5871,11 +5868,15 @@ case OP_Program: { /* jump */
p->nFrame++;
pFrame->pParent = p->pFrame;
pFrame->lastRowid = db->lastRowid;
pFrame->lastRowid = lastRowid;
pFrame->nChange = p->nChange;
pFrame->nDbChange = p->db->nChange;
assert( pFrame->pAuxData==0 );
pFrame->pAuxData = p->pAuxData;
#ifdef SQLITE_TRACE_TRIGGER
pFrame->nVmStep = nVmStep;
pFrame->nVmStepAdj = nVmStep;
#endif
p->pAuxData = 0;
p->nChange = 0;
p->pFrame = pFrame;
@@ -6812,7 +6813,7 @@ case OP_VUpdate: {
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
db->lastRowid = lastRowid = rowid;
}
if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
if( pOp->p5==OE_Ignore ){
@@ -6911,6 +6912,17 @@ case OP_Init: { /* jump */
x(db->pTraceArg, z);
sqlite3_free(z);
}else
#endif
#ifdef SQLITE_TRACE_TRIGGER
if( p->pFrame ){
zTrace = sqlite3_mprintf("%.*s%s", p->nFrame-1,
" :", zTrace
);
if( zTrace ){
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
sqlite3_free(zTrace);
}
}else
#endif
{
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
@@ -7048,11 +7060,9 @@ abort_due_to_error:
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
db->lastRowid = lastRowid;
testcase( nVmStep>0 );
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
db->iProgressCnt += (int)nVmStep;
#endif
sqlite3VdbeLeave(p);
assert( rc!=SQLITE_OK || nExtraDelete==0
|| sqlite3_strlike("DELETE%",p->zSql,0)!=0
+3 -2
View File
@@ -41,7 +41,8 @@ typedef struct SubProgram SubProgram;
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
u8 notUsed1;
u8 p5; /* Fifth parameter is an unsigned character */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
@@ -193,7 +194,7 @@ void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+4 -1
View File
@@ -175,6 +175,10 @@ struct VdbeFrame {
int nChildCsr; /* Number of cursors for child frame */
int nChange; /* Statement changes (Vdbe.nChange) */
int nDbChange; /* Value of db->nChange */
#ifdef SQLITE_TRACE_TRIGGER
int nVmStep; /* Value of nVmStep at start of program */
int nVmStepAdj; /* Adjusted for nested programs */
#endif
};
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
@@ -434,7 +438,6 @@ struct PreUpdate {
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being upated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
};
/*
+16 -18
View File
@@ -1660,7 +1660,6 @@ static UnpackedRecord *vdbeUnpackRecord(
*/
int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
Mem *pMem;
int rc = SQLITE_OK;
/* Test that this call is being made from within an SQLITE_DELETE or
@@ -1669,9 +1668,6 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_old_out;
}
if( p->pPk ){
iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
@@ -1697,14 +1693,17 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
p->aRecord = aRec;
}
pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
}else if( iIdx>=p->pUnpacked->nField ){
if( iIdx>=p->pUnpacked->nField ){
*ppValue = (sqlite3_value *)columnNullValue();
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
if( pMem->flags & MEM_Int ){
sqlite3VdbeMemRealify(pMem);
}else{
Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
*ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
if( pMem->flags & MEM_Int ){
sqlite3VdbeMemRealify(pMem);
}
}
}
@@ -1757,9 +1756,6 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
@@ -1780,11 +1776,13 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
p->pNewUnpacked = pUnpack;
}
pMem = &pUnpack->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else if( iIdx>=pUnpack->nField ){
if( iIdx>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
}else{
pMem = &pUnpack->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}
}
}else{
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
+49 -53
View File
@@ -783,7 +783,7 @@ void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
assert( p->nOp>0 || p->db->mallocFailed );
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
}
@@ -2497,59 +2497,60 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
int i;
const int iSavepoint = p->iStatement-1;
assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
/* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
** is that an IO error may have occurred, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
*/
if( db->nStatement && p->iStatement ){
int i;
const int iSavepoint = p->iStatement-1;
for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
}
if( rc2==SQLITE_OK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
if( rc==SQLITE_OK ){
rc = rc2;
}
}
if( rc2==SQLITE_OK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
db->nStatement--;
p->iStatement = 0;
if( rc==SQLITE_OK ){
if( eOp==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
}
if( rc==SQLITE_OK ){
rc = rc2;
rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
}
}
}
db->nStatement--;
p->iStatement = 0;
if( rc==SQLITE_OK ){
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
db->nDeferredCons = p->nStmtDefCons;
db->nDeferredImmCons = p->nStmtDefImmCons;
}
if( rc==SQLITE_OK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
}
}
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
db->nDeferredImmCons = p->nStmtDefImmCons;
}
return rc;
}
int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
if( p->db->nStatement && p->iStatement ){
return vdbeCloseStatement(p, eOp);
}
return SQLITE_OK;
}
/*
** This function is called when a transaction opened by the database
@@ -3562,7 +3563,7 @@ void sqlite3VdbeRecordUnpack(
p->nField = u;
}
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
/*
** This function compares two index or table record keys in the same way
** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
@@ -3667,7 +3668,7 @@ debugCompareEnd:
}
#endif
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
/*
** Count the number of fields (a.k.a. columns) in the record given by
** pKey,nKey. The verify that this count is less than or equal to the
@@ -4584,10 +4585,10 @@ void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){
if( p ){
int i;
for(i=0; i<nField; i++){
for(i=0; i<p->nField; i++){
Mem *pMem = &p->aMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
@@ -4620,15 +4621,10 @@ void sqlite3VdbePreUpdateHook(
assert( db->pPreUpdate==0 );
memset(&preupdate, 0, sizeof(PreUpdate));
if( HasRowid(pTab)==0 ){
iKey1 = iKey2 = 0;
preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
if( op==SQLITE_UPDATE ){
iKey2 = v->aMem[iReg].u.i;
}else{
if( op==SQLITE_UPDATE ){
iKey2 = v->aMem[iReg].u.i;
}else{
iKey2 = iKey1;
}
iKey2 = iKey1;
}
assert( pCsr->nField==pTab->nCol
@@ -4651,8 +4647,8 @@ void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked);
vdbeFreeUnpacked(db, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.pNewUnpacked);
if( preupdate.aNew ){
int i;
for(i=0; i<pCsr->nField; i++){
+6 -9
View File
@@ -26,6 +26,7 @@ struct Incrblob {
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
u16 iCol; /* Table column this handle is open on */
u8 isPureKV; /* True if pTab is a pure key/value table */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
@@ -66,17 +67,12 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
** then back it up to the point where it does the OP_SeekRowid. This could
** have been down with an extra OP_Goto, but simply setting the program
** counter is faster. */
if( v->pc>3 ){
v->pc = 3;
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
}
if( v->pc>3 ) v->pc = 3;
rc = sqlite3_step(p->pStmt);
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
testcase( pC->nHdrParsed==p->iCol );
testcase( pC->nHdrParsed==p->iCol+1 );
u32 type = pC->aType[p->iCol];
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -322,6 +318,7 @@ int sqlite3_blob_open(
}
}
pBlob->isPureKV = (pTab->nCol==2 && pTab->iPKey==0);
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
+10 -8
View File
@@ -339,7 +339,8 @@ void sqlite3VtabBeginParse(
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
assert( pTable->nModuleArg==0 );
pTable->tabFlags |= TF_Virtual;
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, 0);
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
@@ -627,7 +628,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
int rc;
assert( pTab );
if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){
return SQLITE_OK;
}
@@ -697,7 +698,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
const char *zMod;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable );
/* Locate the required virtual table module */
zMod = pTab->azModuleArg[0];
@@ -751,7 +752,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
return SQLITE_MISUSE_BKPT;
}
pTab = pCtx->pTab;
assert( IsVirtual(pTab) );
assert( (pTab->tabFlags & TF_Virtual)!=0 );
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
if( pParse==0 ){
@@ -765,7 +766,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
&& pParse->pNewTable
&& !db->mallocFailed
&& !pParse->pNewTable->pSelect
&& !IsVirtual(pParse->pNewTable)
&& (pParse->pNewTable->tabFlags & TF_Virtual)==0
){
if( !pTab->aCol ){
Table *pNew = pParse->pNewTable;
@@ -1054,7 +1055,7 @@ FuncDef *sqlite3VtabOverloadFunction(
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
if( NEVER(pTab==0) ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
@@ -1149,7 +1150,8 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
pMod->pEpoTab = pTab;
pTab->nTabRef = 1;
pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 );
pTab->tabFlags |= TF_Virtual;
pTab->nModuleArg = 0;
pTab->iPKey = -1;
addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(db, pTab, 0);
@@ -1220,7 +1222,7 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){
if( !p ){
rc = SQLITE_MISUSE_BKPT;
}else{
assert( p->pTab==0 || IsVirtual(p->pTab) );
assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
p->pVTable->bConstraint = (u8)va_arg(ap, int);
}
break;
+9 -11
View File
@@ -209,8 +209,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
if( pTerm->leftCursor==iCur
&& pTerm->u.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
@@ -309,7 +308,6 @@ static WhereTerm *whereScanInit(
iColumn = pIdx->aiColumn[j];
if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
}else if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
@@ -4114,9 +4112,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
&& nRowEst
){
Bitmask notUsed;
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
if( rc==pWInfo->pResultSet->nExpr ){
if( rc==pWInfo->pDistinctSet->nExpr ){
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
}
@@ -4353,7 +4351,7 @@ WhereInfo *sqlite3WhereBegin(
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
@@ -4429,7 +4427,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->pOrderBy = pOrderBy;
pWInfo->pResultSet = pResultSet;
pWInfo->pDistinctSet = pDistinctSet;
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
@@ -4507,13 +4505,13 @@ WhereInfo *sqlite3WhereBegin(
if( db->mallocFailed ) goto whereBeginError;
if( wctrlFlags & WHERE_WANT_DISTINCT ){
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
/* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){
/* Try to ORDER BY the result set to make distinct processing easier */
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
pWInfo->pOrderBy = pResultSet;
pWInfo->pOrderBy = pDistinctSet;
}
}
@@ -4589,10 +4587,10 @@ WhereInfo *sqlite3WhereBegin(
#endif
/* Attempt to omit tables from the join that do not effect the result */
if( pWInfo->nLevel>=2
&& pResultSet!=0
&& pDistinctSet!=0
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
if( sWLB.pOrderBy ){
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
}
+1 -1
View File
@@ -411,7 +411,7 @@ struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
SrcList *pTabList; /* List of tables in the join */
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
ExprList *pDistinctSet; /* DISTINCT over all these values */
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
+3 -12
View File
@@ -1062,7 +1062,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
@@ -1104,11 +1103,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeComment((v, "init LEFT JOIN no-match flag"));
}
/* Compute a safe address to jump to if we discover that the table for
** this loop is empty and can never contribute content. */
for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
addrHalt = pWInfo->a[j].addrBrk;
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
@@ -1293,7 +1287,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
@@ -1597,10 +1591,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
(pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
&& (pWInfo->eOnePass==ONEPASS_SINGLE)
)){
if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
@@ -1939,7 +1930,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+10 -18
View File
@@ -213,6 +213,15 @@ static int isLikeOrGlob(
#endif
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
){
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
** be the name of an indexed column with TEXT affinity. */
return 0;
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
op = pRight->op;
@@ -229,23 +238,6 @@ static int isLikeOrGlob(
z = pRight->u.zToken;
}
if( z ){
/* If the RHS begins with a digit or a minus sign, then the LHS must
** be an ordinary column (not a virtual table column) with TEXT affinity.
** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
** even though "lhs LIKE rhs" is true. But if the RHS does not start
** with a digit or '-', then "lhs LIKE rhs" will always be false if
** the LHS is numeric and so the optimization still works.
*/
if( sqlite3Isdigit(z[0]) || z[0]=='-' ){
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
){
sqlite3ValueFree(pVal);
return 0;
}
}
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
@@ -874,7 +866,7 @@ static int exprMightBeIndexed(
if( pIdx->aColExpr==0 ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
*piCur = iCur;
*piColumn = XN_EXPR;
return 1;
+1 -1
View File
@@ -164,7 +164,7 @@ do_test corruptC-2.5 {
catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
catchsql {PRAGMA integrity_check}
} {0 {{*** in database main ***
On tree page 4 cell 19: Extends off end of page}}}
Page 4: btreeInitPage() returns error code 11}}}
# {0 {{*** in database main ***
# Corruption detected in cell 710 on page 4
+4 -4
View File
@@ -458,7 +458,7 @@ static void StrAppend(Str *p, const char *z){
sqlite3_uint64 nNew;
if( p->oomErr ) return;
nNew = p->nAlloc*2 + 100 + n;
zNew = sqlite3_realloc64(p->z, nNew);
zNew = sqlite3_realloc(p->z, nNew);
if( zNew==0 ){
sqlite3_free(p->z);
memset(p, 0, sizeof(*p));
@@ -468,7 +468,7 @@ static void StrAppend(Str *p, const char *z){
p->z = zNew;
p->nAlloc = nNew;
}
memcpy(p->z + p->n, z, (int)n);
memcpy(p->z + p->n, z, n);
p->n += n;
p->z[p->n] = 0;
}
@@ -647,7 +647,7 @@ static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
int main(int argc, char **argv){
int i; /* Loop counter */
int nDb = 0; /* Number of databases to fuzz */
char **azDb = 0; /* Names of the databases (limit: 20) */
const char **azDb = 0; /* Names of the databases (limit: 20) */
int verboseFlag = 0; /* True for extra output */
int noLookaside = 0; /* Disable lookaside if true */
int vdbeLimitFlag = 0; /* Stop after 100,000 VDBE ops */
@@ -660,7 +660,7 @@ int main(int argc, char **argv){
unsigned runFlags = 0; /* Flags passed to runSql */
for(i=1; i<argc; i++){
char *z = argv[i];
const char *z = argv[i];
if( z[0]!='-' ){
azDb = realloc(azDb, sizeof(azDb[0])*(nDb+1));
if( azDb==0 ) fatalError("out of memory");
-786
View File
@@ -1,786 +0,0 @@
/*
** 2017-02-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.
**
*************************************************************************
**
** This program implements an SQLite database self-verification utility.
** Usage:
**
** dbselftest DATABASE ...
**
** This program reads the "selftest" table in DATABASE, in rowid order,
** and runs each of the tests described there, reporting results at the
** end.
**
** The intent of this program is to have a set of test database files that
** can be run using future versions of SQLite in order to verify that
** legacy database files continue to be readable. In other words, the
** intent is to confirm that there have been no breaking changes in the
** file format. The program can also be used to verify that database files
** are fully compatible between different architectures.
**
** The selftest table looks like this:
**
** CREATE TABLE selftest (
** id INTEGER PRIMARY KEY, -- Run tests in ascending order
** op TEXT, -- "test", "regexp", "print", etc.
** cmdtxt TEXT, -- Usually the SQL to be run
** expected TEXT -- Expected results
** );
**
*/
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
static const char zHelp[] =
"Usage: dbselftest [OPTIONS] DBFILE ...\n"
"\n"
" --init Create the selftest table\n"
" -q Suppress most output. Errors only\n"
" -v Show extra output\n"
;
/******************************************************************************
** The following code from ext/misc/sha1.c
**
** Context for the SHA1 hash
*/
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
unsigned int state[5];
unsigned int count[2];
unsigned char buffer[64];
};
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
* GCC by itself only generates left rotates. Use right rotates if
* possible to be kinder to dinky implementations with iterative rotate
* instructions.
*/
#define SHA_ROT(op, x, k) \
({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)
#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
|(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
^block[(i+2)&15]^block[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
* determined at run-time.
*/
#define Rl0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
unsigned int qq[5]; /* a, b, c, d, e; */
static int one = 1;
unsigned int block[16];
memcpy(block, buffer, 64);
memcpy(qq,state,5*sizeof(unsigned int));
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
/* Copy p->state[] to working vars */
/*
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
*/
/* 4 rounds of 20 operations each. Loop unrolled. */
if( 1 == *(unsigned char*)&one ){
Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
}else{
Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
}
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
#undef a
#undef b
#undef c
#undef d
#undef e
}
/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
/* SHA1 initialization constants */
p->state[0] = 0x67452301;
p->state[1] = 0xEFCDAB89;
p->state[2] = 0x98BADCFE;
p->state[3] = 0x10325476;
p->state[4] = 0xC3D2E1F0;
p->count[0] = p->count[1] = 0;
}
/* Add new content to the SHA1 hash */
static void hash_step(
SHA1Context *p, /* Add content to this context */
const unsigned char *data, /* Data to be added */
unsigned int len /* Number of bytes in data */
){
unsigned int i, j;
j = p->count[0];
if( (p->count[0] += len << 3) < j ){
p->count[1] += (len>>29)+1;
}
j = (j >> 3) & 63;
if( (j + len) > 63 ){
(void)memcpy(&p->buffer[j], data, (i = 64-j));
SHA1Transform(p->state, p->buffer);
for(; i + 63 < len; i += 64){
SHA1Transform(p->state, &data[i]);
}
j = 0;
}else{
i = 0;
}
(void)memcpy(&p->buffer[j], &data[i], len - i);
}
/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
SHA1Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
hash_step(p, (unsigned char*)zBuf, n);
}
/* Add padding and compute the message digest. Render the
** message digest as lower-case hexadecimal and put it into
** zOut[]. zOut[] must be at least 41 bytes long. */
static void hash_finish(
SHA1Context *p, /* The SHA1 context to finish and render */
char *zOut /* Store hexadecimal hash here */
){
unsigned int i;
unsigned char finalcount[8];
unsigned char digest[20];
static const char zEncode[] = "0123456789abcdef";
for (i = 0; i < 8; i++){
finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
hash_step(p, (const unsigned char *)"\200", 1);
while ((p->count[0] & 504) != 448){
hash_step(p, (const unsigned char *)"\0", 1);
}
hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++){
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
for(i=0; i<20; i++){
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
zOut[i*2+1] = zEncode[digest[i] & 0xf];
}
zOut[i*2]= 0;
}
/*
** Implementation of the sha1(X) function.
**
** Return a lower-case hexadecimal rendering of the SHA1 hash of the
** argument X. If X is a BLOB, it is hashed as is. For all other
** types of input, X is converted into a UTF-8 string and the string
** is hash without the trailing 0x00 terminator. The hash of a NULL
** value is NULL.
*/
static void sha1Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA1Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
char zOut[44];
assert( argc==1 );
if( eType==SQLITE_NULL ) return;
hash_init(&cx);
if( eType==SQLITE_BLOB ){
hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
}else{
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/*
** Run a prepared statement and compute the SHA1 hash on the
** result rows.
*/
static void sha1RunStatement(SHA1Context *pCtx, sqlite3_stmt *pStmt){
int nCol = sqlite3_column_count(pStmt);
const char *z = sqlite3_sql(pStmt);
int n = (int)strlen(z);
hash_step_vformat(pCtx,"S%d:",n);
hash_step(pCtx,(unsigned char*)z,n);
/* Compute a hash over the result of the query */
while( SQLITE_ROW==sqlite3_step(pStmt) ){
int i;
hash_step(pCtx,(const unsigned char*)"R",1);
for(i=0; i<nCol; i++){
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_NULL: {
hash_step(pCtx, (const unsigned char*)"N",1);
break;
}
case SQLITE_INTEGER: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
memcpy(&u, &v, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'I';
hash_step(pCtx, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
double r = sqlite3_column_double(pStmt,i);
memcpy(&u, &r, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'F';
hash_step(pCtx,x,9);
break;
}
case SQLITE_TEXT: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_text(pStmt, i);
hash_step_vformat(pCtx,"T%d:",n2);
hash_step(pCtx, z2, n2);
break;
}
case SQLITE_BLOB: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
hash_step_vformat(pCtx,"B%d:",n2);
hash_step(pCtx, z2, n2);
break;
}
}
}
}
}
/*
** Run one or more statements of SQL. Compute a SHA1 hash of the output.
*/
static int sha1Exec(
sqlite3 *db, /* Run against this database connection */
const char *zSql, /* The SQL to be run */
char *zOut /* Store the SHA1 hash as hexadecimal in this buffer */
){
sqlite3_stmt *pStmt = 0; /* A prepared statement */
int rc; /* Result of an API call */
SHA1Context cx; /* The SHA1 hash context */
hash_init(&cx);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
sha1RunStatement(&cx, pStmt);
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
return SQLITE_OK;
}
/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs. Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/
static void sha1QueryFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
sqlite3_stmt *pStmt = 0;
int rc;
SHA1Context cx;
char zOut[44];
assert( argc==1 );
if( zSql==0 ) return;
hash_init(&cx);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
zSql, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
if( !sqlite3_stmt_readonly(pStmt) ){
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
sha1RunStatement(&cx, pStmt);
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/* End of ext/misc/sha1.c
******************************************************************************/
/* How much output to display */
#define VOLUME_MIN 0
#define VOLUME_OFF 0
#define VOLUME_ERROR_ONLY 1
#define VOLUME_LOW 2
#define VOLUME_ECHO 3
#define VOLUME_VERBOSE 4
#define VOLUME_MAX 4
/* A string accumulator
*/
typedef struct Str {
char *z; /* Accumulated text */
int n; /* Bytes of z[] used so far */
int nAlloc; /* Bytes allocated for z[] */
} Str;
/* Append text to the Str object
*/
static void strAppend(Str *p, const char *z){
int n = (int)strlen(z);
if( p->n+n >= p->nAlloc ){
p->nAlloc += p->n+n + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
if( z==0 ){
printf("Could not allocate %d bytes\n", p->nAlloc);
exit(1);
}
}
memcpy(p->z+p->n, z, n+1);
p->n += n;
}
/* This is an sqlite3_exec() callback that will capture all
** output in a Str.
**
** Columns are separated by ",". Rows are separated by "|".
*/
static int execCallback(void *pStr, int argc, char **argv, char **colv){
int i;
Str *p = (Str*)pStr;
if( p->n ) strAppend(p, "|");
for(i=0; i<argc; i++){
const char *z = (const char*)argv[i];
if( z==0 ) z = "NULL";
if( i>0 ) strAppend(p, ",");
strAppend(p, z);
}
return 0;
}
/*
** Run an SQL statement constructing using sqlite3_vmprintf().
** Return the number of errors.
*/
static int runSql(sqlite3 *db, const char *zFormat, ...){
char *zSql;
char *zErr = 0;
int rc;
int nErr = 0;
va_list ap;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ){
printf("Out of memory\n");
exit(1);
}
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc || zErr ){
printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, zErr);
nErr++;
}
sqlite3_free(zSql);
return nErr;
}
/*
** Generate a prepared statement using a formatted string.
*/
static sqlite3_stmt *prepareSql(sqlite3 *db, const char *zFormat, ...){
char *zSql;
int rc;
sqlite3_stmt *pStmt = 0;
va_list ap;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ){
printf("Out of memory\n");
exit(1);
}
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
pStmt = 0;
}
sqlite3_free(zSql);
return pStmt;
}
/*
** Construct the standard selftest configuration for the database.
*/
static int buildSelftestTable(sqlite3 *db){
int rc;
sqlite3_stmt *pStmt;
int tno = 110;
char *zSql;
char zHash[50];
rc = runSql(db,
"CREATE TABLE IF NOT EXISTS selftest(\n"
" tno INTEGER PRIMARY KEY, -- test number\n"
" op TEXT, -- what kind of test\n"
" sql TEXT, -- SQL text for the test\n"
" ans TEXT -- expected answer\n"
");"
"INSERT INTO selftest"
" VALUES(100,'memo','Hashes generated using --init',NULL);"
);
if( rc ) return 1;
tno = 110;
zSql = "SELECT type,name,tbl_name,sql FROM sqlite_master ORDER BY name";
sha1Exec(db, zSql, zHash);
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
tno += 10;
pStmt = prepareSql(db,
"SELECT lower(name) FROM sqlite_master"
" WHERE type='table' AND sql NOT GLOB 'CREATE VIRTUAL*'"
" AND name<>'selftest'"
" ORDER BY 1");
if( pStmt==0 ) return 1;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
zSql = sqlite3_mprintf("SELECT * FROM \"%w\" NOT INDEXED",
sqlite3_column_text(pStmt, 0));
if( zSql==0 ){
printf("Of of memory\n");
exit(1);
}
sha1Exec(db, zSql, zHash);
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
tno += 10;
sqlite3_free(zSql);
if( rc ) break;
}
sqlite3_finalize(pStmt);
if( rc ) return 1;
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'run','PRAGMA integrity_check','ok');", tno);
if( rc ) return 1;
return rc;
}
/*
** Return true if the named table exists
*/
static int tableExists(sqlite3 *db, const char *zTab){
return sqlite3_table_column_metadata(db, "main", zTab, 0, 0, 0, 0, 0, 0)
== SQLITE_OK;
}
/*
** Default selftest table content, for use when there is no selftest table
*/
static char *azDefaultTest[] = {
0, 0, 0, 0,
"0", "memo", "Missing SELFTEST table - default checks only", "",
"1", "run", "PRAGMA integrity_check", "ok"
};
int main(int argc, char **argv){
int eVolume = VOLUME_LOW; /* How much output to display */
const char **azDb = 0; /* Name of the database file */
int nDb = 0; /* Number of database files to check */
int doInit = 0; /* True if --init is present */
sqlite3 *db = 0; /* Open database connection */
int rc; /* Return code from API calls */
char *zErrMsg = 0; /* An error message return */
char **azTest; /* Content of the selftest table */
int nRow = 0, nCol = 0; /* Rows and columns in azTest[] */
int i; /* Loop counter */
int nErr = 0; /* Number of errors */
int iDb; /* Loop counter for databases */
Str str; /* Result accumulator */
int nTest = 0; /* Number of tests run */
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
if( z[1]=='-' ) z++;
if( strcmp(z, "-help")==0 ){
printf("%s", zHelp);
return 0;
}else
if( strcmp(z, "-init")==0 ){
doInit = 1;
}else
if( strcmp(z, "-a")==0 ){
if( eVolume>VOLUME_MIN) eVolume--;
}else
if( strcmp(z, "-v")==0 ){
if( eVolume<VOLUME_MAX) eVolume++;
}else
{
printf("unknown option: \"%s\"\nUse --help for more information\n",
argv[i]);
return 1;
}
}else{
nDb++;
azDb = sqlite3_realloc(azDb, nDb*sizeof(azDb[0]));
if( azDb==0 ){
printf("out of memory\n");
exit(1);
}
azDb[nDb-1] = argv[i];
}
}
if( nDb==0 ){
printf("No databases specified. Use --help for more info\n");
return 1;
}
if( eVolume>=VOLUME_LOW ){
printf("SQLite %s\n", sqlite3_sourceid());
}
memset(&str, 0, sizeof(str));
strAppend(&str, "\n");
for(iDb=0; iDb<nDb; iDb++, sqlite3_close(db)){
rc = sqlite3_open_v2(azDb[iDb], &db,
doInit ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY, 0);
if( rc ){
printf("Cannot open \"%s\": %s\n", azDb[iDb], sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
sha1Func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
sha1QueryFunc, 0, 0);
}
if( rc ){
printf("Initialization error: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
if( doInit && !tableExists(db, "selftest") ){
buildSelftestTable(db);
}
if( !tableExists(db, "selftest") ){
azTest = azDefaultTest;
nCol = 4;
nRow = 2;
}else{
rc = sqlite3_get_table(db,
"SELECT tno,op,sql,ans FROM selftest ORDER BY tno",
&azTest, &nRow, &nCol, &zErrMsg);
if( rc || zErrMsg ){
printf("Error querying selftest: %s\n", zErrMsg);
sqlite3_free_table(azTest);
continue;
}
}
for(i=1; i<=nRow; i++){
int tno = atoi(azTest[i*nCol]);
const char *zOp = azTest[i*nCol+1];
const char *zSql = azTest[i*nCol+2];
const char *zAns = azTest[i*nCol+3];
if( eVolume>=VOLUME_ECHO ){
char *zQuote = sqlite3_mprintf("%q", zSql);
printf("%d: %s %s\n", tno, zOp, zSql);
sqlite3_free(zQuote);
}
if( strcmp(zOp,"memo")==0 ){
if( eVolume>=VOLUME_LOW ){
printf("%s: %s\n", azDb[iDb], zSql);
}
}else
if( strcmp(zOp,"sha1")==0 ){
char zOut[44];
rc = sha1Exec(db, zSql, zOut);
nTest++;
if( eVolume>=VOLUME_VERBOSE ){
printf("Result: %s\n", zOut);
}
if( rc ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: error-code-%d: %s\n", tno, rc, sqlite3_errmsg(db));
}
}else if( strcmp(zAns,zOut)!=0 ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: Expected: [%s]\n", tno, zAns);
printf("%d: Got: [%s]\n", tno, zOut);
}
}
}else
if( strcmp(zOp,"run")==0 ){
str.n = 0;
str.z[0] = 0;
zErrMsg = 0;
rc = sqlite3_exec(db, zSql, execCallback, &str, &zErrMsg);
nTest++;
if( eVolume>=VOLUME_VERBOSE ){
printf("Result: %s\n", str.z);
}
if( rc || zErrMsg ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: error-code-%d: %s\n", tno, rc, zErrMsg);
}
sqlite3_free(zErrMsg);
}else if( strcmp(zAns,str.z)!=0 ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: Expected: [%s]\n", tno, zAns);
printf("%d: Got: [%s]\n", tno, str.z);
}
}
}else
{
printf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
return 1;
}
}
if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
}
if( eVolume>=VOLUME_LOW || (nErr>0 && eVolume>=VOLUME_ERROR_ONLY) ){
printf("%d errors out of %d tests on %d databases\n", nErr, nTest, nDb);
}
return nErr;
}
-50
View File
@@ -1,50 +0,0 @@
# 2017-02-15
#
# 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 to show that a join involving an empty table is very fast.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Build some test data
#
do_execsql_test emptytable-100 {
CREATE TABLE t1(a);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a) SELECT x FROM c;
CREATE TABLE empty(x);
SELECT count(*) FROM t1;
} {100}
# Interrupt queries after 1M cycles to prevent burning excess CPU
proc stopDb {args} {
db interrupt
}
db progress 1000000 {stopDb}
# Prior to the query planner optimization on 2017-02-15, this query would
# take a ridiculous amount of time. If that optimization stops working,
# the result here will be in interrupt for running too long.
#
do_catchsql_test emptytable-110 {
SELECT count(*) FROM t1, t1, t1, t1, t1, t1, empty;
} {0 0}
do_catchsql_test emptytable-120 {
SELECT count(*) FROM t1, t1 LEFT JOIN empty;
} {0 10000}
do_catchsql_test emptytable-121 {
SELECT count(*) FROM t1, t1 LEFT JOIN t1, empty;
} {0 0}
finish_test
+8 -8
View File
@@ -121,13 +121,13 @@ do_test exclusive2-1.1 {
execsql {
BEGIN;
CREATE TABLE t1(a, b);
INSERT INTO t1(a, b) VALUES(randstr(10, 400), 0);
INSERT INTO t1(a, b) VALUES(randstr(10, 400), 0);
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a) VALUES(randstr(10, 400));
INSERT INTO t1(a) VALUES(randstr(10, 400));
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
COMMIT;
SELECT count(*) FROM t1;
}
@@ -154,7 +154,7 @@ do_test exclusive2-1.4 {
} $::sig
do_test exclusive2-1.5 {
execsql {
UPDATE t1 SET b=a, a=0;
UPDATE t1 SET b=a, a=NULL;
} db2
expr {[t1sig db2] eq $::sig}
} 0
+2 -55
View File
@@ -849,62 +849,9 @@ do_preupdate_test 7.6.4 {
}
# No preupdate callbacks for modifying sqlite_master.
do_preupdate_test 8.1 { CREATE TABLE x1(x, y); } { }
do_preupdate_test 8.2 { ALTER TABLE x1 ADD COLUMN z } { }
do_preupdate_test 8.3 { ALTER TABLE x1 RENAME TO y1 } { }
do_preupdate_test 8.4 { CREATE INDEX y1x ON y1(x) } { }
do_preupdate_test 8.5 { CREATE VIEW v1 AS SELECT * FROM y1 } { }
do_preupdate_test 8.6 { DROP TABLE y1 } { }
#-------------------------------------------------------------------------
reset_db
db preupdate hook preupdate_hook
do_execsql_test 9.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 9.1 {
INSERT INTO t1 VALUES(456, NULL, NULL);
do_preupdate_test 8.1 {
CREATE TABLE x1(x, y);
} {
INSERT main t1 456 456 0 456 {} {}
}
do_execsql_test 9.2 {
ALTER TABLE t1 ADD COLUMN d;
}
do_preupdate_test 9.3 {
INSERT INTO t1(a, b, c) VALUES(457, NULL, NULL);
} {
INSERT main t1 457 457 0 457 {} {} {}
}
do_preupdate_test 9.4 {
DELETE FROM t1 WHERE a=456
} {
DELETE main t1 456 456 0 456 {} {} {}
}
do_preupdate_test 9.5 {
INSERT INTO t2 DEFAULT VALUES;
} {
INSERT main t2 1 1 0 {} 1
}
do_preupdate_test 9.6 {
INSERT INTO t1 DEFAULT VALUES;
} {
INSERT main t1 458 458 0 458 {} {} {}
}
do_execsql_test 10.0 {
CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 10.1 {
INSERT INTO t3 DEFAULT VALUES
} {
INSERT main t3 1 1 0 {} 1
}
do_execsql_test 10.2 { SELECT * FROM t3 } {{} 1}
do_preupdate_test 10.3 {
DELETE FROM t3 WHERE b=1
} {DELETE main t3 1 1 0 {} 1}
finish_test
-218
View File
@@ -1,218 +0,0 @@
# 2017 Jan 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# The tests in this file focus on the pre-update hook.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix hook2
ifcapable !preupdate {
finish_test
return
}
#-------------------------------------------------------------------------
proc do_preupdate_test {tn sql x} {
set X [list]
foreach elem $x {lappend X $elem}
uplevel do_test $tn [list "
set ::preupdate \[list\]
execsql { $sql }
set ::preupdate
"] [list $X]
}
proc preupdate_hook {args} {
set type [lindex $args 0]
eval lappend ::preupdate $args
if {$type != "INSERT"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
lappend ::preupdate [db preupdate old $i]
}
}
if {$type != "DELETE"} {
for {set i 0} {$i < [db preupdate count]} {incr i} {
set rc [catch { db preupdate new $i } v]
lappend ::preupdate $v
}
}
}
#-------------------------------------------------------------------------
# Simple tests - INSERT, UPDATE and DELETE on a WITHOUT ROWID table.
#
db preupdate hook preupdate_hook
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
}
do_preupdate_test 1.1 {
INSERT INTO t1 VALUES('one', 1);
} {
INSERT main t1 0 0 one 1
}
do_preupdate_test 1.2 {
UPDATE t1 SET b=2 WHERE a='one';
} {
UPDATE main t1 0 0 one 1 one 2
}
do_preupdate_test 1.3 {
DELETE FROM t1 WHERE a='one';
} {
DELETE main t1 0 0 one 2
}
#-------------------------------------------------------------------------
# Some more complex tests for the pre-update callback on WITHOUT ROWID
# tables.
#
# 2.1.1 - INSERT statement.
# 2.1.2 - INSERT INTO ... SELECT statement.
# 2.1.3 - REPLACE INTO ... (PK conflict)
# 2.1.4 - REPLACE INTO ... (other index conflicts)
# 2.1.5 - REPLACE INTO ... (both PK and other index conflicts)
#
# 2.2.1 - DELETE statement.
# 2.2.2 - DELETE statement that uses the truncate optimization.
#
# 2.3.1 - UPDATE statement.
# 2.3.2 - UPDATE statement that modifies the PK.
# 2.3.3 - UPDATE OR REPLACE ... (PK conflict).
# 2.3.4 - UPDATE OR REPLACE ... (other index conflicts)
# 2.3.4 - UPDATE OR REPLACE ... (both PK and other index conflicts)
#
do_execsql_test 2.0 {
CREATE TABLE t2(a DEFAULT 4, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
CREATE UNIQUE INDEX t2a ON t2(a);
}
do_preupdate_test 2.1.1 {
INSERT INTO t2(b, c) VALUES(1, 1);
} {
INSERT main t2 0 0 4 1 1
}
do_execsql_test 2.1.2.0 {
CREATE TABLE d1(a DEFAULT 4, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
CREATE UNIQUE INDEX d1a ON d1(a);
INSERT INTO d1 VALUES(1, 2, 3);
INSERT INTO d1 VALUES(11, 12, 13);
}
do_preupdate_test 2.1.2.1 {
INSERT INTO t2 SELECT * FROM d1;
} {
INSERT main t2 0 0 1 2 3
INSERT main t2 0 0 11 12 13
}
do_preupdate_test 2.1.2.2 {
INSERT INTO t2 SELECT a+20, b+20, c+20 FROM d1;
} {
INSERT main t2 0 0 21 22 23
INSERT main t2 0 0 31 32 33
}
do_execsql_test 2.1.2.3 {
SELECT * FROM t2 ORDER BY b, c;
} {
4 1 1
1 2 3
11 12 13
21 22 23
31 32 33
}
do_preupdate_test 2.1.3 {
REPLACE INTO t2 VALUES(45, 22, 23);
} {
DELETE main t2 0 0 21 22 23
INSERT main t2 0 0 45 22 23
}
do_preupdate_test 2.1.4 {
REPLACE INTO t2 VALUES(11, 100, 100);
} {
DELETE main t2 0 0 11 12 13
INSERT main t2 0 0 11 100 100
}
do_preupdate_test 2.1.5 {
REPLACE INTO t2(c, b) VALUES(33, 32)
} {
DELETE main t2 0 0 4 1 1
DELETE main t2 0 0 31 32 33
INSERT main t2 0 0 4 32 33
}
do_execsql_test 2.2.0 {
SELECT * FROM t2 ORDER BY b,c;
} {
1 2 3
45 22 23
4 32 33
11 100 100
}
do_preupdate_test 2.2.1 {
DELETE FROM t2 WHERE b=22;
} {
DELETE main t2 0 0 45 22 23
}
do_preupdate_test 2.2.2 {
DELETE FROM t2;
} {
DELETE main t2 0 0 1 2 3
DELETE main t2 0 0 4 32 33
DELETE main t2 0 0 11 100 100
}
do_execsql_test 2.3.0 {
CREATE TABLE t3(x, y PRIMARY KEY, z UNIQUE) WITHOUT ROWID;
INSERT INTO t3 VALUES('a', 'b', 'c');
INSERT INTO t3 VALUES('d', 'e', 'f');
INSERT INTO t3 VALUES(1, 1, 1);
INSERT INTO t3 VALUES(2, 2, 2);
INSERT INTO t3 VALUES(3, 3, 3);
}
do_preupdate_test 2.3.1 {
UPDATE t3 SET x=4 WHERE y IN ('b', 'e', 'x');
} {
UPDATE main t3 0 0 a b c 4 b c
UPDATE main t3 0 0 d e f 4 e f
}
do_preupdate_test 2.3.2 {
UPDATE t3 SET y=y||y WHERE z IN('c', 'f');
} {
UPDATE main t3 0 0 4 b c 4 bb c
UPDATE main t3 0 0 4 e f 4 ee f
}
do_preupdate_test 2.3.3 {
UPDATE OR REPLACE t3 SET y='bb' WHERE z='f'
} {
DELETE main t3 0 0 4 bb c
UPDATE main t3 0 0 4 ee f 4 bb f
}
do_preupdate_test 2.3.4 {
UPDATE OR REPLACE t3 SET z=2 WHERE y=1;
} {
DELETE main t3 0 0 2 2 2
UPDATE main t3 0 0 1 1 1 1 1 2
}
do_preupdate_test 2.3.5 {
UPDATE OR REPLACE t3 SET z=2, y='bb' WHERE y=3;
} {
DELETE main t3 0 0 1 1 2
DELETE main t3 0 0 4 bb f
UPDATE main t3 0 0 3 3 3 3 bb 2
}
finish_test
+1 -1
View File
@@ -52,7 +52,7 @@ do_faultsim_test 2 -prep {
error [sqlite3_errmsg db]
}
} -test {
faultsim_test_result {1 {no such rowid: -1}} {1 {disk I/O error}}
faultsim_test_result {1 {no such rowid: -1}}
close $::blob
}
-10
View File
@@ -370,14 +370,4 @@ do_execsql_test indexexpr1-1200.4 {
0 0 0 2 0 4 2 0 2 2 4 0
}
# Ticket https://www.sqlite.org/src/tktview/eb703ba7b50c1a
# Incorrect result using an index on an expression with a collating function
#
do_execsql_test indexexpr1-1300.1 {
CREATE TABLE t1300(a INTEGER PRIMARY KEY, b);
INSERT INTO t1300 VALUES(1,'coffee'),(2,'COFFEE'),(3,'stress'),(4,'STRESS');
CREATE INDEX t1300bexpr ON t1300( substr(b,4) );
SELECT a FROM t1300 WHERE substr(b,4)='ess' COLLATE nocase ORDER BY +a;
} {3 4}
finish_test
+30 -198
View File
@@ -67,35 +67,27 @@ static const char zHelp[] =
"\n"
" Generate a new test database file named DBFILE containing N\n"
" BLOBs each of size M bytes. The page size of the new database\n"
" file will be X. Additional options:\n"
"\n"
" --variance V Randomly vary M by plus or minus V\n"
" file will be X\n"
"\n"
" kvtest export DBFILE DIRECTORY\n"
"\n"
" Export all the blobs in the kv table of DBFILE into separate\n"
" files in DIRECTORY.\n"
"\n"
" kvtest stat DBFILE\n"
"\n"
" Display summary information about DBFILE\n"
"\n"
" kvtest run DBFILE [options]\n"
"\n"
" Run a performance test. DBFILE can be either the name of a\n"
" database or a directory containing sample files. Options:\n"
"\n"
" --asc Read blobs in ascending order\n"
" --blob-api Use the BLOB API\n"
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --max-id N Maximum blob key to use\n"
" --mmap N Mmap as much as N bytes of DBFILE\n"
" --jmode MODE Set MODE journal mode prior to starting\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
" --stats Output operating stats before exiting\n"
" --asc Read blobs in ascending order\n"
" --blob-api Use the BLOB API\n"
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --max-id N Maximum blob key to use\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
" --stats Output operating stats before exiting\n"
;
/* Reference resources used */
@@ -140,64 +132,6 @@ static void fatalError(const char *zFormat, ...){
exit(1);
}
/*
** 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){
int 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( zArg[0]>='0' && zArg[0]<='9' ){
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;
}
}
return isNeg? -v : v;
}
/*
** Check the filesystem object zPath. Determine what it is:
**
@@ -257,7 +191,6 @@ static int initMain(int argc, char **argv){
int i, rc;
int nCount = 1000;
int sz = 10000;
int iVariance = 0;
int pgsz = 4096;
sqlite3 *db;
char *zSql;
@@ -272,24 +205,19 @@ static int initMain(int argc, char **argv){
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = integerValue(argv[++i]);
nCount = atoi(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
sz = integerValue(argv[++i]);
sz = atoi(argv[++i]);
if( sz<1 ) fatalError("the --size must be positive");
continue;
}
if( strcmp(z, "-variance")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iVariance = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-pagesize")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
pgsz = integerValue(argv[++i]);
pgsz = atoi(argv[++i]);
if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
fatalError("the --pagesize must be power of 2 between 512 and 65536");
}
@@ -308,9 +236,9 @@ static int initMain(int argc, char **argv){
"BEGIN;\n"
"CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);\n"
"WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<%d)"
" INSERT INTO kv(k,v) SELECT x, randomblob(%d+(random()%%(%d))) FROM c;\n"
" INSERT INTO kv(k,v) SELECT x, randomblob(%d) FROM c;\n"
"COMMIT;\n",
pgsz, nCount, sz, iVariance+1
pgsz, nCount, sz
);
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
if( rc ) fatalError("database create failed: %s", zErrMsg);
@@ -319,65 +247,6 @@ static int initMain(int argc, char **argv){
return 0;
}
/*
** Analyze an existing database file. Report its content.
*/
static int statMain(int argc, char **argv){
char *zDb;
int i, rc;
sqlite3 *db;
char *zSql;
sqlite3_stmt *pStmt;
assert( strcmp(argv[1],"stat")==0 );
assert( argc>=3 );
zDb = argv[2];
for(i=3; i<argc; i++){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
fatalError("unknown option: \"%s\"", argv[i]);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf(
"SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
" FROM kv"
);
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Number of entries: %8d\n", sqlite3_column_int(pStmt, 0));
printf("Average value size: %8d\n", sqlite3_column_int(pStmt, 3));
printf("Minimum value size: %8d\n", sqlite3_column_int(pStmt, 1));
printf("Maximum value size: %8d\n", sqlite3_column_int(pStmt, 2));
}else{
printf("No rows\n");
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("PRAGMA page_size");
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Page-size: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("PRAGMA page_count");
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Page-count: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
return 0;
}
/*
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
** is written into file X. The number of bytes written is returned. Or
@@ -473,13 +342,13 @@ static unsigned char *readFile(const char *zName, int *pnByte){
if( in==0 ) return 0;
pBuf = sqlite3_malloc64( nIn );
if( pBuf==0 ) return 0;
nRead = fread(pBuf, (size_t)nIn, 1, in);
nRead = fread(pBuf, nIn, 1, in);
fclose(in);
if( nRead!=1 ){
sqlite3_free(pBuf);
return 0;
}
if( pnByte ) *pnByte = (int)nIn;
if( pnByte ) *pnByte = nIn;
return pBuf;
}
@@ -611,6 +480,9 @@ static int display_stats(
displayLinuxIoStats(out);
#endif
/* Do not remove this machine readable comment: extra-stats-output-here */
fprintf(out, "\n");
return 0;
}
@@ -619,7 +491,6 @@ static int display_stats(
#define ORDER_DESC 2
#define ORDER_RANDOM 3
/*
** Run a performance test
*/
@@ -631,7 +502,7 @@ static int runMain(int argc, char **argv){
int nCount = 1000; /* Number of blob fetch operations */
int nExtra = 0; /* Extra cycles */
int iKey = 1; /* Next blob key */
int iMax = 0; /* Largest allowed key */
int iMax = 1000; /* Largest allowed key */
int iPagesize = 0; /* Database page size */
int iCache = 1000; /* Database cache size in kibibytes */
int bBlobApi = 0; /* Use the incremental blob I/O API */
@@ -642,12 +513,10 @@ static int runMain(int argc, char **argv){
sqlite3_blob *pBlob = 0; /* Handle for incremental Blob I/O */
sqlite3_int64 tmStart; /* Start time */
sqlite3_int64 tmElapsed; /* Elapsed time */
int mmapSize = 0; /* --mmap N argument */
int nData = 0; /* Bytes of data */
sqlite3_int64 nTotal = 0; /* Total data read */
unsigned char *pData = 0; /* Content of the blob */
unsigned char *pData; /* Content of the blob */
int nAlloc = 0; /* Space allocated for pData[] */
const char *zJMode = 0; /* Journal mode */
assert( strcmp(argv[1],"run")==0 );
@@ -662,35 +531,25 @@ static int runMain(int argc, char **argv){
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = integerValue(argv[++i]);
nCount = atoi(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-mmap")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
mmapSize = integerValue(argv[++i]);
if( nCount<0 ) fatalError("the --mmap must be non-negative");
continue;
}
if( strcmp(z, "-max-id")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iMax = integerValue(argv[++i]);
iMax = atoi(argv[++i]);
if( iMax<1 ) fatalError("the --max-id must be positive");
continue;
}
if( strcmp(z, "-start")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iKey = integerValue(argv[++i]);
iKey = atoi(argv[++i]);
if( iKey<1 ) fatalError("the --start must be positive");
continue;
}
if( strcmp(z, "-cache-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iCache = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-jmode")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
zJMode = argv[++i];
iCache = atoi(argv[++i]);
continue;
}
if( strcmp(z, "-random")==0 ){
@@ -722,8 +581,6 @@ static int runMain(int argc, char **argv){
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf("PRAGMA mmap_size=%d", mmapSize);
sqlite3_exec(db, zSql, 0, 0, 0);
zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
@@ -741,29 +598,8 @@ static int runMain(int argc, char **argv){
}
sqlite3_finalize(pStmt);
pStmt = 0;
if( zJMode ){
zSql = sqlite3_mprintf("PRAGMA journal_mode=%Q", zJMode);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
sqlite3_prepare_v2(db, "PRAGMA journal_mode", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
zJMode = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
}else{
zJMode = "???";
}
sqlite3_finalize(pStmt);
if( iMax<=0 ){
sqlite3_prepare_v2(db, "SELECT max(k) FROM kv", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
iMax = sqlite3_column_int(pStmt, 0);
}
sqlite3_finalize(pStmt);
}
pStmt = 0;
sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
if( iMax<=0 ) iMax = 1000;
for(i=0; i<nCount; i++){
if( eType==PATH_DIR ){
/* CASE 1: Reading blobs out of separate files */
@@ -844,15 +680,14 @@ static int runMain(int argc, char **argv){
printf("SQLite version: %s\n", sqlite3_libversion());
}
printf("--count %d --max-id %d", nCount-nExtra, iMax);
if( eType==PATH_DB ){
printf(" --cache-size %d", iCache);
}
switch( eOrder ){
case ORDER_RANDOM: printf(" --random\n"); break;
case ORDER_DESC: printf(" --desc\n"); break;
default: printf(" --asc\n"); break;
}
if( eType==PATH_DB ){
printf("--cache-size %d --jmode %s\n", iCache, zJMode);
printf("--mmap %d%s\n", mmapSize, bBlobApi ? " --blob-api" : "");
}
if( iPagesize ) printf("Database page size: %d\n", iPagesize);
printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
@@ -872,9 +707,6 @@ int main(int argc, char **argv){
if( strcmp(argv[1],"run")==0 ){
return runMain(argc, argv);
}
if( strcmp(argv[1],"stat")==0 ){
return statMain(argc, argv);
}
showHelp();
return 0;
}
+2 -2
View File
@@ -236,12 +236,12 @@ do_test malloc5-4.2 {
db eval {PRAGMA cache_size=1}
db cache flush
sqlite3_release_memory
sqlite3_soft_heap_limit 200000
sqlite3_soft_heap_limit 100000
sqlite3_memory_highwater 1
execsql {SELECT * FROM abc}
set nMaxBytes [sqlite3_memory_highwater 1]
puts -nonewline " (Highwater mark: $nMaxBytes) "
expr $nMaxBytes <= 210000
expr $nMaxBytes <= 110000
} {1}
do_test malloc5-4.3 {
# Check that the content of table abc is at least roughly as expected.
-4
View File
@@ -754,10 +754,6 @@ test_suite "inmemory_journal" -description {
# This test assumes a journal file is created on disk.
delete_db.test
# This test depends on a successful recovery from the pager error
# state. Which is not possible with an in-memory journal
fts5fault1.test
}]
ifcapable mem3 {
-31
View File
@@ -116,37 +116,6 @@ do_execsql_test printf2-3.5 {
SELECT printf('|%7.8c|%-7.8c|','*','*');
} {|********|********|}
# The "," separator
do_execsql_test printf2-4.1 {
SELECT printf('|%,d|%,d|',0,-1);
} {|0|-1|}
do_execsql_test printf2-4.2 {
SELECT printf('|%,d|%,d|',12,-12);
} {|12|-12|}
do_execsql_test printf2-4.3 {
SELECT printf('|%,d|%,d|',123,-123);
} {|123|-123|}
do_execsql_test printf2-4.4 {
SELECT printf('|%,d|%,d|',1234,-1234);
} {|1,234|-1,234|}
do_execsql_test printf2-4.5 {
SELECT printf('|%,d|%,d|',12345,-12345);
} {|12,345|-12,345|}
do_execsql_test printf2-4.6 {
SELECT printf('|%,d|%,d|',123456,-123456);
} {|123,456|-123,456|}
do_execsql_test printf2-4.7 {
SELECT printf('|%,d|%,d|',1234567,-1234567);
} {|1,234,567|-1,234,567|}
do_execsql_test printf2-4.8 {
SELECT printf('|%,d|%,d|',12345678,-12345678);
} {|12,345,678|-12,345,678|}
do_execsql_test printf2-4.9 {
SELECT printf('|%,d|%,d|',123456789,-123456789);
} {|123,456,789|-123,456,789|}
do_execsql_test printf2-4.10 {
SELECT printf('|%,d|%,d|',1234567890,-1234567890);
} {|1,234,567,890|-1,234,567,890|}
+1 -272
View File
@@ -33,7 +33,7 @@ static const char zHelp[] =
" --size N Relative test size. Default=100\n"
" --stats Show statistics at the end\n"
" --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n"
" --testset T Run test-set T (main, cte, rtree, orm, debug)\n"
" --testset T Run test-set T\n"
" --trace Turn on SQL tracing\n"
" --threads N Use up to N threads for sorting\n"
" --utf16be Set text encoding to UTF-16BE\n"
@@ -1307,275 +1307,6 @@ void testset_rtree(int p1, int p2){
}
#endif /* SQLITE_ENABLE_RTREE */
/*
** A testset that does key/value storage on tables with many columns.
** This is the kind of workload generated by ORMs such as CoreData.
*/
void testset_orm(void){
unsigned i, j, n;
unsigned nRow;
unsigned x1, len;
char zNum[2000]; /* A number name */
static const char zType[] = /* Types for all non-PK columns, in order */
"IBBIIITIVVITBTBFBFITTFBTBVBVIFTBBFITFFVBIFIVBVVVBTVTIBBFFIVIBTB"
"TVTTFTVTVFFIITIFBITFTTFFFVBIIBTTITFTFFVVVFIIITVBBVFFTVVB";
nRow = n = g.szTest*250;
speedtest1_begin_test(100, "Fill %d rows", n);
speedtest1_exec(
"BEGIN;"
"CREATE TABLE ZLOOKSLIKECOREDATA ("
" ZPK INTEGER PRIMARY KEY,"
" ZTERMFITTINGHOUSINGCOMMAND INTEGER,"
" ZBRIEFGOBYDODGERHEIGHT BLOB,"
" ZCAPABLETRIPDOORALMOND BLOB,"
" ZDEPOSITPAIRCOLLEGECOMET INTEGER,"
" ZFRAMEENTERSIMPLEMOUTH INTEGER,"
" ZHOPEFULGATEHOLECHALK INTEGER,"
" ZSLEEPYUSERGRANDBOWL TIMESTAMP,"
" ZDEWPEACHCAREERCELERY INTEGER,"
" ZHANGERLITHIUMDINNERMEET VARCHAR,"
" ZCLUBRELEASELIZARDADVICE VARCHAR,"
" ZCHARGECLICKHUMANEHIRE INTEGER,"
" ZFINGERDUEPIZZAOPTION TIMESTAMP,"
" ZFLYINGDOCTORTABLEMELODY BLOB,"
" ZLONGFINLEAVEIMAGEOIL TIMESTAMP,"
" ZFAMILYVISUALOWNERMATTER BLOB,"
" ZGOLDYOUNGINITIALNOSE FLOAT,"
" ZCAUSESALAMITERMCYAN BLOB,"
" ZSPREADMOTORBISCUITBACON FLOAT,"
" ZGIFTICEFISHGLUEHAIR INTEGER,"
" ZNOTICEPEARPOLICYJUICE TIMESTAMP,"
" ZBANKBUFFALORECOVERORBIT TIMESTAMP,"
" ZLONGDIETESSAYNATURE FLOAT,"
" ZACTIONRANGEELEGANTNEUTRON BLOB,"
" ZCADETBRIGHTPLANETBANK TIMESTAMP,"
" ZAIRFORGIVEHEADFROG BLOB,"
" ZSHARKJUSTFRUITMOVIE VARCHAR,"
" ZFARMERMORNINGMIRRORCONCERN BLOB,"
" ZWOODPOETRYCOBBLERBENCH VARCHAR,"
" ZHAFNIUMSCRIPTSALADMOTOR INTEGER,"
" ZPROBLEMCLUBPOPOVERJELLY FLOAT,"
" ZEIGHTLEADERWORKERMOST TIMESTAMP,"
" ZGLASSRESERVEBARIUMMEAL BLOB,"
" ZCLAMBITARUGULAFAJITA BLOB,"
" ZDECADEJOYOUSWAVEHABIT FLOAT,"
" ZCOMPANYSUMMERFIBERELF INTEGER,"
" ZTREATTESTQUILLCHARGE TIMESTAMP,"
" ZBROWBALANCEKEYCHOWDER FLOAT,"
" ZPEACHCOPPERDINNERLAKE FLOAT,"
" ZDRYWALLBEYONDBROWNBOWL VARCHAR,"
" ZBELLYCRASHITEMLACK BLOB,"
" ZTENNISCYCLEBILLOFFICER INTEGER,"
" ZMALLEQUIPTHANKSGLUE FLOAT,"
" ZMISSREPLYHUMANLIVING INTEGER,"
" ZKIWIVISUALPRIDEAPPLE VARCHAR,"
" ZWISHHITSKINMOTOR BLOB,"
" ZCALMRACCOONPROGRAMDEBIT VARCHAR,"
" ZSHINYASSISTLIVINGCRAB VARCHAR,"
" ZRESOLVEWRISTWRAPAPPLE VARCHAR,"
" ZAPPEALSIMPLESECONDHOUSING BLOB,"
" ZCORNERANCHORTAPEDIVER TIMESTAMP,"
" ZMEMORYREQUESTSOURCEBIG VARCHAR,"
" ZTRYFACTKEEPMILK TIMESTAMP,"
" ZDIVERPAINTLEATHEREASY INTEGER,"
" ZSORTMISTYQUOTECABBAGE BLOB,"
" ZTUNEGASBUFFALOCAPITAL BLOB,"
" ZFILLSTOPLAWJOYFUL FLOAT,"
" ZSTEELCAREFULPLATENUMBER FLOAT,"
" ZGIVEVIVIDDIVINEMEANING INTEGER,"
" ZTREATPACKFUTURECONVERT VARCHAR,"
" ZCALMLYGEMFINISHEFFECT INTEGER,"
" ZCABBAGESOCKEASEMINUTE BLOB,"
" ZPLANETFAMILYPUREMEMORY TIMESTAMP,"
" ZMERRYCRACKTRAINLEADER BLOB,"
" ZMINORWAYPAPERCLASSY TIMESTAMP,"
" ZEAGLELINEMINEMAIL VARCHAR,"
" ZRESORTYARDGREENLET TIMESTAMP,"
" ZYARDOREGANOVIVIDJEWEL TIMESTAMP,"
" ZPURECAKEVIVIDNEATLY FLOAT,"
" ZASKCONTACTMONITORFUN TIMESTAMP,"
" ZMOVEWHOGAMMAINCH VARCHAR,"
" ZLETTUCEBIRDMEETDEBATE TIMESTAMP,"
" ZGENENATURALHEARINGKITE VARCHAR,"
" ZMUFFINDRYERDRAWFORTUNE FLOAT,"
" ZGRAYSURVEYWIRELOVE FLOAT,"
" ZPLIERSPRINTASKOREGANO INTEGER,"
" ZTRAVELDRIVERCONTESTLILY INTEGER,"
" ZHUMORSPICESANDKIDNEY TIMESTAMP,"
" ZARSENICSAMPLEWAITMUON INTEGER,"
" ZLACEADDRESSGROUNDCAREFUL FLOAT,"
" ZBAMBOOMESSWASABIEVENING BLOB,"
" ZONERELEASEAVERAGENURSE INTEGER,"
" ZRADIANTWHENTRYCARD TIMESTAMP,"
" ZREWARDINSIDEMANGOINTENSE FLOAT,"
" ZNEATSTEWPARTIRON TIMESTAMP,"
" ZOUTSIDEPEAHENCOUNTICE TIMESTAMP,"
" ZCREAMEVENINGLIPBRANCH FLOAT,"
" ZWHALEMATHAVOCADOCOPPER FLOAT,"
" ZLIFEUSELEAFYBELL FLOAT,"
" ZWEALTHLINENGLEEFULDAY VARCHAR,"
" ZFACEINVITETALKGOLD BLOB,"
" ZWESTAMOUNTAFFECTHEARING INTEGER,"
" ZDELAYOUTCOMEHORNAGENCY INTEGER,"
" ZBIGTHINKCONVERTECONOMY BLOB,"
" ZBASEGOUDAREGULARFORGIVE TIMESTAMP,"
" ZPATTERNCLORINEGRANDCOLBY TIMESTAMP,"
" ZCYANBASEFEEDADROIT INTEGER,"
" ZCARRYFLOORMINNOWDRAGON TIMESTAMP,"
" ZIMAGEPENCILOTHERBOTTOM FLOAT,"
" ZXENONFLIGHTPALEAPPLE TIMESTAMP,"
" ZHERRINGJOKEFEATUREHOPEFUL FLOAT,"
" ZCAPYEARLYRIVETBRUSH FLOAT,"
" ZAGEREEDFROGBASKET VARCHAR,"
" ZUSUALBODYHALIBUTDIAMOND VARCHAR,"
" ZFOOTTAPWORDENTRY VARCHAR,"
" ZDISHKEEPBLESTMONITOR FLOAT,"
" ZBROADABLESOLIDCASUAL INTEGER,"
" ZSQUAREGLEEFULCHILDLIGHT INTEGER,"
" ZHOLIDAYHEADPONYDETAIL INTEGER,"
" ZGENERALRESORTSKYOPEN TIMESTAMP,"
" ZGLADSPRAYKIDNEYGUPPY VARCHAR,"
" ZSWIMHEAVYMENTIONKIND BLOB,"
" ZMESSYSULFURDREAMFESTIVE BLOB,"
" ZSKYSKYCLASSICBRIEF VARCHAR,"
" ZDILLASKHOKILEMON FLOAT,"
" ZJUNIORSHOWPRESSNOVA FLOAT,"
" ZSIZETOEAWARDFRESH TIMESTAMP,"
" ZKEYFAILAPRICOTMETAL VARCHAR,"
" ZHANDYREPAIRPROTONAIRPORT VARCHAR,"
" ZPOSTPROTEINHANDLEACTOR BLOB"
");"
);
speedtest1_prepare(
"INSERT INTO ZLOOKSLIKECOREDATA(ZPK,ZAIRFORGIVEHEADFROG,"
"ZGIFTICEFISHGLUEHAIR,ZDELAYOUTCOMEHORNAGENCY,ZSLEEPYUSERGRANDBOWL,"
"ZGLASSRESERVEBARIUMMEAL,ZBRIEFGOBYDODGERHEIGHT,"
"ZBAMBOOMESSWASABIEVENING,ZFARMERMORNINGMIRRORCONCERN,"
"ZTREATPACKFUTURECONVERT,ZCAUSESALAMITERMCYAN,ZCALMRACCOONPROGRAMDEBIT,"
"ZHOLIDAYHEADPONYDETAIL,ZWOODPOETRYCOBBLERBENCH,ZHAFNIUMSCRIPTSALADMOTOR,"
"ZUSUALBODYHALIBUTDIAMOND,ZOUTSIDEPEAHENCOUNTICE,ZDIVERPAINTLEATHEREASY,"
"ZWESTAMOUNTAFFECTHEARING,ZSIZETOEAWARDFRESH,ZDEWPEACHCAREERCELERY,"
"ZSTEELCAREFULPLATENUMBER,ZCYANBASEFEEDADROIT,ZCALMLYGEMFINISHEFFECT,"
"ZHANDYREPAIRPROTONAIRPORT,ZGENENATURALHEARINGKITE,ZBROADABLESOLIDCASUAL,"
"ZPOSTPROTEINHANDLEACTOR,ZLACEADDRESSGROUNDCAREFUL,ZIMAGEPENCILOTHERBOTTOM,"
"ZPROBLEMCLUBPOPOVERJELLY,ZPATTERNCLORINEGRANDCOLBY,ZNEATSTEWPARTIRON,"
"ZAPPEALSIMPLESECONDHOUSING,ZMOVEWHOGAMMAINCH,ZTENNISCYCLEBILLOFFICER,"
"ZSHARKJUSTFRUITMOVIE,ZKEYFAILAPRICOTMETAL,ZCOMPANYSUMMERFIBERELF,"
"ZTERMFITTINGHOUSINGCOMMAND,ZRESORTYARDGREENLET,ZCABBAGESOCKEASEMINUTE,"
"ZSQUAREGLEEFULCHILDLIGHT,ZONERELEASEAVERAGENURSE,ZBIGTHINKCONVERTECONOMY,"
"ZPLIERSPRINTASKOREGANO,ZDECADEJOYOUSWAVEHABIT,ZDRYWALLBEYONDBROWNBOWL,"
"ZCLUBRELEASELIZARDADVICE,ZWHALEMATHAVOCADOCOPPER,ZBELLYCRASHITEMLACK,"
"ZLETTUCEBIRDMEETDEBATE,ZCAPABLETRIPDOORALMOND,ZRADIANTWHENTRYCARD,"
"ZCAPYEARLYRIVETBRUSH,ZAGEREEDFROGBASKET,ZSWIMHEAVYMENTIONKIND,"
"ZTRAVELDRIVERCONTESTLILY,ZGLADSPRAYKIDNEYGUPPY,ZBANKBUFFALORECOVERORBIT,"
"ZFINGERDUEPIZZAOPTION,ZCLAMBITARUGULAFAJITA,ZLONGFINLEAVEIMAGEOIL,"
"ZLONGDIETESSAYNATURE,ZJUNIORSHOWPRESSNOVA,ZHOPEFULGATEHOLECHALK,"
"ZDEPOSITPAIRCOLLEGECOMET,ZWEALTHLINENGLEEFULDAY,ZFILLSTOPLAWJOYFUL,"
"ZTUNEGASBUFFALOCAPITAL,ZGRAYSURVEYWIRELOVE,ZCORNERANCHORTAPEDIVER,"
"ZREWARDINSIDEMANGOINTENSE,ZCADETBRIGHTPLANETBANK,ZPLANETFAMILYPUREMEMORY,"
"ZTREATTESTQUILLCHARGE,ZCREAMEVENINGLIPBRANCH,ZSKYSKYCLASSICBRIEF,"
"ZARSENICSAMPLEWAITMUON,ZBROWBALANCEKEYCHOWDER,ZFLYINGDOCTORTABLEMELODY,"
"ZHANGERLITHIUMDINNERMEET,ZNOTICEPEARPOLICYJUICE,ZSHINYASSISTLIVINGCRAB,"
"ZLIFEUSELEAFYBELL,ZFACEINVITETALKGOLD,ZGENERALRESORTSKYOPEN,"
"ZPURECAKEVIVIDNEATLY,ZKIWIVISUALPRIDEAPPLE,ZMESSYSULFURDREAMFESTIVE,"
"ZCHARGECLICKHUMANEHIRE,ZHERRINGJOKEFEATUREHOPEFUL,ZYARDOREGANOVIVIDJEWEL,"
"ZFOOTTAPWORDENTRY,ZWISHHITSKINMOTOR,ZBASEGOUDAREGULARFORGIVE,"
"ZMUFFINDRYERDRAWFORTUNE,ZACTIONRANGEELEGANTNEUTRON,ZTRYFACTKEEPMILK,"
"ZPEACHCOPPERDINNERLAKE,ZFRAMEENTERSIMPLEMOUTH,ZMERRYCRACKTRAINLEADER,"
"ZMEMORYREQUESTSOURCEBIG,ZCARRYFLOORMINNOWDRAGON,ZMINORWAYPAPERCLASSY,"
"ZDILLASKHOKILEMON,ZRESOLVEWRISTWRAPAPPLE,ZASKCONTACTMONITORFUN,"
"ZGIVEVIVIDDIVINEMEANING,ZEIGHTLEADERWORKERMOST,ZMISSREPLYHUMANLIVING,"
"ZXENONFLIGHTPALEAPPLE,ZSORTMISTYQUOTECABBAGE,ZEAGLELINEMINEMAIL,"
"ZFAMILYVISUALOWNERMATTER,ZSPREADMOTORBISCUITBACON,ZDISHKEEPBLESTMONITOR,"
"ZMALLEQUIPTHANKSGLUE,ZGOLDYOUNGINITIALNOSE,ZHUMORSPICESANDKIDNEY)"
"VALUES(?1,?26,?20,?93,?8,?33,?3,?81,?28,?60,?18,?47,?109,?29,?30,?104,?86,"
"?54,?92,?117,?9,?58,?97,?61,?119,?73,?107,?120,?80,?99,?31,?96,?85,?50,?71,"
"?42,?27,?118,?36,?2,?67,?62,?108,?82,?94,?76,?35,?40,?11,?88,?41,?72,?4,"
"?83,?102,?103,?112,?77,?111,?22,?13,?34,?15,?23,?116,?7,?5,?90,?57,?56,"
"?75,?51,?84,?25,?63,?37,?87,?114,?79,?38,?14,?10,?21,?48,?89,?91,?110,"
"?69,?45,?113,?12,?101,?68,?105,?46,?95,?74,?24,?53,?39,?6,?64,?52,?98,"
"?65,?115,?49,?70,?59,?32,?44,?100,?55,?66,?16,?19,?106,?43,?17,?78);"
);
for(i=0; i<n; i++){
x1 = speedtest1_random();
speedtest1_numbername(x1%1000, zNum, sizeof(zNum));
len = (int)strlen(zNum);
sqlite3_bind_int(g.pStmt, 1, i^0xf);
for(j=0; zType[j]; j++){
switch( zType[j] ){
case 'I':
case 'T':
sqlite3_bind_int64(g.pStmt, j+2, x1);
break;
case 'F':
sqlite3_bind_double(g.pStmt, j+2, (double)x1);
break;
case 'V':
case 'B':
sqlite3_bind_text64(g.pStmt, j+2, zNum, len,
SQLITE_STATIC, SQLITE_UTF8);
break;
}
}
speedtest1_run();
}
speedtest1_exec("COMMIT;");
speedtest1_end_test();
n = g.szTest*250;
speedtest1_begin_test(110, "Query %d rows by rowid", n);
speedtest1_prepare(
"SELECT ZCYANBASEFEEDADROIT,ZJUNIORSHOWPRESSNOVA,ZCAUSESALAMITERMCYAN,"
"ZHOPEFULGATEHOLECHALK,ZHUMORSPICESANDKIDNEY,ZSWIMHEAVYMENTIONKIND,"
"ZMOVEWHOGAMMAINCH,ZAPPEALSIMPLESECONDHOUSING,ZHAFNIUMSCRIPTSALADMOTOR,"
"ZNEATSTEWPARTIRON,ZLONGFINLEAVEIMAGEOIL,ZDEWPEACHCAREERCELERY,"
"ZXENONFLIGHTPALEAPPLE,ZCALMRACCOONPROGRAMDEBIT,ZUSUALBODYHALIBUTDIAMOND,"
"ZTRYFACTKEEPMILK,ZWEALTHLINENGLEEFULDAY,ZLONGDIETESSAYNATURE,"
"ZLIFEUSELEAFYBELL,ZTREATPACKFUTURECONVERT,ZMEMORYREQUESTSOURCEBIG,"
"ZYARDOREGANOVIVIDJEWEL,ZDEPOSITPAIRCOLLEGECOMET,ZSLEEPYUSERGRANDBOWL,"
"ZBRIEFGOBYDODGERHEIGHT,ZCLUBRELEASELIZARDADVICE,ZCAPABLETRIPDOORALMOND,"
"ZDRYWALLBEYONDBROWNBOWL,ZASKCONTACTMONITORFUN,ZKIWIVISUALPRIDEAPPLE,"
"ZNOTICEPEARPOLICYJUICE,ZPEACHCOPPERDINNERLAKE,ZSTEELCAREFULPLATENUMBER,"
"ZGLADSPRAYKIDNEYGUPPY,ZCOMPANYSUMMERFIBERELF,ZTENNISCYCLEBILLOFFICER,"
"ZIMAGEPENCILOTHERBOTTOM,ZWESTAMOUNTAFFECTHEARING,ZDIVERPAINTLEATHEREASY,"
"ZSKYSKYCLASSICBRIEF,ZMESSYSULFURDREAMFESTIVE,ZMERRYCRACKTRAINLEADER,"
"ZBROADABLESOLIDCASUAL,ZGLASSRESERVEBARIUMMEAL,ZTUNEGASBUFFALOCAPITAL,"
"ZBANKBUFFALORECOVERORBIT,ZTREATTESTQUILLCHARGE,ZBAMBOOMESSWASABIEVENING,"
"ZREWARDINSIDEMANGOINTENSE,ZEAGLELINEMINEMAIL,ZCALMLYGEMFINISHEFFECT,"
"ZKEYFAILAPRICOTMETAL,ZFINGERDUEPIZZAOPTION,ZCADETBRIGHTPLANETBANK,"
"ZGOLDYOUNGINITIALNOSE,ZMISSREPLYHUMANLIVING,ZEIGHTLEADERWORKERMOST,"
"ZFRAMEENTERSIMPLEMOUTH,ZBIGTHINKCONVERTECONOMY,ZFACEINVITETALKGOLD,"
"ZPOSTPROTEINHANDLEACTOR,ZHERRINGJOKEFEATUREHOPEFUL,ZCABBAGESOCKEASEMINUTE,"
"ZMUFFINDRYERDRAWFORTUNE,ZPROBLEMCLUBPOPOVERJELLY,ZGIVEVIVIDDIVINEMEANING,"
"ZGENENATURALHEARINGKITE,ZGENERALRESORTSKYOPEN,ZLETTUCEBIRDMEETDEBATE,"
"ZBASEGOUDAREGULARFORGIVE,ZCHARGECLICKHUMANEHIRE,ZPLANETFAMILYPUREMEMORY,"
"ZMINORWAYPAPERCLASSY,ZCAPYEARLYRIVETBRUSH,ZSIZETOEAWARDFRESH,"
"ZARSENICSAMPLEWAITMUON,ZSQUAREGLEEFULCHILDLIGHT,ZSHINYASSISTLIVINGCRAB,"
"ZCORNERANCHORTAPEDIVER,ZDECADEJOYOUSWAVEHABIT,ZTRAVELDRIVERCONTESTLILY,"
"ZFLYINGDOCTORTABLEMELODY,ZSHARKJUSTFRUITMOVIE,ZFAMILYVISUALOWNERMATTER,"
"ZFARMERMORNINGMIRRORCONCERN,ZGIFTICEFISHGLUEHAIR,ZOUTSIDEPEAHENCOUNTICE,"
"ZSPREADMOTORBISCUITBACON,ZWISHHITSKINMOTOR,ZHOLIDAYHEADPONYDETAIL,"
"ZWOODPOETRYCOBBLERBENCH,ZAIRFORGIVEHEADFROG,ZBROWBALANCEKEYCHOWDER,"
"ZDISHKEEPBLESTMONITOR,ZCLAMBITARUGULAFAJITA,ZPLIERSPRINTASKOREGANO,"
"ZRADIANTWHENTRYCARD,ZDELAYOUTCOMEHORNAGENCY,ZPURECAKEVIVIDNEATLY,"
"ZPATTERNCLORINEGRANDCOLBY,ZHANDYREPAIRPROTONAIRPORT,ZAGEREEDFROGBASKET,"
"ZSORTMISTYQUOTECABBAGE,ZFOOTTAPWORDENTRY,ZRESOLVEWRISTWRAPAPPLE,"
"ZDILLASKHOKILEMON,ZFILLSTOPLAWJOYFUL,ZACTIONRANGEELEGANTNEUTRON,"
"ZRESORTYARDGREENLET,ZCREAMEVENINGLIPBRANCH,ZWHALEMATHAVOCADOCOPPER,"
"ZGRAYSURVEYWIRELOVE,ZBELLYCRASHITEMLACK,ZHANGERLITHIUMDINNERMEET,"
"ZCARRYFLOORMINNOWDRAGON,ZMALLEQUIPTHANKSGLUE,ZTERMFITTINGHOUSINGCOMMAND,"
"ZONERELEASEAVERAGENURSE,ZLACEADDRESSGROUNDCAREFUL"
" FROM ZLOOKSLIKECOREDATA WHERE ZPK=?1;"
);
for(i=0; i<n; i++){
x1 = speedtest1_random()%nRow;
sqlite3_bind_int(g.pStmt, 1, x1);
speedtest1_run();
}
speedtest1_end_test();
}
/*
** A testset used for debugging speedtest1 itself.
*/
@@ -1879,8 +1610,6 @@ int main(int argc, char **argv){
testset_main();
}else if( strcmp(zTSet,"debug1")==0 ){
testset_debug1();
}else if( strcmp(zTSet,"orm")==0 ){
testset_orm();
}else if( strcmp(zTSet,"cte")==0 ){
testset_cte();
}else if( strcmp(zTSet,"rtree")==0 ){
+16 -24
View File
@@ -148,68 +148,60 @@ do_execsql_test tabfunc01-600 {
do_test tabfunc01-700 {
set PTR1 [intarray_addr 5 7 13 17 23]
set PTR [intarray_addr 5 7 13 17 23]
db eval {
SELECT b FROM t600, carray($PTR1,5) WHERE a=value;
SELECT b FROM t600, carray($PTR,5) WHERE a=value;
}
} {(005) (007) (013) (017) (023)}
do_test tabfunc01-701 {
db eval {
SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int32');
SELECT b FROM t600 WHERE a IN carray($PTR,5,'int32');
}
} {(005) (007) (013) (017) (023)}
do_test tabfunc01-702 {
db eval {
SELECT b FROM t600 WHERE a IN carray($PTR1,4,'int32');
SELECT b FROM t600 WHERE a IN carray($PTR,4,'int32');
}
} {(005) (007) (013) (017)}
do_catchsql_test tabfunc01-710 {
SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int33');
SELECT b FROM t600 WHERE a IN carray($PTR,5,'int33');
} {1 {unknown datatype: 'int33'}}
do_test tabfunc01-720 {
set PTR2 [int64array_addr 5 7 13 17 23]
set PTR [int64array_addr 5 7 13 17 23]
db eval {
SELECT b FROM t600, carray($PTR2,5,'int64') WHERE a=value;
SELECT b FROM t600, carray($PTR,5,'int64') WHERE a=value;
}
} {(005) (007) (013) (017) (023)}
do_test tabfunc01-721 {
db eval {
SELECT remember(123,$PTR2);
SELECT value FROM carray($PTR2,5,'int64');
SELECT remember(123,$PTR);
SELECT value FROM carray($PTR,5,'int64');
}
} {123 123 7 13 17 23}
do_test tabfunc01-722 {
set PTR3 [expr {$PTR2+16}]
set PTR2 [expr {$PTR+16}]
db eval {
SELECT remember(987,$PTR3);
SELECT value FROM carray($PTR2,5,'int64');
SELECT remember(987,$PTR2);
SELECT value FROM carray($PTR,5,'int64');
}
} {987 123 7 987 17 23}
do_test tabfunc01-730 {
set PTR4 [doublearray_addr 5.0 7.0 13.0 17.0 23.0]
set PTR [doublearray_addr 5.0 7.0 13.0 17.0 23.0]
db eval {
SELECT b FROM t600, carray($PTR4,5,'double') WHERE a=value;
SELECT b FROM t600, carray($PTR,5,'double') WHERE a=value;
}
} {(005) (007) (013) (017) (023)}
do_test tabfunc01-740 {
set PTR5 [textarray_addr x5 x7 x13 x17 x23]
set PTR [textarray_addr 5 7 13 17 23]
db eval {
SELECT b FROM t600, carray($PTR5,5,'char*') WHERE a=trim(value,'x');
SELECT b FROM t600, carray($PTR,5,'char*') WHERE a=value;
}
} {(005) (007) (013) (017) (023)}
do_test tabfunc01-750 {
db eval {
SELECT aa.value, bb.value, '|'
FROM carray($PTR4,5,'double') AS aa
JOIN carray($PTR5,5,'char*') AS bb ON aa.rowid=bb.rowid;
}
} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}
# Free up memory allocations
intarray_addr
int64array_addr
doublearray_addr
+3 -30
View File
@@ -461,7 +461,7 @@ if {[info exists cmdlinearg]==0} {
}
{^-+backtrace=.+$} {
foreach {dummy cmdlinearg(backtrace)} [split $a =] break
sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
sqlite3_memdebug_backtrace $value
}
{^-+binarylog=.+$} {
foreach {dummy cmdlinearg(binarylog)} [split $a =] break
@@ -919,37 +919,10 @@ proc normalize_list {L} {
set L2
}
# Either:
#
# do_execsql_test TESTNAME SQL ?RES?
# do_execsql_test -db DB TESTNAME SQL ?RES?
#
proc do_execsql_test {args} {
set db db
if {[lindex $args 0]=="-db"} {
set db [lindex $args 1]
set args [lrange $args 2 end]
}
if {[llength $args]==2} {
foreach {testname sql} $args {}
set result ""
} elseif {[llength $args]==3} {
foreach {testname sql result} $args {}
} else {
error [string trim {
wrong # args: should be "do_execsql_test ?-db DB? testname sql ?result?"
}]
}
proc do_execsql_test {testname sql {result {}}} {
fix_testname testname
uplevel do_test \
[list $testname] \
[list "execsql {$sql} $db"] \
[list [list {*}$result]]
uplevel do_test [list $testname] [list "execsql {$sql}"] [list [list {*}$result]]
}
proc do_catchsql_test {testname sql result} {
fix_testname testname
uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
+1 -1
View File
@@ -42,7 +42,7 @@ do_test tkt-78e04-1.3 {
} {}
do_test tkt-78e04-1.4 {
execsql {
EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1abc%';
EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE 'abc%';
}
} {0 0 0 {SCAN TABLE USING COVERING INDEX i1}}
do_test tkt-78e04-1.5 {
-25
View File
@@ -176,30 +176,5 @@ foreach {tn sql} {
}
}
#-------------------------------------------------------------------------
#
do_execsql_test 5.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX x1c ON x1(b, c);
INSERT INTO x1 VALUES(1, 'a', 1);
INSERT INTO x1 VALUES(2, 'a', 2);
INSERT INTO x1 VALUES(3, 'a', 3);
}
do_execsql_test 5.1.1 {
UPDATE x1 SET c=c+1 WHERE b='a';
}
do_execsql_test 5.1.2 {
SELECT * FROM x1;
} {1 a 2 2 a 3 3 a 4}
do_test 5.2 {
catch { array unset A }
db eval { EXPLAIN UPDATE x1 SET c=c+1 WHERE b='a' } { incr A($opcode) }
set A(NotExists)
} {1}
finish_test
+14 -14
View File
@@ -1295,25 +1295,25 @@ do_execsql_test 18.1.0 {
CREATE INDEX i6 ON t6(b, a);
INSERT INTO t6 VALUES(1, 'Peter');
INSERT INTO t6 VALUES(2, 'Andrew');
INSERT INTO t6 VALUES(3, '8James');
INSERT INTO t6 VALUES(4, '8John');
INSERT INTO t6 VALUES(3, 'James');
INSERT INTO t6 VALUES(4, 'John');
INSERT INTO t6 VALUES(5, 'Phillip');
INSERT INTO t6 VALUES(6, 'Bartholomew');
CREATE VIRTUAL TABLE e6 USING echo(t6);
}
foreach {tn sql res filter} {
1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James}
1.1 "SELECT a FROM e6 WHERE b>'James'" {4 1 5}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} James}
1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9}
1.2 "SELECT a FROM e6 WHERE b>='J' AND b<'K'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} J K}
1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%}
1.3 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%}
1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%}
1.4 "SELECT a FROM e6 WHERE b LIKE 'j%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%}
} {
set echo_module {}
do_execsql_test 18.$tn.1 $sql $res
@@ -1322,11 +1322,11 @@ foreach {tn sql res filter} {
do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON }
foreach {tn sql res filter} {
2.1 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8J%}
2.1 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%}
2.2 "SELECT a FROM e6 WHERE b LIKE '8j%'" {}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8j%}
2.2 "SELECT a FROM e6 WHERE b LIKE 'j%'" {}
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%}
} {
set echo_module {}
do_execsql_test 18.$tn.1 $sql $res
+4 -4
View File
@@ -31,14 +31,14 @@ do_execsql_test 1.0 {
}
foreach {tn sql expect} {
1 "SELECT * FROM e6 WHERE b LIKE '8abc'" {
1 "SELECT * FROM e6 WHERE b LIKE 'abc'" {
xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?}
xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8abc
xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} abc
}
2 "SELECT * FROM e6 WHERE b GLOB '8abc'" {
2 "SELECT * FROM e6 WHERE b GLOB 'abc'" {
xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?}
xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8abc
xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} abc
}
} {
do_test 1.$tn {
-35
View File
@@ -1,35 +0,0 @@
#!/bin/bash
#
# A script for running speed tests using kvtest.
#
# The test database must be set up first. Recommended
# command-line:
#
# ./kvtest init kvtest.db --count 100K --size 12K --variance 5K
if test "$1" = ""
then
echo "Usage: $0 OUTPUTFILE [OPTIONS]"
exit
fi
NAME=$1
shift
OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DIRECT_OVERFLOW_READ -DUSE_PREAD"
KVARGS="--count 100K --stats"
gcc -g -Os -I. $OPTS $* kvtest.c sqlite3.c -o kvtest
# First run using SQL
rm cachegrind.out.[1-9][0-9]*
valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS 2>&1 | tee summary-kvtest-$NAME.txt
mv cachegrind.out.[1-9][0-9]* cachegrind.out.sql-$NAME
cg_anno.tcl cachegrind.out.sql-$NAME >cout-kvtest-sql-$NAME.txt
# Second run using the sqlite3_blob object
valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS --blob-api 2>&1 | tee -a summary-kvtest-$NAME.txt
mv cachegrind.out.[1-9][0-9]* cachegrind.out.$NAME
cg_anno.tcl cachegrind.out.$NAME >cout-kvtest-$NAME.txt
# Diff the sqlite3_blob API analysis for non-trunk runs.
if test "$NAME" != "trunk"; then
fossil test-diff --tk cout-kvtest-trunk.txt cout-kvtest-$NAME.txt &
fi
+27 -44
View File
@@ -316,31 +316,6 @@ static int yyGrowStack(yyParser *p){
# define YYMALLOCARGTYPE size_t
#endif
/* Initialize a new parser that has already been allocated.
*/
void ParseInit(void *yypParser){
yyParser *pParser = (yyParser*)yypParser;
#ifdef YYTRACKMAXSTACKDEPTH
pParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
pParser->yytos = NULL;
pParser->yystack = NULL;
pParser->yystksz = 0;
if( yyGrowStack(pParser) ){
pParser->yystack = &pParser->yystk0;
pParser->yystksz = 1;
}
#endif
#ifndef YYNOERRORRECOVERY
pParser->yyerrcnt = -1;
#endif
pParser->yytos = pParser->yystack;
pParser->yystack[0].stateno = 0;
pParser->yystack[0].major = 0;
}
#ifndef Parse_ENGINEALWAYSONSTACK
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
@@ -356,11 +331,28 @@ void ParseInit(void *yypParser){
void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
if( pParser ) ParseInit(pParser);
if( pParser ){
#ifdef YYTRACKMAXSTACKDEPTH
pParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
pParser->yytos = NULL;
pParser->yystack = NULL;
pParser->yystksz = 0;
if( yyGrowStack(pParser) ){
pParser->yystack = &pParser->yystk0;
pParser->yystksz = 1;
}
#endif
#ifndef YYNOERRORRECOVERY
pParser->yyerrcnt = -1;
#endif
pParser->yytos = pParser->yystack;
pParser->yystack[0].stateno = 0;
pParser->yystack[0].major = 0;
}
return pParser;
}
#endif /* Parse_ENGINEALWAYSONSTACK */
/* The following function deletes the "minor type" or semantic value
** associated with a symbol. The symbol can be either a terminal
@@ -414,18 +406,6 @@ static void yy_pop_parser_stack(yyParser *pParser){
yy_destructor(pParser, yytos->major, &yytos->minor);
}
/*
** Clear all secondary memory allocations from the parser
*/
void ParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
}
#ifndef Parse_ENGINEALWAYSONSTACK
/*
** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down.
@@ -438,13 +418,16 @@ void ParseFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
#ifndef YYPARSEFREENEVERNULL
if( p==0 ) return;
if( pParser==0 ) return;
#endif
ParseFinalize(p);
(*freeProc)(p);
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
(*freeProc)((void*)pParser);
}
#endif /* Parse_ENGINEALWAYSONSTACK */
/*
** Return the peak depth of the stack for a parser.
-41
View File
@@ -1,41 +0,0 @@
/*
** Link this program against an SQLite library of unknown provenance in order
** to display the compile-time maximum values for various settings.
*/
#include "sqlite3.h"
#include <stdio.h>
static const struct {
int eCode;
char *zName;
} aLimit[] = {
{ SQLITE_LIMIT_LENGTH, "SQLITE_MAX_LENGTH" },
{ SQLITE_LIMIT_SQL_LENGTH, "SQLITE_MAX_SQL_LENGTH" },
{ SQLITE_LIMIT_COLUMN, "SQLITE_MAX_COLUMN" },
{ SQLITE_LIMIT_EXPR_DEPTH, "SQLITE_MAX_EXPR_DEPTH" },
{ SQLITE_LIMIT_COMPOUND_SELECT, "SQLITE_MAX_COMPOUND_SELECT" },
{ SQLITE_LIMIT_VDBE_OP, "SQLITE_MAX_VDBE_OP" },
{ SQLITE_LIMIT_FUNCTION_ARG, "SQLITE_MAX_FUNCTION_ARG" },
{ SQLITE_LIMIT_ATTACHED, "SQLITE_MAX_ATTACHED" },
{ SQLITE_LIMIT_LIKE_PATTERN_LENGTH, "SQLITE_MAX_LIKE_PATTERN_LENGTH" },
{ SQLITE_LIMIT_VARIABLE_NUMBER, "SQLITE_MAX_VARIABLE_NUMBER" },
{ SQLITE_LIMIT_TRIGGER_DEPTH, "SQLITE_MAX_TRIGGER_DEPTH" },
{ SQLITE_LIMIT_WORKER_THREADS, "SQLITE_MAX_WORKER_THREADS" },
};
static int maxLimit(sqlite3 *db, int eCode){
int iOrig = sqlite3_limit(db, eCode, 0x7fffffff);
return sqlite3_limit(db, eCode, iOrig);
}
int main(int argc, char **argv){
sqlite3 *db;
int j, rc;
rc = sqlite3_open(":memory:", &db);
if( rc==SQLITE_OK ){
for(j=0; j<sizeof(aLimit)/sizeof(aLimit[0]); j++){
printf("%-35s %10d\n", aLimit[j].zName, maxLimit(db, aLimit[j].eCode));
}
sqlite3_close(db);
}
}
+1 -1
View File
@@ -83,7 +83,7 @@ Replace.exe:
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \\
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\
| sort >> sqlite3.def
}]]
+2 -10
View File
@@ -73,13 +73,7 @@ close $in
# Set up patterns for recognizing API declarations.
#
set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)}
set declpattern1 {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
set declpattern2 \
{^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3session_[_a-zA-Z0-9]+)(\(.*)$}
set declpattern3 \
{^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changeset_[_a-zA-Z0-9]+)(\(.*)$}
set declpattern {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
# Force the output to use unix line endings, even on Windows.
fconfigure stdout -translation lf
@@ -127,9 +121,7 @@ foreach file $filelist {
if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
set line "SQLITE_API $line"
} else {
if {[regexp $declpattern1 $line all rettype funcname rest] || \
[regexp $declpattern2 $line all rettype funcname rest] || \
[regexp $declpattern3 $line all rettype funcname rest]} {
if {[regexp $declpattern $line all rettype funcname rest]} {
set line SQLITE_API
append line " " [string trim $rettype]
if {[string index $rettype end] ne "*"} {
-3
View File
@@ -142,6 +142,3 @@ fi
if test $doExplain -eq 1; then
./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
fi
if test "$NAME" != "trunk"; then
fossil test-diff --tk cout-trunk.txt cout-$NAME.txt
fi