Merge sqlite-release(3.30.1) into prerelease-integration

This commit is contained in:
Stephen Lombardo 2019-10-27 18:31:57 -04:00
commit 9df3ee334f
212 changed files with 11313 additions and 3386 deletions

View File

@ -631,7 +631,6 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000

View File

@ -19,7 +19,7 @@ TOP = ../sqlite
#### C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
BCC = gcc -g -O2
BCC = gcc -g -O0
#BCC = /opt/ancic/bin/c89 -0
#### If the target operating system supports the "usleep()" system
@ -38,8 +38,8 @@ THREADSAFE = -DTHREADSAFE=0
#### Specify any extra linker options needed to make the library
# thread safe
#
#THREADLIB = -lpthread
THREADLIB =
THREADLIB = -lpthread -lm -ldl
#THREADLIB =
#### Specify any extra libraries needed to access required functions.
#
@ -54,11 +54,9 @@ TLIBS =
# You can make the library go almost twice as fast if you compile
# with -DNDEBUG=1
#
#OPTS = -DSQLITE_DEBUG=2
#OPTS = -DSQLITE_DEBUG=1
#OPTS =
OPTS = -DNDEBUG=1
OPTS += -DHAVE_FDATASYNC=1
OPTS += -DSQLITE_DEBUG=1
OPTS += -DSQLITE_ENABLE_WHERETRACE
OPTS += -DSQLITE_ENABLE_SELECTTRACE
#### The suffix to add to executable files. ".exe" for windows.
# Nothing for unix.
@ -70,7 +68,7 @@ EXE =
# will run on the target platform. This is usually the same
# as BCC, unless you are cross-compiling.
#
TCC = gcc -O6
TCC = gcc -O0
#TCC = gcc -g -O0 -Wall
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
@ -91,18 +89,12 @@ SHPREFIX = lib
#### Extra compiler options needed for programs that use the TCL library.
#
#TCL_FLAGS =
#TCL_FLAGS = -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6
#### Linker options needed to link against the TCL library.
#
#LIBTCL = -ltcl -lm -ldl
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz
#### Additional objects for SQLite library when TCL support is enabled.
#TCLOBJ =

View File

@ -73,7 +73,7 @@ API_ARMOR = 0
!IFNDEF NO_WARN
!IF $(USE_FULLWARN)!=0
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
!ENDIF
!ENDIF
@ -351,7 +351,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1

View File

@ -1 +1 @@
3.29.0
3.30.1

View File

@ -73,7 +73,7 @@ API_ARMOR = 0
!IFNDEF NO_WARN
!IF $(USE_FULLWARN)!=0
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
!ENDIF
!ENDIF

18
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlcipher 3.29.0.
# Generated by GNU Autoconf 2.69 for sqlcipher 3.30.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlcipher'
PACKAGE_TARNAME='sqlcipher'
PACKAGE_VERSION='3.29.0'
PACKAGE_STRING='sqlcipher 3.29.0'
PACKAGE_VERSION='3.30.1'
PACKAGE_STRING='sqlcipher 3.30.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@ -1337,7 +1337,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 sqlcipher 3.29.0 to adapt to many kinds of systems.
\`configure' configures sqlcipher 3.30.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1402,7 +1402,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlcipher 3.29.0:";;
short | recursive ) echo "Configuration of sqlcipher 3.30.1:";;
esac
cat <<\_ACEOF
@ -1538,7 +1538,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlcipher configure 3.29.0
sqlcipher configure 3.30.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1957,7 +1957,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 sqlcipher $as_me 3.29.0, which was
It was created by sqlcipher $as_me 3.30.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -13808,7 +13808,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 sqlcipher $as_me 3.29.0, which was
This file was extended by sqlcipher $as_me 3.30.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -13874,7 +13874,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="\\
sqlcipher config.status 3.29.0
sqlcipher config.status 3.30.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -134,6 +134,7 @@ do_setup_rec_test $tn.5 {
SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
}
if 0 {
do_setup_rec_test $tn.6 {
CREATE TABLE t1(a, b, c);
} {
@ -142,6 +143,7 @@ do_setup_rec_test $tn.6 {
CREATE INDEX t1_idx_00000061 ON t1(a);
SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
}
}
do_setup_rec_test $tn.7 {
CREATE TABLE t1(a, b, c);

View File

@ -308,6 +308,18 @@
SQLITE_EXTENSION_INIT1
#endif
/*
** The following are copied from sqliteInt.h.
**
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#ifndef SQLITE_AMALGAMATION
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
@ -2086,10 +2098,11 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
}
/*
** Value used to signify the end of an position-list. This is safe because
** it is not possible to have a document with 2^31 terms.
** Value used to signify the end of an position-list. This must be
** as large or larger than any value that might appear on the
** position-list, even a position list that has been corrupted.
*/
#define POSITION_LIST_END 0x7fffffff
#define POSITION_LIST_END LARGEST_INT64
/*
** This function is used to help parse position-lists. When this function is
@ -2165,14 +2178,14 @@ static int fts3PoslistMerge(
fts3GetVarint32(&p1[1], &iCol1);
if( iCol1==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else if( *p1==POS_END ) iCol1 = 0x7fffffff;
else iCol1 = 0;
if( *p2==POS_COLUMN ){
fts3GetVarint32(&p2[1], &iCol2);
if( iCol2==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else if( *p2==POS_END ) iCol2 = 0x7fffffff;
else iCol2 = 0;
if( iCol1==iCol2 ){
@ -2474,7 +2487,8 @@ static void fts3PutDeltaVarint3(
iWrite = *piPrev - iVal;
}
assert( *pbFirst || *piPrev==0 );
assert( *pbFirst==0 || iWrite>0 );
assert_fts3_nc( *pbFirst==0 || iWrite>0 );
assert( *pbFirst==0 || iWrite>=0 );
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
*piPrev = iVal;
*pbFirst = 1;
@ -2580,6 +2594,8 @@ static int fts3DoclistOrMerge(
fts3PoslistCopy(&p, &p2);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}
assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
}
if( rc!=SQLITE_OK ){
@ -3179,18 +3195,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
return rc;
}
/*
** The following are copied from sqliteInt.h.
**
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#ifndef SQLITE_AMALGAMATION
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
/*
** If the numeric type of argument pVal is "integer", then return it
** converted to a 64-bit signed integer. Otherwise, return a copy of

View File

@ -433,10 +433,10 @@ static void fts3SnippetDetails(
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
u64 mPhrase = (u64)1 << i;
u64 mPhrase = (u64)1 << (i%64);
u64 mPos = (u64)1 << (iCsr - iStart);
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
assert( i>=0 && i<=64 );
assert( i>=0 );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{

View File

@ -3797,14 +3797,14 @@ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
p->nNode = nNode;
/* Figure out if this is a leaf or an internal node. */
if( p->aNode[0] ){
if( aNode && aNode[0] ){
/* An internal node. */
p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
}else{
p->iOff = 1;
}
return nodeReaderNext(p);
return aNode ? nodeReaderNext(p) : SQLITE_OK;
}
/*
@ -3941,6 +3941,7 @@ static int fts3AppendToNode(
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
memcpy(pPrev->a, zTerm, nTerm);
pPrev->n = nTerm;
@ -4295,8 +4296,8 @@ static int fts3IncrmergeLoad(
NodeReader reader;
pNode = &pWriter->aNodeWriter[i];
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
if( reader.aNode ){
if( pNode->block.a){
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
if( rc==SQLITE_OK ){

View File

@ -178,6 +178,7 @@ struct Fts5Config {
char *zContentExprlist;
Fts5Tokenizer *pTok;
fts5_tokenizer *pTokApi;
int bLock; /* True when table is preparing statement */
/* Values loaded from the %_config table */
int iCookie; /* Incremented when %_config is modified */
@ -694,6 +695,7 @@ int sqlite3Fts5ExprEof(Fts5Expr*);
i64 sqlite3Fts5ExprRowid(Fts5Expr*);
void sqlite3Fts5ExprFree(Fts5Expr*);
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);
/* Called during startup to register a UDF with SQLite */
int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);

View File

@ -683,7 +683,7 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){
rc = sqlite3_declare_vtab(pConfig->db, zSql);
sqlite3_free(zSql);
}
return rc;
}

View File

@ -309,6 +309,42 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){
}
}
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
Fts5Parse sParse;
memset(&sParse, 0, sizeof(sParse));
if( *pp1 ){
Fts5Expr *p1 = *pp1;
int nPhrase = p1->nPhrase + p2->nPhrase;
p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0);
p2->pRoot = 0;
if( sParse.rc==SQLITE_OK ){
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
);
if( ap==0 ){
sParse.rc = SQLITE_NOMEM;
}else{
int i;
memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*));
for(i=0; i<p2->nPhrase; i++){
ap[i] = p2->apExprPhrase[i];
}
p1->nPhrase = nPhrase;
p1->apExprPhrase = ap;
}
}
sqlite3_free(p2->apExprPhrase);
sqlite3_free(p2);
}else{
*pp1 = p2;
}
return sParse.rc;
}
/*
** Argument pTerm must be a synonym iterator. Return the current rowid
** that it points to.

View File

@ -690,6 +690,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
}else{
/* TODO1: Fix this */
pRet->p[nByte] = 0x00;
pRet->p[nByte+1] = 0x00;
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
}
}
@ -712,7 +713,7 @@ static void fts5DataRelease(Fts5Data *pData){
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
Fts5Data *pRet = fts5DataRead(p, iRowid);
if( pRet ){
if( pRet->szLeaf>pRet->nn ){
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
p->rc = FTS5_CORRUPT;
fts5DataRelease(pRet);
pRet = 0;
@ -4996,9 +4997,12 @@ static void fts5MergePrefixLists(
Fts5PoslistWriter writer;
memset(&writer, 0, sizeof(writer));
/* See the earlier comment in this function for an explanation of why
** corrupt input position lists might cause the output to consume
** at most 20 bytes of unexpected space. */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferZero(&tmp);
sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
if( p->rc ) break;
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
@ -5046,6 +5050,12 @@ static void fts5MergePrefixLists(
}
/* WRITEPOSLISTSIZE */
assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
if( tmp.n>i1.nPoslist+i2.nPoslist ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
break;
}
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
fts5DoclistIterNext(&i1);

View File

@ -465,17 +465,39 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
**
** 1. A MATCH constraint against the special column.
** 1. A MATCH constraint against the table column.
** 2. A MATCH constraint against the "rank" column.
** 3. An == constraint against the rowid column.
** 4. A < or <= constraint against the rowid column.
** 5. A > or >= constraint against the rowid column.
** 3. A MATCH constraint against some other column.
** 4. An == constraint against the rowid column.
** 5. A < or <= constraint against the rowid column.
** 6. A > or >= constraint against the rowid column.
**
** Within the ORDER BY, either:
** Within the ORDER BY, the following are supported:
**
** 5. ORDER BY rank [ASC|DESC]
** 6. ORDER BY rowid [ASC|DESC]
**
** Information for the xFilter call is passed via both the idxNum and
** idxStr variables. Specifically, idxNum is a bitmask of the following
** flags used to encode the ORDER BY clause:
**
** FTS5_BI_ORDER_RANK
** FTS5_BI_ORDER_ROWID
** FTS5_BI_ORDER_DESC
**
** idxStr is used to encode data from the WHERE clause. For each argument
** passed to the xFilter method, the following is appended to idxStr:
**
** Match against table column: "m"
** Match against rank column: "r"
** Match against other column: "<column-number>"
** Equality constraint against the rowid: "="
** A < or <= against the rowid: "<"
** A > or >= against the rowid: ">"
**
** This function ensures that there is at most one "r" or "=". And that if
** there exists an "=" then there is no "<" or ">".
**
** Costs are assigned as follows:
**
** a) If an unusable MATCH operator is present in the WHERE clause, the
@ -503,32 +525,18 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
Fts5Config *pConfig = pTab->pConfig;
const int nCol = pConfig->nCol;
int idxFlags = 0; /* Parameter passed through to xFilter() */
int bHasMatch;
int iNext;
int i;
struct Constraint {
int op; /* Mask against sqlite3_index_constraint.op */
int fts5op; /* FTS5 mask for idxFlags */
int iCol; /* 0==rowid, 1==tbl, 2==rank */
int omit; /* True to omit this if found */
int iConsIndex; /* Index in pInfo->aConstraint[] */
} aConstraint[] = {
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
FTS5_BI_MATCH, 1, 1, -1},
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
FTS5_BI_RANK, 2, 1, -1},
{SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1},
{SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE,
FTS5_BI_ROWID_LE, 0, 0, -1},
{SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE,
FTS5_BI_ROWID_GE, 0, 0, -1},
};
char *idxStr;
int iIdxStr = 0;
int iCons = 0;
int bSeenEq = 0;
int bSeenGt = 0;
int bSeenLt = 0;
int bSeenMatch = 0;
int bSeenRank = 0;
int aColMap[3];
aColMap[0] = -1;
aColMap[1] = nCol;
aColMap[2] = nCol+1;
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
@ -536,40 +544,85 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
/* Set idxFlags flags for all WHERE clause terms that will be used. */
if( pConfig->bLock ){
pTab->base.zErrMsg = sqlite3_mprintf(
"recursively defined fts5 content table"
);
return SQLITE_ERROR;
}
idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
int iCol = p->iColumn;
if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
){
/* A MATCH operator or equivalent */
if( p->usable ){
idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
aConstraint[0].iConsIndex = i;
}else{
if( p->usable==0 || iCol<0 ){
/* As there exists an unusable MATCH constraint this is an
** unusable plan. Set a prohibitively high cost. */
pInfo->estimatedCost = 1e50;
assert( iIdxStr < pInfo->nConstraint*6 + 1 );
idxStr[iIdxStr] = 0;
return SQLITE_OK;
}else{
if( iCol==nCol+1 ){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
bSeenRank = 1;
}else{
bSeenMatch = 1;
idxStr[iIdxStr++] = 'm';
if( iCol<nCol ){
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
idxStr += strlen(&idxStr[iIdxStr]);
assert( idxStr[iIdxStr]=='\0' );
}
}
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
pInfo->aConstraintUsage[i].omit = 1;
}
}else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
int j;
for(j=1; j<ArraySize(aConstraint); j++){
struct Constraint *pC = &aConstraint[j];
if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
pC->iConsIndex = i;
idxFlags |= pC->fts5op;
}
else if( p->usable && bSeenEq==0
&& p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
){
idxStr[iIdxStr++] = '=';
bSeenEq = 1;
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
}
}
if( bSeenEq==0 ){
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
if( p->iColumn<0 && p->usable ){
int op = p->op;
if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){
if( bSeenLt ) continue;
idxStr[iIdxStr++] = '<';
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
bSeenLt = 1;
}else
if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){
if( bSeenGt ) continue;
idxStr[iIdxStr++] = '>';
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
bSeenGt = 1;
}
}
}
}
idxStr[iIdxStr] = '\0';
/* Set idxFlags flags for the ORDER BY clause */
if( pInfo->nOrderBy==1 ){
int iSort = pInfo->aOrderBy[0].iColumn;
if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
idxFlags |= FTS5_BI_ORDER_RANK;
}else if( iSort==-1 ){
idxFlags |= FTS5_BI_ORDER_ROWID;
@ -583,26 +636,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
}
/* Calculate the estimated cost based on the flags set in idxFlags. */
bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
}else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
}else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
if( bSeenEq ){
pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
}else if( bSeenLt && bSeenGt ){
pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
}else if( bSeenLt || bSeenGt ){
pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
}else{
pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
}
/* Assign argvIndex values to each constraint in use. */
iNext = 1;
for(i=0; i<ArraySize(aConstraint); i++){
struct Constraint *pC = &aConstraint[i];
if( pC->iConsIndex>=0 ){
pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
}
pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
}
pInfo->idxNum = idxFlags;
@ -925,7 +967,7 @@ static int fts5CursorFirstSorted(
**
** If SQLite a built-in statement cache, this wouldn't be a problem. */
rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
"SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
"SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s",
pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
(zRankArgs ? ", " : ""),
(zRankArgs ? zRankArgs : ""),
@ -981,10 +1023,10 @@ static int fts5SpecialMatch(
assert( pTab->p.base.zErrMsg==0 );
pCsr->ePlan = FTS5_PLAN_SPECIAL;
if( 0==sqlite3_strnicmp("reads", z, n) ){
if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){
pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
}
else if( 0==sqlite3_strnicmp("id", z, n) ){
else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){
pCsr->iSpecial = pCsr->iCsrId;
}
else{
@ -1125,7 +1167,7 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
static int fts5FilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *zUnused, /* Unused */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
@ -1133,19 +1175,17 @@ static int fts5FilterMethod(
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK; /* Error code */
int iVal = 0; /* Counter for apVal[] */
int bDesc; /* True if ORDER BY [rank|rowid] DESC */
int bOrderByRank; /* True if ORDER BY rank */
sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
UNUSED_PARAM(zUnused);
UNUSED_PARAM(nVal);
int i;
int iIdxStr = 0;
Fts5Expr *pExpr = 0;
if( pCsr->ePlan ){
fts5FreeCursorComponents(pCsr);
@ -1158,23 +1198,60 @@ static int fts5FilterMethod(
assert( pCsr->pRank==0 );
assert( pCsr->zRank==0 );
assert( pCsr->zRankArgs==0 );
assert( pTab->pSortCsr==0 || nVal==0 );
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Decode the arguments passed through to this function.
**
** Note: The following set of if(...) statements must be in the same
** order as the corresponding entries in the struct at the top of
** fts5BestIndexMethod(). */
if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
iCol = (idxNum>>16);
assert( iCol>=0 && iCol<=pConfig->nCol );
assert( iVal==nVal );
/* Decode the arguments passed through to this function. */
for(i=0; i<nVal; i++){
switch( idxStr[iIdxStr++] ){
case 'r':
pRank = apVal[i];
break;
case 'm': {
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
if( zText==0 ) zText = "";
if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
iCol = 0;
do{
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
iIdxStr++;
}while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
}else{
iCol = pConfig->nCol;
}
if( zText[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
** indicates that the MATCH expression is not a full text query,
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
goto filter_out;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
}
if( rc!=SQLITE_OK ) goto filter_out;
}
break;
}
case '=':
pRowidEq = apVal[i];
break;
case '<':
pRowidLe = apVal[i];
break;
default: assert( idxStr[iIdxStr-1]=='>' );
pRowidGe = apVal[i];
break;
}
}
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
@ -1201,7 +1278,7 @@ static int fts5FilterMethod(
** (pCursor) is used to execute the query issued by function
** fts5CursorFirstSorted() above. */
assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
assert( nVal==0 && bOrderByRank==0 && bDesc==0 );
assert( pCsr->iLastRowid==LARGEST_INT64 );
assert( pCsr->iFirstRowid==SMALLEST_INT64 );
if( pTab->pSortCsr->bDesc ){
@ -1214,29 +1291,15 @@ static int fts5FilterMethod(
pCsr->ePlan = FTS5_PLAN_SOURCE;
pCsr->pExpr = pTab->pSortCsr->pExpr;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}else if( pMatch ){
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
if( zExpr==0 ) zExpr = "";
}else if( pCsr->pExpr ){
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
if( rc==SQLITE_OK ){
if( zExpr[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
** indicates that the MATCH expression is not a full text query,
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
if( bOrderByRank ){
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
}else{
char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
}else{
pCsr->ePlan = FTS5_PLAN_MATCH;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}
}
pCsr->ePlan = FTS5_PLAN_MATCH;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}
}
}else if( pConfig->zContent==0 ){
@ -1253,7 +1316,7 @@ static int fts5FilterMethod(
);
if( rc==SQLITE_OK ){
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
}else{
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
@ -1262,6 +1325,8 @@ static int fts5FilterMethod(
}
}
filter_out:
sqlite3Fts5ExprFree(pExpr);
pConfig->pzErrmsg = pzErrmsg;
return rc;
}
@ -2232,7 +2297,7 @@ static void fts5ApiCallback(
iCsrId = sqlite3_value_int64(argv[0]);
pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
if( pCsr==0 ){
if( pCsr==0 || pCsr->ePlan==0 ){
char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
sqlite3_result_error(context, zErr, -1);
sqlite3_free(zErr);

View File

@ -138,7 +138,9 @@ static int fts5StorageGetStmt(
}else{
int f = SQLITE_PREPARE_PERSISTENT;
if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
p->pConfig->bLock++;
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
p->pConfig->bLock--;
sqlite3_free(zSql);
if( rc!=SQLITE_OK && pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));

View File

@ -253,5 +253,20 @@ do_execsql_test 6.2 {
SELECT name FROM sqlite_master;
} {}
#---------------------------------------------------------------------------
# Check that an fts5 table cannot be its own content table.
#
reset_db
do_execsql_test 7.1 {
CREATE VIRTUAL TABLE t1 USING fts5(a, c=t1 );
INSERT INTO t1( a ) VALUES('abc');
}
do_catchsql_test 7.2 {
SELECT * FROM t1;
} {1 {recursively defined fts5 content table}}
do_catchsql_test 7.3 {
SELECT * FROM t1('abc');
} {1 {recursively defined fts5 content table}}
finish_test

View File

@ -767,7 +767,7 @@ SELECT * FROM t1 WHERE t1 MATCH 'abandon';
do_catchsql_test 13.1 {
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
} {1 {vtable constructor failed: t1}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -958,7 +958,7 @@ do_test 15.0 {
do_catchsql_test 15.1 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#---------------------------------------------------------------------------
#
@ -3903,19 +3903,19 @@ do_test 33.0 {
| end crash-fed6e90021ba5d.db
}]} {}
do_execsql_test 33.1 {
do_catchsql_test 33.1 {
CREATE VIRTUAL TABLE t2 USING fts5vocab('t1','row');
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col');
CREATE VIRTUAL TABLE t4 USING fts5vocab('t1','instance');
}
} {/*malformed database schema*/}
do_catchsql_test 33.2 {
SELECT * FROM t2;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
do_catchsql_test 33.3 {
SELECT * FROM t2, t3, t4 WHERE t2.term=t3.term AND t3.term=t4.term;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -4637,17 +4637,17 @@ do_test 37.0 {
do_catchsql_test 37.1 {
SELECT * FROM t3;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 37.0 {
do_execsql_test 37a.0 {
CREATE VIRTUAL TABLE t1 USING fts5(b, c);
INSERT INTO t1 VALUES('a', 'b');
SELECT quote(block) FROM t1_data WHERE rowid=10;
} {X'000000000101010001010101'}
do_execsql_test 37.1 {
do_execsql_test 37a.1 {
UPDATE t1_data SET block = X'FFFFFFFF0101010001010101' WHERE rowid = 10;
SELECT rowid FROM t1('a');
} {1}
@ -4894,7 +4894,7 @@ do_test 38.0 {
do_catchsql_test 38.1 {
UPDATE t1 SET b=quote(zeroblob(200)) WHERE t1 MATCH 'thread*';
} {0 {}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -5326,16 +5326,16 @@ do_test 40.0 {
| end crash2.txt.db
}]} {}
do_execsql_test 40.1 {
do_catchsql_test 40.1 {
BEGIN;
INSERT INTO t1(b) VALUES(X'819192e578de3fa24af3733ca8769291a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bf');
INSERT INTO t1(b) VALUES(X'c8ae0d0e7c3175946e62ba2b449511d4eb504079984a20f77969f62206c9f3d7ea25358ab705e6978627290b6d48db9032f815a06a79a4f4b809841a0942eed12954ed166f666111812a508abc3bec87958846edaec0a6fe14564bc0a4b78f1c35ebcacca6bae29cc37ae9b59d8a2d7593af1e47dda0ece2268a98d20febafad037964f139851f9a57f48b3706b01721769071991412044cd6006f1d72eb6eb4aa5ad77e378176db8c15575fbeee47165e38a7c6c5a557ac2dfe11813976eaf6741cf593a9e457053a3c34cddfbe605a6e25419f993de8374fafcd3636509d8416a51dc7bcc14cfca322ae343078f47e23522431c17d0da0c033');
INSERT INTO t1(b) VALUES(X'dc29a94e873a45a4243fce9b912aaefbadf1d0423e0345793874b356eeb500b92fb05284c1601fe9bad3143f72162f10242cec27c44ebf764c8fc9fb0824e32c4161472a4f914f579e0e8274f08ca1a02e59b9d8eec1f31061f9ccb9ed97a6f06534e991f7992c761489e6a7724f6e9c2b581e77487ded3a986d53c4419bbd3e9747cee300e670dd7294874c77e2ed48da68eaa6c3ec954a09ac410493d98e34d6686e54fbbe80696705f10e040c66093efb40746b33600685c94c664c7942835a9e954866121d5dcfb2cb12e92521ea3df175ee17072502dad9b9c1565f801b2179799011eb7418bfa00323e3157589e648ff7378be233c79b7');
}
} {/*malformed database schema*/}
do_catchsql_test 40.2 {
INSERT INTO t1(a,b) VALUES(1,11),(2,22),(3, true ),(4,44);
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -5789,7 +5789,7 @@ do_test 43.0 {
do_catchsql_test 43.1 {
INSERT INTO t1(t1) VALUES('optimize');
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -6047,7 +6047,7 @@ do_catchsql_test 45.2 {
INSERT INTO t1(t1, rank) VALUES('merge', 5);
INSERT INTO t1(t1, rank) VALUES('merge', 5);
INSERT INTO t1(t1, rank) VALUES('merge', 5);
} {0 {}}
} {/*malformed database schema*/}
#--------------------------------------------------------------------------
reset_db
@ -6265,7 +6265,7 @@ do_test 46.0 {
do_catchsql_test 46.1 {
SELECT snippet(t1,'[','', '--',-1,10) FROM t1('*');
} {0 {{}}}
} {/*malformed database schema*/}
#--------------------------------------------------------------------------
reset_db
@ -6418,7 +6418,7 @@ do_test 47.0 {
do_catchsql_test 47.1 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
do_catchsql_test 47.2 {
SELECT count(*) FROM (
@ -6426,7 +6426,7 @@ do_catchsql_test 47.2 {
highlight(t1, 2, '[', ']') FROM t1('g h')
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank
)
} {0 3}
} {/*malformed database schema*/}
#--------------------------------------------------------------------------
reset_db
@ -6908,7 +6908,7 @@ do_catchsql_test 50.1 {
#-------------------------------------------------------------------------
reset_db
do_execsql_test 51.1 {
do_execsql_test 51.0 {
BEGIN TRANSACTION;
PRAGMA writable_schema=ON;
CREATE VIRTUAL TABLE t1 USING fts5(a,b,c);
@ -6976,7 +6976,7 @@ COMMIT;
do_catchsql_test 51.1 {
SELECT max(rowid)==0 FROM t1('e*');
} {0 0}
} {1 {database disk image is malformed}}
#--------------------------------------------------------------------------
reset_db
@ -7130,7 +7130,7 @@ do_test 52.0 {
do_catchsql_test 52.1 {
SELECT fts5_decode(id, block) FROM t1_data;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -7346,7 +7346,7 @@ do_test 53.0 {
do_catchsql_test 53.1 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x<>1 FROM c WHERE x<10)
INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -7562,7 +7562,7 @@ do_test 54.0 {
do_catchsql_test 54.1 {
SELECT rowid==-1 FROM t1('t*');
} {0 {0 0 0}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -7777,10 +7777,10 @@ do_test 55.0 {
| end crash-b366b5ac0d3887.db
}]} {}
do_execsql_test 55.1 {
do_catchsql_test 55.1 {
SAVEPOINT one;
DELETE FROM t1 WHERE a MATCH 'ts';
}
} {/*malformed database schema*/}
do_execsql_test 55.2 {
ROLLBACK TO one;
@ -8013,7 +8013,7 @@ do_test 56.1 {
set res "1 {database disk image is malformed}"
}
set res
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -8131,7 +8131,7 @@ do_test 57.0 {
do_catchsql_test 57.1 {
INSERT INTO t1(t1) VALUES('optimize')
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
reset_db
@ -8339,9 +8339,9 @@ do_test 58.0 {
| end crash-5a5acd0ab42d31.db
}]} {}
do_execsql_test 58.1 {
do_catchsql_test 58.1 {
SELECT * FROM t1('t*');
} {{} {} {} {} {} {}}
} {/*malformed database schema*/}
#-------------------------------------------------------------------------
do_test 59.0 {
@ -8544,7 +8544,7 @@ do_test 59.0 {
do_catchsql_test 59.1 {
SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*eŸ'
} {0 {}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
do_test 60.0 {
@ -8750,7 +8750,7 @@ do_test 60.0 {
do_catchsql_test 60.2 {
SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ'
} {0 {}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
do_test 61.0 {
@ -8948,13 +8948,13 @@ do_test 61.0 {
| end crash-e5fa281edabddf.db
}]} {}
do_execsql_test 61.1 {
do_catchsql_test 61.1 {
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1'(),'col' );
}
} {/*malformed database schema*/}
do_catchsql_test 61.2 {
SELECT * FROM t3 ORDER BY rowid;
} {1 {database disk image is malformed}}
} {/*malformed database schema*/}
breakpoint
#-------------------------------------------------------------------------
@ -9159,7 +9159,622 @@ do_test 62.0 {
do_catchsql_test 62.1 {
WITH c(x) AS (VALUES(false) UNION ALL SELECT x+1 FROM c WHERE x<72)
INSERT INTO t1(a) SELECT randomblob(2829) FROM c;
} {0 {}}
} {/*malformed database schema*/}
#---------------------------------------------------------------------------
do_test 63.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 24576 pagesize 4096 filename crash-8230e6c3b368f5.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
| 96: 00 00 00 00 0d 00 00 00 06 0e 0f 00 0f aa 0f 53 ...............S
| 112: 0e e8 0e 8b 0e 33 0e 0f 00 00 00 00 00 00 00 00 .....3..........
| 3584: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 ................
| 3600: 06 06 17 11 11 01 31 74 61 62 7c 65 62 63 62 62 ......1tab|ebcbb
| 3616: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 62 62 .CREATE TABLE bb
| 3632: 28 61 29 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 (a)V.......table
| 3648: 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 t1_configt1_conf
| 3664: 69 67 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 ig.CREATE TABLE
| 3680: 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 't1_config'(k PR
| 3696: 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 57 49 IMARY KEY, v) WI
| 3712: 54 48 4f 55 54 20 52 4f 57 49 44 5b 04 07 17 21 THOUT ROWID[...!
| 3728: 21 01 81 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 !...tablet1_docs
| 3744: 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 izet1_docsize.CR
| 3760: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 9d EATE TABLE 't1_.
| 3776: 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 54 45 47 ocsize'(id INTEG
| 3792: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 3808: 73 7a 20 42 4c 4f 42 29 69 03 07 17 19 19 01 81 sz BLOB)i.......
| 3824: 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 -tablet1_idxt1_i
| 3840: 64 78 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 dx.CREATE TABLE
| 3856: 27 74 31 5f 69 64 78 27 28 73 65 67 69 64 2c 20 't1_idx'(segid,
| 3872: 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d term, pgno, PRIM
| 3888: 41 52 59 20 4b 45 59 28 73 65 67 69 64 2c 20 74 ARY KEY(segid, t
| 3904: 65 72 6d 29 29 20 57 49 54 48 4f 55 54 20 52 4f erm)) WITHOUT RO
| 3920: 57 49 44 55 02 07 17 1b 1b 01 81 01 74 61 62 6c WIDU........tabl
| 3936: 65 64 31 5f 64 61 74 61 74 31 5f 64 61 74 61 02 ed1_datat1_data.
| 3952: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
| 3968: 5f 64 61 74 61 27 28 69 64 20 49 4e 54 45 47 45 _data'(id INTEGE
| 3984: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 R PRIMARY KEY, b
| 4000: 6c 6f 63 6b 20 42 4c 4f 42 29 54 01 07 17 10 11 lock BLOB)T.....
| 4016: 08 81 15 74 61 62 6c 65 74 31 74 31 43 52 45 41 ...tablet1t1CREA
| 4032: 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c 45 TE VIRTUAL TABLE
| 4048: 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 28 61 t1 USING fts5(a
| 4064: 2c 62 2c 70 72 65 66 69 78 3d 22 31 2c 32 2c 33 ,b,prefix=.1,2,3
| 4080: 2c 34 22 2c 20 63 6f 6e 74 65 6e 74 3d 22 22 29 ,4., content=..)
| page 2 offset 4096
| 0: 0d 0b 6a 00 37 09 4c 02 0f e7 09 4c 0f c6 0f a4 ..j.7.L....L....
| 16: 0f 88 0f 6d 0f 4b 0f 2c 0f 0e 0e ec 0e cd 0e ad ...m.K.,........
| 32: 0e 8e 0e 6c 0e 4b 0e 29 0e 08 0d e6 0d c4 0d b5 ...l.K.)........
| 48: 0d 97 0d 76 0d 54 0d 31 0d 15 0c f3 0c d3 0c b5 ...v.T.1........
| 64: 0c 95 0c 73 0c 54 0c 32 0c 10 0b ee 0b cc 0b b0 ...s.T.2........
| 80: 0b 8d 0b 7e 0b 48 0b 2e 0b 0b 0a ef 0a cc 0a ad ...~.H..........
| 96: 0a 8c 0a 6d 0a 4d 0a 2b 0a 0c 09 ec 09 ca 09 a8 ...m.M.+........
| 112: 09 86 09 63 0f f1 00 00 00 00 00 00 00 00 00 00 ...c............
| 2368: 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 03 00 ................
| 2384: 30 00 00 00 01 01 03 35 00 03 01 01 12 02 01 12 0......5........
| 2400: 03 01 11 1c 8c 80 80 80 80 10 03 00 3e 00 00 00 ............>...
| 2416: 17 01 05 05 34 74 61 62 6c 03 02 03 01 04 77 68 ....4tabl.....wh
| 2432: 65 72 03 02 06 09 1b 8c 80 80 80 80 0f 03 00 3c er.............<
| 2448: 00 00 00 16 05 34 66 74 73 34 03 02 02 01 04 6e .....4fts4.....n
| 2464: 75 6d 62 03 06 01 04 09 1b 8c 80 80 80 80 0e 03 umb.............
| 2480: 00 3c 00 00 00 16 04 33 74 68 65 13 06 01 01 04 .<.....3the.....
| 2496: 01 03 77 68 65 03 02 04 04 0a 1b 8c 80 80 80 80 ..whe...........
| 2512: 0d 03 00 3c 00 00 00 16 04 33 6e 75 6d 03 06 01 ...<.....3num...
| 2528: 01 05 01 03 75 61 62 03 02 03 04 0a 19 8c 80 80 ....uab.........
| 2544: 80 80 0c 03 00 38 00 00 00 14 03 32 ec 68 03 02 .....8.....2.h..
| 2560: 04 00 04 33 66 74 73 03 02 02 04 07 18 8c 80 80 ...3fts.........
| 2576: 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 03 02 .....6.....2ta..
| 2592: 03 02 01 68 03 06 01 01 04 04 17 1b 8c 80 80 80 ...h............
| 2608: 80 0a 03 00 3c 00 00 00 16 03 32 6e 75 03 06 01 ....<.....2nu...
| 2624: 01 05 01 02 6f 66 03 06 01 01 06 04 09 19 8c 80 ....of..........
| 2640: 80 80 80 09 03 00 38 00 00 00 14 03 32 66 74 03 ......8.....2ft.
| 2656: 02 02 01 02 69 73 03 06 01 01 03 04 07 18 8c 80 ....is..........
| 2672: 80 80 80 08 03 00 36 00 00 00 13 02 31 74 03 08 ......6.....1t..
| 2688: 03 01 01 04 01 01 77 03 02 04 04 09 1a 8c 80 80 ......w.........
| 2704: 80 80 07 03 00 3a 00 00 00 15 02 31 6e 03 08 01 .....:.....1n...
| 2720: 01 02 05 01 01 6f 03 06 01 01 06 04 09 18 8c 80 .....o..........
| 2736: 80 80 80 06 03 00 36 00 00 00 13 04 02 31 66 03 ......6......1f.
| 2752: 02 02 01 01 69 03 06 01 01 03 05 06 1c 8c 80 80 ....i...........
| 2768: 80 80 05 03 00 3e 00 00 00 17 04 30 74 68 65 03 .....>.....0the.
| 2784: 06 01 01 04 01 05 77 68 65 72 65 03 02 04 0a 15 ......where.....
| 2800: 8c 80 80 80 80 04 03 00 30 00 00 00 11 01 01 06 ........0.......
| 2816: 06 30 74 61 62 6c 65 03 02 03 07 1c 8c 80 80 80 .0table.........
| 2832: 80 03 03 00 3e 00 00 00 17 07 30 6e 75 6d 62 65 ....>.....0numbe
| 2848: 72 03 06 01 01 05 01 02 6f 66 03 06 04 0d 13 8c r.......of......
| 2864: 80 80 80 80 02 03 00 2c 00 00 00 0f 01 01 03 02 .......,........
| 2880: 30 6e 03 06 01 01 02 07 1b 8c 80 80 80 80 01 03 0n..............
| 2896: 00 3c 00 00 00 16 08 30 66 74 73 34 61 75 78 03 .<.....0fts4aux.
| 2912: 02 02 01 02 69 73 03 06 04 0c 00 00 00 14 2a 00 ....is........*.
| 2928: 00 00 01 01 02 24 00 02 01 01 12 02 01 12 08 88 .....$..........
| 2944: 80 80 80 80 12 03 00 16 00 00 00 05 02 1c 88 80 ................
| 2960: 80 80 80 11 03 00 3e 00 00 00 17 05 34 72 6f 77 ......>.....4row
| 2976: 73 02 06 01 01 05 01 04 74 68 65 72 02 02 04 0b s.......ther....
| 2992: 15 88 80 80 80 80 10 03 00 30 00 00 00 11 02 01 .........0......
| 3008: 01 07 05 34 62 65 74 77 02 02 04 08 1b 88 80 80 ...4betw........
| 3024: 80 80 0f 03 00 3c 00 00 00 16 04 04 33 72 6f 77 .....<......3row
| 3040: 02 06 01 01 05 01 03 74 68 64 02 08 05 0a 1b 88 .......thd......
| 3056: 80 80 80 80 0e 03 00 3c 00 00 00 16 01 01 02 04 .......<........
| 3072: 33 61 72 65 02 02 03 01 03 62 65 74 02 02 07 08 3are.....bet....
| 3088: 1b 88 80 80 80 80 0d 03 00 3c 00 00 00 16 03 32 .........<.....2
| 3104: 74 68 02 08 02 01 01 07 00 04 33 61 6e 64 02 06 th........3and..
| 3120: 04 0a 1b 88 80 80 80 80 0c 03 00 3c 00 00 00 16 ...........<....
| 3136: 03 32 69 6e 02 06 01 01 06 01 02 72 6f 02 06 01 .2in.......ro...
| 3152: 01 43 04 09 18 88 80 80 80 80 0b 03 00 36 00 00 .C...........6..
| 3168: 00 13 02 03 32 61 72 02 02 03 01 02 62 65 02 02 ....2ar.....be..
| 3184: 04 05 07 1b 88 80 80 80 80 0a 03 00 3c 00 00 00 ............<...
| 3200: 16 02 31 74 02 08 02 01 01 07 00 03 32 61 6e 02 ..1t........2an.
| 3216: 06 01 01 04 09 19 88 80 80 80 80 09 03 00 38 00 ..............8.
| 3232: 00 00 14 02 31 6e 02 06 01 01 03 01 01 72 02 06 ....1n.......r..
| 3248: 01 01 05 04 08 17 88 80 80 80 80 08 03 00 34 00 ..............4.
| 3264: 00 00 12 02 31 62 02 02 04 01 01 69 02 06 01 01 ....1b.....i....
| 3280: 06 04 06 19 88 80 80 80 80 07 03 00 38 00 00 00 ............8...
| 3296: 14 04 02 31 32 02 02 05 01 01 61 02 08 03 01 01 ...12.....a.....
| 3312: 02 05 06 1b 88 80 80 80 80 06 03 00 3c 00 00 00 ............<...
| 3328: 16 06 30 74 68 65 72 65 02 02 01 00 02 30 21 02 ..0there.....0!.
| 3344: 06 01 01 04 0a 15 88 80 80 80 80 05 03 00 30 00 ..............0.
| 3360: 00 00 11 01 01 05 04 30 74 68 65 02 06 01 01 07 .......0the.....
| 3376: 07 1c 88 80 80 80 80 04 03 00 3e 00 00 00 17 01 ..........>.....
| 3392: 01 06 02 30 6e 02 06 01 01 03 01 04 72 6f 77 73 ...0n.......rows
| 3408: 02 06 07 08 1b 88 80 80 80 80 03 03 00 3c 00 51 .............<.Q
| 3424: 00 16 08 30 62 65 74 77 65 65 6e 02 02 04 01 02 ...0between.....
| 3440: 69 6e 02 06 04 0c 1a 88 80 80 80 80 02 03 00 3a in.............:
| 3456: 00 00 00 15 04 30 61 6e 64 02 06 01 01 02 02 02 .....0and.......
| 3472: 72 65 02 02 03 04 0a 17 88 80 80 80 80 01 03 00 re..............
| 3488: 34 00 00 00 12 02 30 31 02 06 01 01 04 01 01 32 4.....01.......2
| 3504: 02 02 05 04 08 08 84 80 80 80 80 12 03 00 16 00 ................
| 3520: 00 00 05 04 1b 84 80 80 80 80 11 03 00 3c 00 00 .............<..
| 3536: 00 16 05 34 74 51 62 6c 01 06 01 01 05 02 03 65 ...4tQbl.......e
| 3552: 72 6d 01 02 04 0b 1b 84 80 80 80 80 10 03 00 3c rm.............<
| 3568: 00 00 00 16 05 34 65 17 63 68 01 02 03 01 04 70 .....4e.ch.....p
| 3584: 72 65 73 01 02 05 04 09 1a 84 80 80 80 80 0f 03 res.............
| 3600: 00 3a 00 00 00 15 04 33 74 65 72 01 02 04 02 02 .:.....3ter.....
| 3616: 68 65 01 06 01 01 03 04 08 1b 84 80 80 80 80 0e he..............
| 3632: 03 00 3c 00 00 00 16 04 33 70 72 65 01 02 05 01 ..<.....3pre....
| 3648: 03 74 61 62 01 06 01 01 05 04 08 1a 84 80 80 80 .tab............
| 3664: 80 0d 03 00 3a 00 00 00 15 04 33 66 6f 72 01 03 ....:.....3for..
| 3680: 02 02 02 74 73 01 06 01 01 04 04 08 1b 84 80 80 ...ts...........
| 3696: 80 80 0c 03 00 3c 00 00 00 16 03 32 74 68 01 06 .....<.....2th..
| 3712: 01 01 03 00 04 33 65 61 63 01 02 03 04 09 18 84 .....3eac.......
| 3728: 80 80 80 80 0b 03 00 36 00 00 00 13 03 32 74 61 .......6.....2ta
| 3744: 01 06 01 01 05 02 01 65 01 02 04 04 09 19 84 80 .......e........
| 3760: 80 80 80 0a 03 00 38 00 00 00 14 03 32 69 6e 01 ......8.....2in.
| 3776: 06 01 01 02 01 02 70 72 01 02 05 04 09 18 84 80 ......pr........
| 3792: 80 80 80 09 03 00 36 00 00 00 13 03 32 66 6f 01 ......6.....2fo.
| 3808: 02 02 02 01 74 01 06 01 01 04 04 07 1b 84 80 80 ....t...........
| 3824: 80 80 08 03 00 3c 00 00 00 16 02 31 74 01 0a 04 .....<.....1t...
| 3840: 01 01 03 04 00 03 32 65 61 01 02 03 04 0a 17 84 ......2ea.......
| 3856: 80 80 80 80 07 03 00 34 00 00 00 12 02 31 69 01 .......4.....1i.
| 3872: 06 01 01 02 01 01 70 01 02 05 04 08 18 84 80 80 ......p.........
| 3888: 80 80 06 03 00 36 00 00 00 12 02 31 65 01 02 02 .....6.....1e...
| 3904: 01 01 66 01 08 02 01 01 04 04 06 1b 84 80 80 80 ..f.............
| 3920: 80 05 03 00 3c 00 00 00 16 05 30 74 65 72 6d 01 ....<.....0term.
| 3936: 02 04 02 02 68 65 01 06 01 01 03 04 09 14 84 80 ....he..........
| 3952: 80 80 80 04 03 00 2e 00 00 00 10 06 30 74 61 62 ............0tab
| 3968: 6c 65 01 06 01 01 05 04 15 84 80 80 80 80 03 03 le..............
| 3984: 00 30 00 00 00 11 02 08 30 70 72 65 73 65 6e 74 .0......0present
| 4000: 01 02 05 05 1b 84 80 80 80 80 02 03 00 3c 00 00 .............<..
| 4016: 00 16 04 30 66 74 73 01 06 01 01 04 01 02 69 6e ...0fts.......in
| 4032: 01 06 01 01 04 0a 1a 84 80 80 80 80 01 03 00 3a ...............:
| 4048: 00 00 00 15 05 30 65 61 63 68 01 02 03 01 03 66 .....0each.....f
| 4064: 6f 72 01 02 01 f4 09 06 01 03 00 12 03 0b 0f 00 or..............
| 4080: 00 08 8c 80 80 80 80 11 03 00 16 00 00 00 05 04 ................
| page 3 offset 8192
| 0: 0a 00 00 00 32 0e 4f 00 0f fa 0f f1 0f e9 0f e1 ....2.O.........
| 16: 0f d8 0f d1 0f c9 0f c1 0f b9 0f b1 0f a9 0f a0 ................
| 32: 0f 98 0f 90 0f 87 0f 80 0f 78 0f 71 0f 68 0f 5f .........x.q.h._
| 48: 0f 56 0f 4d 0f 41 0f 38 0f 2f 0f 26 0f 1d 0f 13 .V.M.A.8./.&....
| 64: 0f 0a 0f 01 0e f7 0e ee 0e e6 0e dd 0e d6 0e cd ................
| 80: 0e c3 0e ba 0e b0 0e a8 0e 9f 0e 00 00 00 00 00 ................
| 3648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
| 3664: 04 01 10 01 03 34 74 20 07 04 01 0e 01 03 34 1e .....4t ......4.
| 3680: 09 04 01 12 01 03 33 74 68 1c 08 04 01 10 01 03 ......3th.......
| 3696: 33 6e 1a 08 04 01 10 01 03 32 77 18 08 04 01 10 3n.......2w.....
| 3712: 01 03 32 74 16 08 04 01 10 01 03 32 6e 14 07 04 ..2t.......2n...
| 3728: 01 0e 01 03 32 12 08 04 01 10 01 03 31 74 10 07 ....2.......1t..
| 3744: f4 01 10 01 03 31 6e 0e 07 04 01 0e 01 03 31 0c .....1n.......1.
| 3760: 09 04 01 12 01 03 30 74 68 0a 08 04 01 10 01 03 ......0th.......
| 3776: 30 74 08 09 04 01 12 01 03 30 6e 75 06 08 04 01 0t.......0nu....
| 3792: 10 01 03 30 6e 04 06 04 01 0c 01 03 02 08 04 01 ...0n...........
| 3808: 10 01 02 34 73 22 07 04 01 0e 01 02 34 20 08 04 ...4s.......4 ..
| 3824: 01 10 01 02 33 72 1e 09 04 01 12 01 02 33 61 72 ....3r.......3ar
| 3840: 1c 08 04 01 10 01 02 32 74 1a 08 04 01 10 01 02 .......2t.......
| 3856: 32 69 18 09 04 01 12 01 02 32 61 72 16 08 04 01 2i.......2ar....
| 3872: 10 01 02 31 74 14 08 04 01 10 01 02 31 6e 12 08 ...1t.......1n..
| 3888: 04 01 10 01 02 31 62 10 08 04 01 10 01 02 31 32 .....1b.......12
| 3904: 0e 0b 04 01 16 01 02 30 74 00 00 00 00 00 00 00 .......0t.......
| page 4 offset 12288
| 4064: 00 00 00 00 00 00 00 00 00 00 00 05 02 03 00 10 ................
| 4080: 03 05 05 02 03 00 10 04 06 05 01 03 00 10 04 04 ................
| page 5 offset 16384
| 0: 0a 00 00 00 02 0f eb 00 0f eb 0f f4 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 08 03 15 01 70 ...............p
| 4080: 67 73 7a 08 0b 03 1b 01 76 65 72 73 69 6f 6e 04 gsz.....version.
| end crash-8230e6c3b368f5.db
}]} {}
do_catchsql_test 63.1 {
SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*';
} {/*malformed database schema*/}
do_catchsql_test 63.2 {
INSERT INTO t1(t1) VALUES('optimize');
} {/*malformed database schema*/}
do_catchsql_test 63.3 {
SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*';
} {/*malformed database schema*/}
#---------------------------------------------------------------------------
do_test 64.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-4470f0b94422f7.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j
| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 01 00 00 .....=..........
| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet
| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con
| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE
| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k
| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v)
| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^..
| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d
| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz
| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE '
| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id
| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)]..
| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c
| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten
| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE '
| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id
| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l...
| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id
| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE
| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'(
| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn
| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s
| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT
| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX.....
| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data
| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE
| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data'
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B
| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl
| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI
| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b)
| page 2 offset 4096
| 0: 0d 0f 44 00 05 0e 81 00 0f 1a 0e 81 0f af 0f 58 ..D............X
| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0..........
| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$......
| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e.....
| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................
| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................
| 3792: 07 f3 03 02 01 65 03 1e 03 05 05 04 05 05 01 00 .....e..........
| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 06 05 04 ........6.......
| 3824: 06 05 04 05 05 01 01 03 06 04 04 06 04 04 06 04 ................
| 3840: 04 06 04 03 03 01 65 03 14 04 05 06 f5 05 01 01 ......e.........
| 3856: 02 08 09 01 20 04 05 07 05 07 05 07 05 05 01 00 .... ...........
| 3872: 02 08 0a 0a 0a 04 01 65 03 02 0a 01 06 0a 0a 0a .......e........
| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e.............
| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*.......
| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P.......
| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e......
| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e....
| 3968: 05 04 05 05 01 01 03 06 04 04 06 04 03 03 01 65 ...............e
| 3984: 02 14 04 05 07 05 05 01 01 02 08 0a 04 01 65 02 ..............e.
| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1
| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e
| 4032: 01 10 02 05 05 01 01 04 03 03 02 01 65 01 12 03 ............e...
| 4048: 05 05 01 01 03 06 04 03 03 01 65 01 0e 04 05 05 ..........e.....
| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL.
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 03 0f ec 00 0f 00 00 00 00 00 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 04 0e 1a 00 0f c7 0f 5b 0e ef 0e 1a ...........[....
| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R....
| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee
| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 66 20 65 eee e ee eeef e
| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 3664: 20 65 65 20 65 65 65 65 20 65 65 20 65 65 65 20 ee eeee ee eee
| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee
| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e
| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e
| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 65 65 20 65 e e e e ee eee e
| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 1f 65 e eeeee ee e e.e
| 3760: 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 65 ee eee ee eeeee
| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee
| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 20 65 ee eeeee ee e e
| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej
| 3824: 03 03 ff 75 71 65 20 65 65 1f 65 65 65 20 65 20 ...uqe ee.eee e
| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee
| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee
| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee
| 3888: 65 20 65 20 65 20 65 65 20 65 65 65 20 65 65 20 e e e ee eee ee
| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 20 65 eeeee ee e e e e
| 3920: 65 20 65 65 65 20 65 65 20 65 65 6a 02 04 00 75 e eee ee eej...u
| 3936: 40 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 @e ee eee e ee e
| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee
| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e
| 3984: 65 20 65 65 65 65 65 65 20 65 65 20 65 20 65 20 e eeeeee ee e e
| 4000: 65 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 e ee eee ee eeee
| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee
| 4032: 65 20 65 65 20 65 65 37 01 04 00 41 3f 65 20 65 e ee ee7...A?e e
| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e
| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e
| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee
| page 5 offset 16384
| 0: 0d 00 00 00 04 0f e4 00 0f f9 0f f2 0f eb 0f e4 ................
| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 03 03 00 10 .........!!.....
| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................
| page 6 offset 20480
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-4470f0b94422f7.db
}]} {}
do_catchsql_test 64.1 {
SELECT * FROM ttt('e*');
} {1 {database disk image is malformed}}
#---------------------------------------------------------------------------
do_test 65.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-3aef66940ace0c.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 00 00 00 00 ...k............
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 3776: 63 30 2c 20 63 31 2c d6 63 32 29 69 04 07 17 19 c0, c1,.c2)i....
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
| page 3 offset 8192
| 0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00 ................
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30 ...........21160
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1 609...........3.
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 01 02 ..........5.....
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 3d ......0000000..=
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
| 3328: 01 02 02 03 06 01 01 f2 03 06 4e 02 02 03 06 01 ..........N.....
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
| 3408: 62 73 74 61 74 07 02 03 01 02 13 01 02 03 02 04 bstat...........
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 07 65 ebug...........e
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
| 3472: 01 02 02 01 02 01 f1 02 02 01 02 02 01 02 02 01 ................
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
| 3504: 02 01 02 02 02 08 76 b4 65 6e 73 69 6f 6e 1f 02 ......v.ension..
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
| 3536: 01 02 03 01 02 03 04 01 25 0d 02 03 01 02 03 01 ........%.......
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
| 3568: 02 06 65 6f 70 6f 6c 79 0f f2 03 01 02 03 01 02 ..eopoly........
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
| 3616: 00 03 6d 61 78 1c 02 0c 01 02 02 01 02 02 02 05 ..max...........
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n
| 3664: 6f 63 61 73 65 02 06 01 02 02 13 06 00 f2 02 03 ocase...........
| 3680: 06 01 12 02 13 06 01 02 02 03 06 01 02 02 03 06 ................
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 8e 06 01 02 ................
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe....
| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab.....
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
| 3888: 01 06 01 11 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 3920: 01 01 02 01 06 01 01 01 01 06 01 01 02 01 06 01 ................
| 3936: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
| 3952: 02 01 06 01 01 01 f1 06 01 01 02 ad 06 01 01 02 ................
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3984: 06 01 01 01 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
| 4048: 12 44 13 11 0f 47 13 0e fc 0e 11 10 0f 0e 10 0f .D...G..........
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 4 offset 12288
| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 5 offset 16384
| 0: 0d 00 00 00 24 0c 0a 00 00 00 00 00 00 00 00 00 ....$...........
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 8f DSAFE=0XNOCASE..
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 43 41 46 45 3d ..%..THREADCAFE=
| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM
| 3168: 49 54 20 4b 4f 41 44 21 45 58 54 45 4e 53 49 4f IT KOAD!EXTENSIO
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
| 3232: 4f 4d 59 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMYT LOAD EXTENS
| 3248: 49 4f 4e 58 52 54 56 a9 4d 1f 1e 05 00 33 0f 19 IONXRTV.M....3..
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
| 3280: 30 30 30 57 42 49 4e 31 52 59 1f 1d 05 00 33 0f 000WBIN1RY....3.
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 32 0000XNOCASE....2
| 3328: 0f 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 ..NAX MEMORY-500
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
| 3392: 4c 45 20 52 54 52 45 45 59 4e 4f 43 41 53 45 17 LE RTREEYNOCASE.
| 3408: 19 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 .f.%..ENABLE RTR
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
| 3440: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49 NABLE MEMSYS5XBI
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
| 3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 E MEMSYS5XNOCASE
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 10 25 MSYS5XRTRIM....%
| 3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN@BLE JSON1XB
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
| 3552: 4c 45 20 4a 53 4f 4e 32 58 4e 4f 43 41 53 45 17 LE JSON2XNOCASE.
| 3568: 13 05 00 25 0f 17 45 4d 41 42 4c 45 20 4a 53 4f ...%..EMABLE JSO
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 NABLE GEOPOLYXBI
| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4f 81 42 4c NARY....)..EO.BL
| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 51 53 45 E GEOPOLYXNOCQSE
| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE
| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....#
| 3680: 0f 1a 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
| 3712: 45 20 46 54 53 35 48 4e 4f 43 41 53 45 16 1d 05 E FTS5HNOCASE...
| 3728: 00 23 0f a4 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
| 3760: 4c 45 20 46 55 53 34 58 42 49 4e 41 52 59 17 0b LE FUS4XBINARY..
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
| 3792: 57 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e WNOCASE....#..EN
| 3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e ABLE FTS4.RTRIM.
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d TAT VTABXNOCASE.
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 8a 4e 41 52 .....DEBUGXB.NAR
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3f 87 ...C..COMPILER?.
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
| 4064: 45 0d 60 59 4c 45 52 3d 67 63 63 2d 35 2e 34 2d E.`YLER=gcc-5.4-
| 4080: 30 20 32 30 31 36 30 36 30 39 00 00 00 00 00 00 0 20160609......
| page 6 offset 20480
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
| 3824: 06 22 03 01 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 02 01 . ..............
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
| 3968: 06 00 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
| page 7 offset 24576
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| end crash-3aef66940ace0c.db
}]} {}
do_catchsql_test 65.1 {
SELECT ( MATCH (t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ'
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
#
reset_db
do_test 66.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-37cecb4e784e9f.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07 .....@ ........
| 96: 00 00 00 00 0d 00 00 00 07 0d d2 00 0f c4 0f 6d ...............m
| 112: 0f 02 0e ab 0e 4e 0d f6 0d d2 00 00 00 00 00 00 .....N..........
| 3536: 00 00 22 07 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
| 3552: 32 74 32 07 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
| 3568: 20 74 32 28 78 29 56 06 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
| 3584: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
| 3600: 6f 6e 66 69 67 06 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
| 3616: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
| 3632: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
| 3648: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 05 WITHOUT ROWID[.
| 3664: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
| 3680: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
| 3696: 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
| 3712: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
| 3728: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
| 3744: 59 2c 20 73 7a 20 42 4c 4f 42 29 55 04 06 17 21 Y, sz BLOB)U...!
| 3760: 21 01 77 74 61 62 6c 65 74 31 5f 63 6f 6e 74 65 !.wtablet1_conte
| 3776: 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 04 43 52 45 ntt1_content.CRE
| 3792: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f ATE TABLE 't1_co
| 3808: 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 45 ntent'(id INTEGE
| 3824: 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 63 R PRIMARY KEY, c
| 3840: 30 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 0)i.......-table
| 3856: 74 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 t1_idxt1_idx.CRE
| 3872: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 ATE TABLE 't1_id
| 3888: 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 x'(segid, term,
| 3904: 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 pgno, PRIMARY KE
| 3920: 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 Y(segid, term))
| 3936: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 WITHOUT ROWIDU..
| 3952: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 ......tablet1_da
| 3968: 74 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 tat1_data.CREATE
| 3984: 20 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 TABLE 't1_data'
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
| 4016: 41 52 49 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARI KEY, block B
| 4032: 4c 4f 42 29 3a 01 06 17 11 11 08 63 74 61 62 6c LOB):......ctabl
| 4048: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
| 4064: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
| 4080: 4e 47 20 66 74 73 35 28 63 6f 6e 74 65 6e 74 29 NG fts5(content)
| page 2 offset 4096
| 0: 0d 00 00 00 03 0f bd 00 0f e8 0f ef 0f bd 00 01 ................
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 24 84 80 .............$..
| 4032: 80 80 80 01 03 00 4e 00 00 00 1e 06 30 61 62 61 ......N.....0aba
| 4048: 63 6b 01 02 02 04 02 66 74 02 02 02 04 04 6e 64 ck.....ft.....nd
| 4064: 6f 6e 03 02 02 04 0a 07 05 01 03 00 10 03 03 0f on..............
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 00 01 01 ...$............
| page 3 offset 8192
| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 4 offset 12288
| 0: 0d 00 00 00 03 0f e0 00 0f f6 0f ec 0f e0 00 00 ................
| 4064: 0a 03 03 00 1b 61 62 61 6e 64 6f 6e 08 02 03 00 .....abandon....
| 4080: 17 61 62 61 66 74 08 01 03 00 17 61 62 61 63 6b .abaft.....aback
| page 5 offset 16384
| 0: 0d 00 00 00 03 0f ee 00 0f fa 0f f4 0f ee 00 00 ................
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 03 ................
| 4080: 03 00 0e 01 04 02 03 00 0e 01 04 01 03 00 0e 01 ................
| page 6 offset 20480
| 0: 0a 00 00 01 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 7 offset 24576
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e1 0f d6 00 00 ................
| 4048: 00 00 00 00 00 00 09 01 52 1b 72 65 62 75 69 6c ........R.rebuil
| 4064: 64 11 02 02 2b 69 6e 74 65 67 72 69 74 79 2d 63 d...+integrity-c
| 4080: 68 65 63 6b 0a 01 02 1d 6f 70 74 69 6d 69 7a 65 heck....optimize
| end crash-37cecb4e784e9f.db
}]} {}
do_catchsql_test 66.1 {
INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test

View File

@ -147,5 +147,27 @@ do_faultsim_test 5.1 -faults oom* -body {
faultsim_test_result {0 {1 4}}
}
#-------------------------------------------------------------------------
# Test OOM injection in a query with two MATCH expressions
#
reset_db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
INSERT INTO t1 VALUES('a b c d'); -- 1
INSERT INTO t1 VALUES('d a b c'); -- 2
INSERT INTO t1 VALUES('c d a b'); -- 3
INSERT INTO t1 VALUES('b c d a'); -- 4
}
do_faultsim_test 6.1 -faults oom* -body {
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' }
} -test {
faultsim_test_result {0 {1 2 3 4}}
}
do_faultsim_test 6.2 -faults oom* -body {
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' }
} -test {
faultsim_test_result {0 {1 2 3 4}}
}
finish_test

111
ext/fts5/test/fts5misc.test Normal file
View File

@ -0,0 +1,111 @@
# 2019 September 02
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5misc
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
}
do_catchsql_test 1.1.1 {
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*');
} {1 {unknown special query: }}
do_catchsql_test 1.1.2 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*'));
} {1 {unknown special query: }}
do_catchsql_test 1.2.1 {
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id');
} {0 {{}}}
do_catchsql_test 1.2.2 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id'));
} {0 {}}
do_catchsql_test 1.3.1 {
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
} {1 {no such cursor: 1}}
do_catchsql_test 1.3.2 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
db close
sqlite3 db test.db
do_catchsql_test 1.3.3 {
SELECT a FROM t1
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t0(c0);
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
}
do_execsql_test 2.1.1 {
BEGIN TRANSACTION;
INSERT INTO vt0(c0) VALUES ('xyz');
}
do_execsql_test 2.1.2 {
ALTER TABLE t0 ADD COLUMN c5;
}
do_execsql_test 2.1.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.1.4 {
INSERT INTO vt0(c0) VALUES ('abc');
COMMIT
}
do_execsql_test 2.1.5 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
reset_db
do_execsql_test 2.2.1 {
CREATE TABLE t0(c0);
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
BEGIN TRANSACTION;
INSERT INTO vt0(c0) VALUES ('xyz');
}
breakpoint
do_execsql_test 2.2.2 {
ALTER TABLE t0 RENAME TO t1;
}
do_execsql_test 2.2.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.2.4 {
INSERT INTO vt0(c0) VALUES ('abc');
COMMIT;
}
do_execsql_test 2.2.5 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
finish_test

View File

@ -0,0 +1,99 @@
# 2014 September 13
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5multi
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
fts5_aux_test_functions db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
INSERT INTO t1 VALUES('gg bb bb' ,'gg ff gg' ,'ii ii');
INSERT INTO t1 VALUES('dd dd hh kk','jj' ,'aa');
INSERT INTO t1 VALUES('kk gg ee' ,'hh cc' ,'hh jj aa cc');
INSERT INTO t1 VALUES('hh' ,'bb jj cc' ,'kk ii');
INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa' ,'ee');
INSERT INTO t1 VALUES('ee' ,'ff gg kk aa','ee ff ee');
INSERT INTO t1 VALUES('ff jj' ,'gg ee' ,'kk ee gg kk');
INSERT INTO t1 VALUES('ff ee dd hh','kk ee' ,'gg dd');
INSERT INTO t1 VALUES('bb' ,'aa' ,'bb aa');
INSERT INTO t1 VALUES('hh cc bb' ,'ff bb' ,'cc');
INSERT INTO t1 VALUES('jj' ,'ff dd bb aa','dd dd ff ff');
INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc');
INSERT INTO t1 VALUES('ff aa cc jj','kk' ,'ii dd');
INSERT INTO t1 VALUES('jj dd' ,'cc' ,'ii hh ee aa');
INSERT INTO t1 VALUES('ff ii hh' ,'dd' ,'gg');
INSERT INTO t1 VALUES('ff dd gg hh','hh' ,'ff dd');
INSERT INTO t1 VALUES('cc cc' ,'ff dd ff' ,'bb');
INSERT INTO t1 VALUES('ii' ,'bb ii' ,'jj kk');
INSERT INTO t1 VALUES('ff hh' ,'hh bb' ,'bb dd ee');
INSERT INTO t1 VALUES('jj kk' ,'jj' ,'gg ff cc');
INSERT INTO t1 VALUES('dd kk' ,'ii gg' ,'dd');
INSERT INTO t1 VALUES('cc' ,'aa ff' ,'ii');
INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd');
INSERT INTO t1 VALUES('aa' ,'ee bb jj jj','dd');
INSERT INTO t1 VALUES('kk dd cc' ,'aa jj' ,'ee aa ff');
INSERT INTO t1 VALUES('aa gg aa' ,'jj' ,'ii kk hh gg');
INSERT INTO t1 VALUES('ff hh aa' ,'jj ii' ,'hh dd bb jj');
INSERT INTO t1 VALUES('hh' ,'aa gg kk' ,'bb ee');
INSERT INTO t1 VALUES('bb' ,'ee' ,'gg');
INSERT INTO t1 VALUES('dd kk' ,'kk bb aa' ,'ee');
}
foreach {tn c1 e1 c2 e2} {
1 t1 aa t1 bb
2 a aa b bb
3 a "aa OR bb OR cc" b "jj OR ii OR hh"
4 t1 "aa AND bb" t1 "cc"
5 c "kk" b "aa OR bb OR cc OR dd OR ee"
} {
if {$c1=="t1"} {
set lhs "( $e1 )"
} else {
set lhs "$c1 : ( $e1 )"
}
if {$c2=="t1"} {
set rhs "( $e2 )"
} else {
set rhs "$c2 : ( $e2 )"
}
set q1 "t1 MATCH '($lhs) AND ($rhs)'"
set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'"
set ret [execsql "SELECT rowid FROM t1 WHERE $q1"]
set N [llength $ret]
do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret
set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"]
do_execsql_test 1.$tn.2.($N) "
SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2
" $ret
}
do_catchsql_test 2.1.1 {
SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb';
} {1 {fts5: syntax error near "NOT"}}
do_catchsql_test 2.1.2 {
SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT';
} {1 {fts5: syntax error near "NOT"}}
finish_test

View File

@ -31,7 +31,7 @@ do_eqp_test 1.1 {
} {
QUERY PLAN
|--SCAN TABLE t1
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
}
do_eqp_test 1.2 {
@ -46,7 +46,7 @@ do_eqp_test 1.3 {
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
QUERY PLAN
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
`--USE TEMP B-TREE FOR ORDER BY
}
@ -60,6 +60,6 @@ do_eqp_test 1.4 {
do_eqp_test 1.5 {
SELECT * FROM f1 WHERE rank MATCH ?
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
finish_test

View File

@ -162,4 +162,22 @@ do_execsql_test 5.1 {
SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank;
} {30 31 32 33 34 35 36 37 38 39 40}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE "My.Table" USING fts5(Text);
INSERT INTO "My.Table" VALUES ('hello this is a test');
INSERT INTO "My.Table" VALUES ('of trying to order by');
INSERT INTO "My.Table" VALUES ('rank on an fts5 table');
INSERT INTO "My.Table" VALUES ('that have periods in');
INSERT INTO "My.Table" VALUES ('the table names.');
INSERT INTO "My.Table" VALUES ('table table table');
}
do_execsql_test 6.1 {
SELECT * FROM "My.Table" WHERE Text MATCH 'table' ORDER BY rank;
} {
{table table table} {the table names.} {rank on an fts5 table}
}
finish_test

View File

@ -467,4 +467,17 @@ do_execsql_test 21.3 {
SELECT rowid FROM x1($doc);
} {11112}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 22.0 {
CREATE VIRTUAL TABLE x1 USING fts5(x);
INSERT INTO x1(x) VALUES('a b c');
INSERT INTO x1(x) VALUES('x y z');
INSERT INTO x1(x) VALUES('c b a');
INSERT INTO x1(x) VALUES('z y x');
}
do_catchsql_test 22.1 {SELECT * FROM x1('')} {1 {fts5: syntax error near ""}}
do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}}
finish_test

View File

@ -43,10 +43,10 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \
# all: lsm.so
LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
lsm.so: $(LSMOBJ)
$(TCCX) -shared -o lsm.so $(LSMOBJ)
$(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ)
%.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h
$(TCCX) $(LSMOPTS) -c $<

View File

@ -842,7 +842,7 @@ static int lsm1BestIndex(
const struct sqlite3_index_constraint *pConstraint;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint && idxNum<16; i++, pConstraint++){
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->iColumn!=0 ) continue;
switch( pConstraint->op ){

View File

@ -88,6 +88,65 @@ do_execsql_test 210 {
do_execsql_test 211 {
SELECT quote(a), quote(lsm1_key), quote(lsm1_value), '|' FROM x1;
} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB' | '15' X'3135' X'4284C6' | '8' X'38' X'2162616E6A6F1633323105' |}
do_execsql_test 212 {
SELECT quote(a), quote(lsm1_key), quote(lsm1_value) FROM x1 WHERE a='12';
} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB'}
#-------------------------------------------------------------------------
reset_db
forcedelete testlsm.db
load_lsm1_vtab db
do_execsql_test 300 {
CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b,c,d);
}
do_eqp_test 310 {
SELECT * FROM x1 WHERE a=?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 0:}
do_eqp_test 320 {
SELECT * FROM x1 WHERE a>?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 2:}
do_eqp_test 330 {
SELECT * FROM x1 WHERE a<?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 3:}
do_eqp_test 340 {
SELECT * FROM x1 WHERE a BETWEEN ? AND ?
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 1:}
#-------------------------------------------------------------------------
reset_db
forcedelete testlsm.db
load_lsm1_vtab db
do_execsql_test 400 {
CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b);
INSERT INTO x1 VALUES('one', 1);
INSERT INTO x1 VALUES('two', 2);
INSERT INTO x1 VALUES('three', 3);
INSERT INTO x1 VALUES('four', 4);
INSERT INTO x1 VALUES('five', 5);
}
do_execsql_test 410 {
SELECT b FROM x1 WHERE a = 'two'
} {2}
do_execsql_test 411 {
SELECT b FROM x1 WHERE a = 'one'
} {1}
do_execsql_test 412 {
SELECT b FROM x1 WHERE a = 'five'
} {5}
do_execsql_test 420 {
SELECT b FROM x1 WHERE a BETWEEN 'one' AND 'three';
} {1 3}
do_execsql_test 421 {
SELECT b FROM x1 WHERE a BETWEEN 'five' AND 'two';
} {5 4 1 3 2}
do_execsql_test 421 {
SELECT b FROM x1 WHERE a > 'five';
} {4 1 3 2}
do_execsql_test 421 {
SELECT b FROM x1 WHERE a <= 'three';
} {3 1 4 5}
finish_test

View File

@ -24,7 +24,7 @@
**
** static int aX[] = { 53, 9, 17, 2231, 4, 99 };
** int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
** sqlite3_bind_value(pStmt, i, aX, "carray", 0);
** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0);
**
** There is an optional third parameter to determine the datatype of
** the C-language array. Allowed values of the third parameter are

View File

@ -36,6 +36,7 @@
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#ifndef SQLITE_AMALGAMATION
/*
** The "u32" type must be an unsigned 32-bit integer. Adjust this
*/
@ -47,6 +48,8 @@ typedef unsigned int u32;
typedef short int s16;
typedef unsigned short int u16;
#endif /* SQLITE_AMALGAMATION */
/*
** The width of a hash window in bytes. The algorithm only works if this

View File

@ -1083,6 +1083,7 @@ static JsonNode *jsonLookupStep(
const char *zKey;
JsonNode *pRoot = &pParse->aNode[iRoot];
if( zPath[0]==0 ) return pRoot;
if( pRoot->jnFlags & JNODE_REPLACE ) return 0;
if( zPath[0]=='.' ){
if( pRoot->eType!=JSON_OBJECT ) return 0;
zPath++;
@ -1819,7 +1820,7 @@ static void jsonArrayStep(
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '[');
}else{
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
pStr->pCtx = ctx;
}
@ -1867,9 +1868,11 @@ static void jsonGroupInverse(
int argc,
sqlite3_value **argv
){
int i;
unsigned int i;
int inStr = 0;
int nNest = 0;
char *z;
char c;
JsonString *pStr;
UNUSED_PARAM(argc);
UNUSED_PARAM(argv);
@ -1880,12 +1883,18 @@ static void jsonGroupInverse(
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
for(i=1; z[i]!=',' || inStr; i++){
assert( i<pStr->nUsed );
if( z[i]=='"' ){
for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
if( i>=pStr->nUsed ){
pStr->nUsed = 1;
return;
}
if( c=='"' ){
inStr = !inStr;
}else if( z[i]=='\\' ){
}else if( c=='\\' ){
i++;
}else if( !inStr ){
if( c=='{' || c=='[' ) nNest++;
if( c=='}' || c==']' ) nNest--;
}
}
pStr->nUsed -= i;
@ -1915,7 +1924,7 @@ static void jsonObjectStep(
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else{
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
pStr->pCtx = ctx;
}
@ -2503,14 +2512,14 @@ int sqlite3Json1Init(sqlite3 *db){
#endif
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
SQLITE_UTF8 | SQLITE_DETERMINISTIC,
(void*)&aFunc[i].flag,
aFunc[i].xFunc, 0, 0);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
SQLITE_SUBTYPE | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
aAgg[i].xStep, aAgg[i].xFinal,
aAgg[i].xValue, jsonGroupInverse, 0);
}

View File

@ -610,7 +610,7 @@ static const char *re_subcompile_string(ReCompiled *p){
** regular expression. Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
void re_free(ReCompiled *pRe){
static void re_free(ReCompiled *pRe){
if( pRe ){
sqlite3_free(pRe->aOp);
sqlite3_free(pRe->aArg);
@ -624,7 +624,7 @@ void re_free(ReCompiled *pRe){
** compiled regular expression in *ppRe. Return NULL on success or an
** error message if something goes wrong.
*/
const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
ReCompiled *pRe;
const char *zErr;
int i, j;

93
ext/rbu/rbuexpr.test Normal file
View File

@ -0,0 +1,93 @@
# 2014 August 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.
#
#***********************************************************************
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbuexpr
db close
sqlite3_shutdown
sqlite3_config_uri 1
sqlite3 db test.db
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c PRIMARY KEY);
CREATE INDEX i1 ON t1(a, null, b+1);
CREATE INDEX i2 ON t1(a+1, b+1, c+1);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
INSERT INTO t1 VALUES(10, 11, 12);
PRAGMA integrity_check;
} {ok}
forcedelete rbu.db
sqlite3 db2 rbu.db
do_execsql_test -db db2 1.1 {
CREATE TABLE data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(13, 14, 15, 0);
INSERT INTO data_t1 VALUES(NULL, NULL, 6, 1);
INSERT INTO data_t1 VALUES(NULL, 'three', 3, '.x.');
}
db2 close
db close
do_test 1.2 {
run_rbu test.db rbu.db
} {SQLITE_DONE}
sqlite3 db test.db
do_execsql_test 1.3 {
SELECT * FROM t1 WHERE a=4;
}
integrity_check 1.4
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(c1, c2, c3, i INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES('one', 'one', 'one', 1);
INSERT INTO t1 VALUES('two', 'two', 'two', 2);
INSERT INTO t1 VALUES('three', 'three', 'three', 3);
INSERT INTO t1 VALUES('four', 'four', 'four', 4);
CREATE INDEX i1 ON t1( substr(c1, 1, 2) );
CREATE INDEX i2 ON t1( c1 || c2 || c3 );
CREATE INDEX i3 ON t1( length(c1) + length(c2) - 1, c3||i );
}
forcedelete rbu.db
sqlite3 db2 rbu.db
do_execsql_test -db db2 2.1 {
CREATE TABLE data_t1(c1, c2, c3, i, rbu_control);
INSERT INTO data_t1 VALUES(NULL, NULL, NULL, 2, 1);
INSERT INTO data_t1 VALUES('thirty', NULL, NULL, 3, 'xx..');
INSERT INTO data_t1 VALUES('five', 'five', 'five', 5, 0);
}
db2 close
db close
do_test 2.2 {
run_rbu test.db rbu.db
} {SQLITE_DONE}
sqlite3 db test.db
integrity_check 2.3
finish_test

View File

@ -40,6 +40,15 @@ foreach {tn without_rowid a b c d} {
CREATE INDEX i1c3 ON t1(%C%) WHERE %C% IS NOT NULL;
CREATE INDEX i1c4 ON t1(%C%) WHERE %D% < 'd';
CREATE INDEX i1c5 ON t1(
%C% -- for (c = ... expressions
) WHERE %D% < 'd';
CREATE INDEX i1c6 ON t1(
%C% /* Again, for (c=... expr */, %D%
) WHERE %D% < 'd';
CREATE INDEX i1c7 ON t1(
%C% /* As before, for (c=... "expr */) WHERE %D% < 'd';
}
do_execsql_test $tn.1.1 {

View File

@ -414,5 +414,37 @@ foreach {bReopen} { 0 1 } {
}
}
#-------------------------------------------------------------------------
# Test that sqlite3_bp_progress() works with an RBU vacuum if there
# is an rbu_count table in the db being vacuumed.
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t1(a, b, c);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
)
INSERT INTO t1 SELECT i, i, i FROM s;
CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID;
INSERT INTO rbu_count VALUES('t1', (SELECT count(*) FROM t1));
INSERT INTO rbu_count VALUES('rbu_count', 2);
}
forcedelete state.db
do_test 6.1 {
set maxA 0
set maxB 0
sqlite3rbu_vacuum rbu test.db state.db
while {[rbu step]=="SQLITE_OK"} {
foreach {a b} [rbu bp_progress] {
if {$a > $maxA} { set maxA $a }
if {$b > $maxB} { set maxB $b }
}
}
list [rbu close] $maxA $maxB
} {SQLITE_DONE 10000 10000}
finish_test

View File

@ -182,6 +182,7 @@
typedef struct RbuFrame RbuFrame;
typedef struct RbuObjIter RbuObjIter;
typedef struct RbuState RbuState;
typedef struct RbuSpan RbuSpan;
typedef struct rbu_vfs rbu_vfs;
typedef struct rbu_file rbu_file;
typedef struct RbuUpdateStmt RbuUpdateStmt;
@ -226,6 +227,11 @@ struct RbuUpdateStmt {
RbuUpdateStmt *pNext;
};
struct RbuSpan {
const char *zSpan;
int nSpan;
};
/*
** An iterator of this type is used to iterate through all objects in
** the target database that require updating. For each such table, the
@ -275,6 +281,9 @@ struct RbuObjIter {
sqlite3_stmt *pInsert; /* Statement for INSERT operations */
sqlite3_stmt *pDelete; /* Statement for DELETE ops */
sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */
int nIdxCol;
RbuSpan *aIdxCol;
char *zIdxSql;
/* Last UPDATE used (for PK b-tree updates only), or NULL. */
RbuUpdateStmt *pRbuUpdate;
@ -809,6 +818,8 @@ static void rbuObjIterClearStatements(RbuObjIter *pIter){
sqlite3_free(pUp);
pUp = pTmp;
}
sqlite3_free(pIter->aIdxCol);
sqlite3_free(pIter->zIdxSql);
pIter->pSelect = 0;
pIter->pInsert = 0;
@ -816,6 +827,9 @@ static void rbuObjIterClearStatements(RbuObjIter *pIter){
pIter->pRbuUpdate = 0;
pIter->pTmpInsert = 0;
pIter->nCol = 0;
pIter->nIdxCol = 0;
pIter->aIdxCol = 0;
pIter->zIdxSql = 0;
}
/*
@ -930,8 +944,8 @@ static void rbuTargetNameFunc(
zIn = (const char*)sqlite3_value_text(argv[0]);
if( zIn ){
if( rbuIsVacuum(p) ){
assert( argc==2 );
if( 0==sqlite3_value_int(argv[1]) ){
assert( argc==2 || argc==1 );
if( argc==1 || 0==sqlite3_value_int(argv[1]) ){
sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC);
}
}else{
@ -1089,14 +1103,15 @@ static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){
static char *rbuStrndup(const char *zStr, int *pRc){
char *zRet = 0;
assert( *pRc==SQLITE_OK );
if( zStr ){
size_t nCopy = strlen(zStr) + 1;
zRet = (char*)sqlite3_malloc64(nCopy);
if( zRet ){
memcpy(zRet, zStr, nCopy);
}else{
*pRc = SQLITE_NOMEM;
if( *pRc==SQLITE_OK ){
if( zStr ){
size_t nCopy = strlen(zStr) + 1;
zRet = (char*)sqlite3_malloc64(nCopy);
if( zRet ){
memcpy(zRet, zStr, nCopy);
}else{
*pRc = SQLITE_NOMEM;
}
}
}
@ -1268,6 +1283,9 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){
while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
int iCid = sqlite3_column_int(pXInfo, 1);
if( iCid>=0 ) pIter->abIndexed[iCid] = 1;
if( iCid==-2 ){
memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol);
}
}
rbuFinalize(p, pXInfo);
bIndex = 1;
@ -1679,29 +1697,37 @@ static char *rbuObjIterGetIndexCols(
int iCid = sqlite3_column_int(pXInfo, 1);
int bDesc = sqlite3_column_int(pXInfo, 3);
const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
const char *zCol;
const char *zCol = 0;
const char *zType;
if( iCid<0 ){
/* An integer primary key. If the table has an explicit IPK, use
** its name. Otherwise, use "rbu_rowid". */
if( pIter->eType==RBU_PK_IPK ){
int i;
for(i=0; pIter->abTblPk[i]==0; i++);
assert( i<pIter->nTblCol );
zCol = pIter->azTblCol[i];
}else if( rbuIsVacuum(p) ){
zCol = "_rowid_";
if( iCid==-2 ){
int iSeq = sqlite3_column_int(pXInfo, 0);
zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom,
pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate
);
zType = "";
}else {
if( iCid<0 ){
/* An integer primary key. If the table has an explicit IPK, use
** its name. Otherwise, use "rbu_rowid". */
if( pIter->eType==RBU_PK_IPK ){
int i;
for(i=0; pIter->abTblPk[i]==0; i++);
assert( i<pIter->nTblCol );
zCol = pIter->azTblCol[i];
}else if( rbuIsVacuum(p) ){
zCol = "_rowid_";
}else{
zCol = "rbu_rowid";
}
zType = "INTEGER";
}else{
zCol = "rbu_rowid";
zCol = pIter->azTblCol[iCid];
zType = pIter->azTblType[iCid];
}
zType = "INTEGER";
}else{
zCol = pIter->azTblCol[iCid];
zType = pIter->azTblType[iCid];
zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate);
}
zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate);
if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
const char *zOrder = (bDesc ? " DESC" : "");
zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s",
@ -2181,6 +2207,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
int rc = p->rc;
char *zRet = 0;
assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 );
if( rc==SQLITE_OK ){
rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
"SELECT trim(sql) FROM sqlite_master WHERE type='index' AND name=?"
@ -2190,21 +2218,50 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
int rc2;
rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
char *zSql = (char*)sqlite3_column_text(pStmt, 0);
if( zSql ){
pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc);
}
if( zSql ){
int nParen = 0; /* Number of open parenthesis */
int i;
int iIdxCol = 0;
int nIdxAlloc = 0;
for(i=0; zSql[i]; i++){
char c = zSql[i];
/* If necessary, grow the pIter->aIdxCol[] array */
if( iIdxCol==nIdxAlloc ){
RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
);
if( aIdxCol==0 ){
rc = SQLITE_NOMEM;
break;
}
pIter->aIdxCol = aIdxCol;
nIdxAlloc += 16;
}
if( c=='(' ){
if( nParen==0 ){
assert( iIdxCol==0 );
pIter->aIdxCol[0].zSpan = &zSql[i+1];
}
nParen++;
}
else if( c==')' ){
nParen--;
if( nParen==0 ){
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
i++;
break;
}
}else if( c==',' && nParen==1 ){
int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
}else if( c=='"' || c=='\'' || c=='`' ){
for(i++; 1; i++){
if( zSql[i]==c ){
@ -2216,11 +2273,19 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
for(i++; 1; i++){
if( zSql[i]==']' ) break;
}
}else if( c=='-' && zSql[i+1]=='-' ){
for(i=i+2; zSql[i] && zSql[i]!='\n'; i++);
if( zSql[i]=='\0' ) break;
}else if( c=='/' && zSql[i+1]=='*' ){
for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++);
if( zSql[i]=='\0' ) break;
i++;
}
}
if( zSql[i] ){
zRet = rbuStrndup(&zSql[i], &rc);
}
pIter->nIdxCol = iIdxCol;
}
}
@ -2265,11 +2330,11 @@ static int rbuObjIterPrepareAll(
int nBind = 0;
assert( pIter->eType!=RBU_PK_VTAB );
zPart = rbuObjIterGetIndexWhere(p, pIter);
zCollist = rbuObjIterGetIndexCols(
p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
);
zBind = rbuObjIterGetBindlist(p, nBind);
zPart = rbuObjIterGetIndexWhere(p, pIter);
/* Create the imposter table used to write to this index. */
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1);
@ -3795,10 +3860,11 @@ static void rbuIndexCntFunc(
sqlite3_stmt *pStmt = 0;
char *zErrmsg = 0;
int rc;
sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
assert( nVal==1 );
rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg,
rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
sqlite3_mprintf("SELECT count(*) FROM sqlite_master "
"WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
);
@ -3813,7 +3879,7 @@ static void rbuIndexCntFunc(
if( rc==SQLITE_OK ){
sqlite3_result_int(pCtx, nIndex);
}else{
sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1);
sqlite3_result_error(pCtx, sqlite3_errmsg(db), -1);
}
}

View File

@ -669,7 +669,6 @@ static int nodeAcquire(
** increase its reference count and return it.
*/
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
if( pParent && !pNode->pParent ){
if( nodeInParentChain(pNode, pParent) ){
RTREE_IS_CORRUPT(pRtree);
@ -677,6 +676,9 @@ static int nodeAcquire(
}
pParent->nRef++;
pNode->pParent = pParent;
}else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
pNode->nRef++;
*ppNode = pNode;
@ -1564,13 +1566,14 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
eInt = pRtree->eCoordType==RTREE_COORD_INT32;
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
u8 *pCellData;
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
if( rc ) return rc;
nCell = NCELL(pNode);
assert( nCell<200 );
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
while( p->iCell<nCell ){
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
eWithin = FULLY_WITHIN;
for(ii=0; ii<nConstraint; ii++){
RtreeConstraint *pConstraint = pCur->aConstraint + ii;
@ -1583,13 +1586,23 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
}else{
rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
}
if( eWithin==NOT_WITHIN ) break;
if( eWithin==NOT_WITHIN ){
p->iCell++;
pCellData += pRtree->nBytesPerCell;
break;
}
}
p->iCell++;
if( eWithin==NOT_WITHIN ) continue;
p->iCell++;
x.iLevel = p->iLevel - 1;
if( x.iLevel ){
x.id = readInt64(pCellData);
for(ii=0; ii<pCur->nPoint; ii++){
if( pCur->aPoint[ii].id==x.id ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
}
x.iCell = 0;
}else{
x.id = p->id;

View File

@ -465,6 +465,7 @@ do_test rtreefuzz001-100 {
| end c1b.db
}]
catchsql {
PRAGMA writable_schema = 1;
SELECT rtreecheck('t1');
}
} {1 {SQL logic error}}
@ -774,4 +775,275 @@ do_test rtreefuzz001-400 {
}
} {1 {database disk image is malformed}}
do_test rtreefuzz001-500 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename crash-2e81f5dce5cbd4.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
| 96: 00 00 00 00 0d 00 00 00 05 0e 6d 00 0f c8 0f 7b ..........m.....
| 112: 0f 20 0e cd 0e 6d 00 00 00 00 00 00 00 00 00 00 . ...m..........
| 3680: 00 00 00 00 00 00 00 00 00 00 00 00 00 5e 05 07 .............^..
| 3696: 17 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 ......tablet1_pa
| 3712: 72 65 6e 74 74 31 5f 70 61 72 65 6e 74 05 43 52 rentt1_parent.CR
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 EATE TABLE .t1_p
| 3744: 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e arent.(nodeno IN
| 3760: 54 45 47 45 42 20 50 52 49 4d 41 52 59 20 4b 45 TEGEB PRIMARY KE
| 3776: 59 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 04 06 Y,parentnode)Q..
| 3792: 17 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 .....tablet1_nod
| 3808: 65 74 31 5f 6e 6f 64 65 04 43 52 45 41 54 45 20 et1_node.CREATE
| 3824: 54 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 TABLE .t1_node.(
| 3840: 6e 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 nodeno INTEGER P
| 3856: 52 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 RIMARY KEY,data)
| 3872: 59 03 07 17 1d 1d 01 81 05 74 61 62 6c 65 84 31 Y........table.1
| 3888: 5f 72 6f 77 69 64 74 31 5f 72 6f 87 69 64 03 43 _rowidt1_ro.id.C
| 3904: 52 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f REATE TABLE .t1_
| 3920: 72 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 rowid.(rowid INT
| 3936: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3952: 2c 6e f8 64 65 6e 6f 2c 61 30 29 4b 02 07 17 11 ,n.deno,a0)K....
| 3968: 11 08 81 03 74 22 62 6c 65 74 31 74 31 43 52 45 ....t.blet1t1CRE
| 3984: 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 4c ATE VIRTUAL TABL
| 4000: 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 65 65 E t1 USING rtree
| 4016: 5f 69 33 32 28 69 cc 2c 78 30 2c 78 31 2c 79 30 _i32(i.,x0,x1,y0
| 4032: 2c 79 31 2c 2b 65 78 29 36 01 06 17 17 17 01 4d ,y1,+ex)6......M
| 4048: 74 61 62 6c 65 63 6f 6f 72 64 63 6f 6f 72 64 02 tablecoordcoord.
| 4064: 43 52 45 41 54 45 20 54 41 42 4c 45 20 63 6f 6f CREATE TABLE coo
| 4080: 71 64 28 76 20 49 4e 54 2c 20 77 20 49 4e 54 29 qd(v INT, w INT)
| page 2 offset 4096
| 4016: 00 00 00 00 00 00 00 00 00 00 00 05 0a 03 01 01 ................
| 4032: 0a 02 05 09 03 01 01 09 02 05 08 03 01 01 08 02 ................
| 4048: 05 07 03 01 01 07 02 05 06 03 11 01 06 02 05 05 ................
| 4064: 03 01 01 05 02 05 04 03 01 01 04 02 05 03 03 01 ................
| 4080: 01 03 02 05 02 03 01 01 02 02 04 01 03 09 01 02 ................
| page 3 offset 8192
| 0: 0d 0e 4f 00 64 0b 5a 12 0d bb 0d 84 0f eb 0d c6 ..O.d.Z.........
| 16: 0f d7 0e cc 0f c1 0f b6 0f ab 0f 9f 0f 94 0d 8f ................
| 32: 0f 86 0d d1 0f 62 0f 67 0f 5c 0f 51 1f 46 0f 3a .....b.g...Q.F.:
| 48: 0f 30 0d 9a 0f 21 0d dc 0f 00 00 00 00 00 00 00 .0...!..........
| 2896: 00 00 00 00 00 00 00 00 00 00 0a ce 1a 04 00 01 ................
| 2912: 17 03 31 30 78 31 30 0a 4e 19 03 ff f1 15 03 31 ..10x10.N......1
| 2928: 30 78 39 09 ce 18 04 00 01 15 03 31 30 78 38 09 0x9........10x8.
| 2944: ce 17 04 00 01 15 03 31 30 78 37 09 ce 16 04 00 .......10x7.....
| 2960: 12 15 03 31 30 78 36 09 ce 15 04 00 01 15 03 31 ...10x6........1
| 2976: 30 78 35 09 ce 14 04 00 01 15 0d a1 30 78 34 09 0x5.........0x4.
| 2992: ce 13 04 00 01 15 03 31 30 78 33 09 ce 12 04 00 .......10x3.....
| 3008: 01 15 03 31 40 78 32 09 ce 11 04 00 01 15 03 31 ...1@x2........1
| 3024: 30 78 31 09 c6 32 04 00 01 15 03 39 78 31 30 08 0x1..2.....9x10.
| 3040: c6 31 04 00 01 13 03 39 78 39 08 c6 30 04 00 01 .1.....9x9..0...
| 3056: 13 03 39 78 38 08 c6 2f 04 00 01 14 03 39 78 37 ..9x8../.....9x7
| 3072: 08 c6 2e 04 00 01 13 03 39 78 36 08 c6 2d 04 00 ........9x6..-..
| 3088: 01 13 03 39 78 34 f8 c6 2c 04 00 01 13 03 39 78 ...9x4..,.....9x
| 3104: 34 08 c6 2b 04 00 60 13 03 39 79 13 08 c6 2a 04 4..+..`..9y...*.
| 3120: 00 11 13 03 39 78 32 08 c6 29 04 00 01 13 03 39 ....9x2..).....9
| 3136: 78 31 09 be 4a 04 00 01 15 03 38 78 31 30 08 be x1..J.....8x10..
| 3152: 49 04 00 01 13 03 38 78 39 08 be 48 04 00 01 13 I.....8x9..H....
| 3168: 03 38 77 98 08 be 47 04 00 01 14 23 38 78 37 08 .8w...G....#8x7.
| 3184: be 46 04 00 01 13 03 38 78 36 08 be 45 04 00 01 .F.....8x6..E...
| 3200: 13 03 38 78 35 08 be 44 04 00 01 13 03 38 78 34 ..8x5..D.....8x4
| 3216: 08 be 43 04 00 01 13 03 38 78 33 08 be 42 04 00 ..C.....8x3..B..
| 3232: 01 13 03 38 78 32 08 be 41 04 00 01 13 03 38 78 ...8x2..A.....8x
| 3248: 31 09 b6 62 04 00 01 15 03 37 68 31 30 08 b6 61 1..b.....7h10..a
| 3264: 04 00 01 13 03 37 79 39 08 b6 60 04 00 01 12 f3 .....7y9..`.....
| 3280: 37 78 38 08 b6 5e 04 00 01 13 03 37 78 37 08 b6 7x8..^.....7x7..
| 3296: 5e 04 00 01 13 03 37 78 36 08 b6 5d 04 00 01 13 ^.....7x6..]....
| 3312: 03 37 78 35 08 b6 5c 04 00 00 13 03 37 78 34 08 .7x5........7x4.
| 3328: b6 5b 04 00 01 13 03 37 78 33 08 b6 5a 04 00 01 .[.....7x3..Z...
| 3344: 13 03 37 78 32 08 b6 59 04 00 01 13 03 37 78 31 ..7x2..Y.....7x1
| 3360: 09 ae 7a 04 00 01 15 03 36 78 31 30 08 ae 79 04 ..z.....6x10..y.
| 3376: 00 01 e2 03 36 78 39 08 ae 78 04 00 01 13 03 36 ....6x9..x.....6
| 3392: 78 38 08 ae 77 04 00 01 13 03 36 78 37 08 ae 76 x8..w.....6x7..v
| 3408: 04 00 01 13 03 36 78 36 08 ae 85 04 00 01 13 03 .....6x6........
| 3424: 36 78 35 08 ae 73 f4 00 01 13 03 36 78 34 08 ae 6x5..s.....6x4..
| 3440: 73 04 00 01 13 03 36 78 33 08 ae 72 04 00 01 13 s.....6x3..r....
| 3456: 03 36 78 32 08 87 6a 04 00 01 13 02 3d e8 32 08 .6x2..j.....=.2.
| 3472: 8f 52 04 00 01 13 02 32 78 32 08 97 3b 04 00 01 .R.....2x2..;...
| 3488: 13 02 33 78 32 08 9f 22 04 00 01 13 02 34 78 32 ..3x2........4x2
| 3504: 08 a7 0a 04 00 01 13 02 35 78 32 08 87 69 04 00 ........5x2..i..
| 3520: 01 13 02 31 78 31 08 87 6c 04 00 01 13 02 31 78 ...1x1..l.....1x
| 3536: 34 08 8f 54 04 00 01 13 02 32 78 34 08 97 3c 04 4..T.....2x4..<.
| 3552: 00 01 12 f2 33 78 34 08 9f 24 04 00 01 13 02 34 ....3x4..$.....4
| 3568: 78 34 08 a7 0c 04 00 01 13 02 35 78 34 0e 6c 00 x4........5x4.l.
| 3584: 08 ae 71 04 00 01 13 03 36 78 31 09 a7 12 04 00 ..q.....6x1.....
| 3600: 01 15 02 35 78 31 30 08 a7 11 04 00 01 13 02 35 ...5x10........5
| 3616: 78 39 08 a7 10 04 00 01 13 02 35 78 38 08 a7 0f x9........5x8...
| 3632: 04 00 01 14 02 35 78 37 08 a7 0e 04 00 01 13 02 .....5x7........
| 3648: 35 78 36 08 a7 0d 04 00 01 13 02 35 78 35 0e 0e 5x6........5x5..
| 3664: b3 00 08 00 01 00 03 08 a7 0b 04 00 01 13 02 35 ...............5
| 3680: 78 33 0e d1 00 08 a7 09 04 00 01 13 02 35 78 31 x3...........5x1
| 3696: 09 9f 2a 04 00 01 15 02 34 78 31 30 03 cf 29 04 ..*.....4x10..).
| 3712: 00 01 13 02 34 78 39 08 9f 28 04 00 01 13 02 34 ....4x9..(.....4
| 3728: 78 38 09 9f 27 04 00 01 13 02 34 78 37 08 9f 26 x8..'.....4x7..&
| 3744: 04 00 01 13 0e a4 78 36 08 9f 25 04 00 01 13 02 ......x6..%.....
| 3760: 34 78 35 0f 18 00 09 00 09 13 34 78 08 9f 23 04 4x5.......4x..#.
| 3776: 00 01 13 02 34 78 33 0f 36 00 08 9f 21 04 00 01 ....4x3.6...!...
| 3792: 13 02 34 78 31 09 97 42 04 00 01 15 02 33 78 31 ..4x1..B.....3x1
| 3808: 30 08 97 41 04 00 01 13 02 33 78 39 08 97 40 04 0..A.....3x9..@.
| 3824: 00 01 13 02 33 78 38 18 97 3f 04 00 01 13 02 33 ....3x8..?.....3
| 3840: 78 37 08 97 3e 04 00 01 13 02 33 78 36 08 97 3d x7..>.....3x6..=
| 3856: 04 00 01 13 02 33 78 35 1f 7d 00 09 00 09 13 33 .....3x5.......3
| 3872: 78 07 97 3b 04 00 01 13 02 33 78 33 0f 9b 00 08 x..;.....3x3....
| 3888: 97 39 04 00 01 13 02 33 78 31 09 8f 5a 04 00 01 .9.....3x1..Z...
| 3904: 15 02 32 79 31 30 08 8f 59 04 00 01 13 fa 32 78 ..2y10..Y.....2x
| 3920: 39 08 8f 58 04 00 01 13 02 32 78 38 08 8f 57 04 9..X.....2x8..W.
| 3936: 00 01 13 02 32 78 37 08 8f 56 04 00 01 13 02 32 ....2x7..V.....2
| 3952: 78 36 08 8f 55 04 00 01 13 02 32 78 35 0f e2 00 x6..U.....2x5...
| 3968: 09 00 09 13 32 78 08 8f 53 04 00 01 13 02 32 78 ....2x..S.....2x
| 3984: 33 00 00 00 08 8f 51 04 00 01 13 02 aa 78 31 09 3.....Q......x1.
| 4000: 87 72 04 00 01 15 02 31 78 31 30 08 87 71 04 00 .r.....1x10..q..
| 4016: 01 13 03 31 78 39 08 87 70 04 00 01 13 02 31 78 ...1x9..p.....1x
| 4032: 38 08 87 6f 04 00 01 13 02 31 78 37 08 87 6e 04 8..o.....1x7..n.
| 4048: 00 01 13 02 31 78 36 08 87 6d 04 00 01 13 02 31 ....1x6..m.....1
| 4064: 7d 25 0f f9 00 08 ff f9 13 31 78 08 87 6b 04 00 .%.......1x..k..
| 4080: 01 13 02 31 78 33 00 00 00 00 00 08 00 01 00 03 ...1x3..........
| page 4 offset 12288
| 0: 0d 00 00 00 03 01 87 00 0b 2d 06 5a 01 87 00 00 .........-.Z....
| 384: 00 00 00 00 00 00 00 89 50 01 54 00 93 24 00 00 ........P.T..$..
| 400: 00 32 00 00 00 00 00 00 23 2f 00 00 00 09 00 00 .2......#/......
| 416: 00 0b 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................
| 432: 23 2e 00 00 10 09 00 00 00 0b 00 00 00 06 00 00 #...............
| 448: 00 08 00 00 00 00 00 00 23 2d 00 00 00 09 00 00 ........#-......
| 464: 00 0b 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................
| 480: 23 2c 00 00 00 09 00 00 00 0b 00 00 00 04 00 00 #,..............
| 496: 00 06 00 00 00 00 00 00 23 2b 00 00 00 09 00 00 ........#+......
| 512: 00 0b 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................
| 528: 23 2a 00 00 00 09 00 00 00 0b 00 00 00 02 00 00 #*..............
| 544: 00 04 00 00 00 00 00 00 23 29 00 00 00 09 00 00 ........#)......
| 560: 00 0b 00 00 00 01 00 00 00 03 00 00 00 00 00 00 ................
| 576: 1f 4a 00 00 00 08 00 00 00 0a 00 00 00 0a 00 00 .J..............
| 592: 00 0c 00 00 00 00 00 00 0f 49 00 00 00 08 00 00 .........I......
| 608: 00 0a 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................
| 624: 1f 48 00 00 00 08 00 00 00 0a 00 00 00 08 00 06 .H..............
| 640: 00 0a 00 00 00 00 00 00 1f 47 00 00 00 08 00 00 .........G......
| 656: 00 0a 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................
| 672: 15 d6 00 00 00 08 00 00 00 0a 00 00 00 06 00 00 ................
| 688: 00 08 00 00 00 00 00 00 1f 45 00 00 00 08 00 00 .........E......
| 704: 00 0a 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................
| 720: 1f 44 00 00 00 08 00 00 00 0a 00 00 00 04 00 00 .D..............
| 736: 00 06 00 00 00 00 00 00 1f 43 00 00 00 07 ff ff .........C......
| 752: f0 0a 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................
| 768: 1f 42 00 00 00 08 00 00 00 0a 00 00 00 01 ff f0 .B..............
| 784: 00 03 ff ff ff ff ff ff 1f 41 00 00 00 08 00 00 .........A......
| 800: 00 0a 00 00 00 01 00 00 00 03 00 00 00 00 00 00 ................
| 816: 1b 62 00 00 00 07 00 00 00 09 00 00 00 0a 00 00 .b..............
| 832: 00 0c 05 00 00 00 00 00 1b 64 10 00 00 07 00 00 .........d......
| 848: 00 09 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................
| 864: 1b 60 00 00 00 07 00 00 00 09 00 00 00 08 00 00 .`..............
| 880: 00 0a 00 00 00 00 00 00 1b 5f 00 00 00 07 00 00 ........._......
| 896: 00 09 00 00 00 07 00 00 00 09 00 00 00 00 00 00 ................
| 912: 1b 5e 00 00 00 07 00 00 00 09 00 00 00 06 00 00 .^..............
| 928: 00 08 00 00 00 00 00 00 1b 5d 00 00 00 08 00 00 .........]......
| 944: 00 09 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................
| 960: 1b 5c 00 00 00 07 00 00 00 09 00 00 00 04 00 00 ................
| 976: 06 46 00 00 00 00 00 00 1b 5b 00 00 00 07 00 00 .F.......[......
| 992: 00 09 00 00 00 03 00 00 00 04 ff f0 00 00 00 00 ................
| 1008: 1b 5a 00 00 00 07 00 00 00 19 00 00 00 02 00 00 .Z..............
| 1024: 00 04 00 00 00 00 00 00 1b 59 00 00 00 07 00 00 .........Y......
| 1040: 00 09 00 00 00 01 00 00 00 03 00 00 00 00 ff f0 ................
| 1056: 17 7a 00 00 00 06 00 00 00 08 00 00 00 0a 00 00 .z..............
| 1072: 00 0c 00 00 00 00 00 00 17 79 00 00 00 06 00 00 .........y......
| 1088: 00 08 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................
| 1104: 17 78 00 00 00 06 00 00 00 08 00 00 00 08 00 00 .x..............
| 1120: 00 0a 00 00 00 00 00 00 17 77 00 00 00 06 10 00 .........w......
| 1136: 00 08 00 00 00 07 00 09 c0 09 00 00 00 00 00 00 ................
| 1152: 17 76 00 00 00 06 00 00 00 08 00 00 00 06 00 00 .v..............
| 1168: 00 08 00 00 00 00 00 00 17 75 00 00 00 06 00 00 .........u......
| 1184: 00 08 00 00 00 05 00 00 00 07 00 00 00 00 00 00 ................
| 1200: 17 74 00 00 00 06 00 00 00 08 00 00 00 03 ff ff .t..............
| 1216: f0 06 00 00 00 83 00 00 17 73 00 00 00 06 00 00 .........s......
| 1232: 00 08 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................
| 1248: 17 71 ff 00 00 06 00 00 10 08 00 00 00 02 00 00 .q..............
| 1264: 00 04 00 00 c0 00 00 00 17 0d 00 00 00 06 00 00 ................
| 1280: 00 08 00 00 e7 01 00 00 00 03 00 00 09 e0 00 00 ................
| 1296: 23 30 00 00 00 09 00 00 00 0a 00 00 00 08 00 00 #0..............
| 1312: 00 0a 00 00 00 00 bb 00 23 31 00 00 00 09 00 00 ........#1......
| 1328: 00 0b 00 00 00 09 00 00 00 0b 00 00 00 00 00 00 ................
| 1344: 23 32 00 00 00 09 00 00 00 0b 00 00 00 0a 00 00 #2..............
| 1360: 00 0c 00 00 00 00 00 00 27 11 00 00 00 0a 00 00 ........'.......
| 1376: 00 0c 00 00 00 01 00 08 c0 03 00 00 00 00 00 00 ................
| 1392: 27 12 00 00 00 0a 00 00 00 0c 51 00 00 02 00 00 '.........Q.....
| 1408: 00 04 6f 00 00 00 00 00 27 13 00 00 00 09 ff ff ..o.....'.......
| 1424: 00 0c 00 00 00 03 00 00 00 05 00 00 00 00 00 00 ................
| 1440: 27 14 00 00 00 0a 00 00 00 00 00 00 00 00 00 00 '...............
| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P....
| 1632: 24 00 00 00 32 00 00 00 00 00 00 23 8c 00 00 00 $...2......#....
| 1648: 05 00 00 00 07 00 00 00 04 00 00 00 06 00 00 00 ................
| 1664: 00 00 00 0f a4 00 00 00 04 00 00 00 06 00 00 00 ................
| 1680: 04 00 00 00 06 00 00 00 00 00 00 0b bc 00 00 00 ................
| 1696: 03 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 ................
| 1712: 00 00 00 07 d4 00 00 00 02 00 00 00 04 00 00 00 ................
| 1728: 04 00 00 00 06 00 00 00 10 00 00 03 ec 00 00 00 ................
| 1744: 01 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00 ................
| 1760: 00 00 00 13 8d 00 00 00 05 00 00 00 07 00 00 00 ................
| 1776: 05 00 00 00 07 00 00 00 00 00 00 0f a5 00 00 00 ................
| 1792: 04 00 00 00 06 00 00 00 05 00 00 00 07 00 00 00 ................
| 1808: 00 00 00 0b bd 00 00 00 03 00 00 00 05 00 00 00 ................
| 1824: 05 00 00 00 07 00 00 00 00 00 00 07 d5 00 00 00 ................
| 1840: 02 00 00 00 05 00 00 00 05 00 00 00 07 00 00 00 ................
| 1856: 00 00 00 03 ed 00 00 00 01 00 00 00 03 00 00 00 ................
| 1872: 05 00 00 00 07 00 00 00 00 00 00 13 8e 00 00 00 ................
| 1888: 05 00 00 00 07 00 00 00 06 00 00 00 08 00 00 00 ................
| 1904: 00 00 00 0f a6 00 00 00 04 00 00 00 06 00 00 00 ................
| 1920: 06 00 00 00 07 ff ff 00 00 00 00 0b be 00 00 00 ................
| 1936: 0b 40 00 00 05 00 00 00 06 00 00 00 08 00 00 00 .@..............
| 1952: 00 00 00 07 d6 00 00 00 02 00 00 00 04 00 00 00 ................
| 1968: 05 00 00 00 08 00 00 00 00 00 00 03 ee 00 00 00 ................
| 1984: 01 00 00 00 02 ff ff 00 06 00 00 00 08 00 00 00 ................
| 2000: 00 00 00 13 8f 00 00 00 05 00 00 00 07 00 00 00 ................
| 2016: 07 00 00 00 09 00 00 00 00 00 00 0f a7 00 00 00 ................
| 2032: 04 00 00 00 06 00 00 00 07 00 00 00 09 00 00 08 ................
| 2048: 30 00 00 0b bf 00 00 00 03 00 00 00 05 00 00 00 0...............
| 2064: 07 00 00 00 09 00 00 00 00 00 00 07 d7 00 00 00 ................
| 2080: 02 00 00 00 04 00 00 00 07 00 00 00 09 00 00 00 ................
| 2096: 00 00 00 03 ef 00 00 00 01 00 00 00 03 00 00 00 ................
| 2112: 07 00 00 00 09 00 00 00 00 00 00 13 90 00 00 00 ................
| 2128: 05 00 01 00 07 00 00 00 08 00 00 00 0a 00 00 00 ................
| 2144: 00 00 00 0f a8 00 00 00 04 00 00 00 06 00 00 00 ................
| 2160: 08 00 00 00 0a 00 00 00 00 00 00 0b f2 00 00 00 ................
| 2176: 03 00 00 00 05 00 00 00 08 00 00 00 0a 00 00 01 ................
| 2192: 00 00 00 07 d8 00 00 00 02 00 00 00 04 00 00 00 ................
| 2208: 08 00 00 00 0a 00 00 00 00 00 00 03 f0 00 00 00 ................
| 2224: 01 00 00 00 03 00 00 00 08 00 00 00 09 ff 00 00 ................
| 2240: 00 00 00 13 91 00 00 00 05 00 00 00 07 00 00 00 ................
| 2256: 09 00 00 00 0b 00 00 00 00 00 00 0f a9 00 00 00 ................
| 2272: 04 00 00 00 06 00 00 00 09 00 00 00 0b 00 00 00 ................
| 2288: 00 00 00 0b c1 00 00 00 03 00 00 00 05 00 00 00 ................
| 2304: 09 00 00 00 0b 00 00 00 00 00 00 07 d9 00 00 00 ................
| 2320: 02 00 00 00 04 00 00 00 09 00 00 00 0b 00 00 01 ................
| 2336: 00 00 00 03 f0 ff ff 00 01 00 00 00 03 00 00 00 ................
| 2352: 09 00 00 00 0b 00 00 00 00 00 00 13 92 00 00 00 ................
| 2368: 05 00 00 00 07 00 00 00 0a 00 00 00 0c 00 00 00 ................
| 2384: 00 00 00 0f aa 00 00 00 04 00 00 00 06 00 00 00 ................
| 2400: 0a 00 00 00 0c 00 00 00 00 00 00 0b c2 00 00 00 ................
| 2416: 03 00 00 00 05 00 00 00 0a 00 00 00 0c 00 00 00 ................
| 2432: 00 00 00 07 da 00 00 00 02 00 00 00 04 00 00 00 ................
| 2448: 0a 00 00 00 0c 00 00 00 00 00 00 03 f2 00 00 00 ................
| 2464: 01 00 00 10 03 00 00 00 0a 00 00 00 0c 00 00 00 ................
| 2480: 00 00 00 03 eb 00 00 00 01 00 00 00 03 00 00 00 ................
| 2496: 03 00 00 00 05 00 00 00 00 00 00 07 d3 00 00 00 ................
| 2512: 02 00 00 00 04 00 00 00 03 00 00 00 05 00 00 00 ................
| 2528: 00 00 00 0b bb 00 00 00 03 00 00 00 05 00 00 00 ................
| 2544: 03 00 00 00 05 00 00 00 00 00 00 0f a3 00 00 00 ................
| 2560: 04 00 00 00 06 00 00 00 03 00 00 00 05 00 00 00 ................
| 2576: 00 00 00 13 8b 00 00 00 05 00 00 00 07 00 00 00 ................
| 2592: 03 00 00 00 05 00 00 00 00 00 00 03 ea 00 00 00 ................
| 2608: 01 00 00 00 03 00 00 00 02 00 00 00 04 00 00 00 ................
| 2624: 00 00 00 07 d2 00 00 00 02 00 00 00 04 00 00 00 ................
| 2640: 02 00 00 00 04 00 00 00 00 00 00 0b ba 00 00 00 ................
| 2656: 03 00 00 00 05 00 00 00 02 00 00 00 04 00 00 00 ................
| 2672: 00 00 00 0f a1 ff ff ff 04 00 00 00 06 00 00 00 ................
| 2688: 02 00 00 00 04 00 00 00 00 00 00 13 8a 00 00 00 ................
| 2704: 05 00 00 00 06 ff ff ff f2 00 00 00 04 00 00 00 ................
| 2720: 00 00 00 03 e9 00 00 00 01 00 00 00 03 00 00 00 ................
| 2736: 01 00 00 00 03 00 00 00 00 00 00 07 d1 00 00 00 ................
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
| 2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 02 ...$............
| 2880: ff ff ff 06 00 00 00 0c 00 00 00 01 00 00 00 0b ................
| 2896: 00 00 00 00 00 00 00 02 40 00 00 00 00 00 00 00 ........@.......
| end crash-2e81f5dce5cbd4.db}]
execsql { PRAGMA writable_schema = 1;}
catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}
finish_test

View File

@ -1837,7 +1837,7 @@ static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){
i64 nNew = p->nAlloc ? p->nAlloc : 128;
do {
nNew = nNew*2;
}while( (nNew-p->nBuf)<nByte );
}while( (size_t)(nNew-p->nBuf)<nByte );
aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
if( 0==aNew ){

View File

@ -527,7 +527,6 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000

411
manifest

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6
18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b

View File

@ -136,8 +136,8 @@ void sqlite3AlterRenameTable(
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
exit_rename_table;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
goto exit_rename_table;
}
#ifndef SQLITE_OMIT_VIEW
@ -435,6 +435,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
goto exit_begin_add_column;
}
sqlite3MayAbort(pParse);
assert( pTab->addColOffset>0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);

View File

@ -27,13 +27,13 @@
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** created and used by SQLite versions 3.7.9 through 3.29.0 when
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
** version of sqlite_stat3 and is only available when compiled with
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
** not possible to enable both STAT3 and STAT4 at the same time. If they
** are both enabled, then STAT4 takes precedence.
** is a superset of sqlite_stat2 and is also now deprecated. The
** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only
** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite
** versions 3.8.1 and later. STAT4 is the only variant that is still
** supported.
**
** For most applications, sqlite_stat1 provides all the statistics required
** for the query planner to make good choices.
@ -144,17 +144,11 @@
#if defined(SQLITE_ENABLE_STAT4)
# define IsStat4 1
# define IsStat3 0
#elif defined(SQLITE_ENABLE_STAT3)
# define IsStat4 0
# define IsStat3 1
#else
# define IsStat4 0
# define IsStat3 0
# undef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 1
#endif
#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */
/*
** This routine generates code that opens the sqlite_statN tables.
@ -183,14 +177,10 @@ static void openStatTable(
{ "sqlite_stat1", "tbl,idx,stat" },
#if defined(SQLITE_ENABLE_STAT4)
{ "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
{ "sqlite_stat3", 0 },
#elif defined(SQLITE_ENABLE_STAT3)
{ "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
{ "sqlite_stat4", 0 },
#else
{ "sqlite_stat3", 0 },
{ "sqlite_stat4", 0 },
#endif
{ "sqlite_stat3", 0 },
};
int i;
sqlite3 *db = pParse->db;
@ -271,7 +261,7 @@ typedef struct Stat4Sample Stat4Sample;
struct Stat4Sample {
tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
tRowcnt *anLt; /* sqlite_stat4.nLt */
union {
i64 iRowid; /* Rowid in main table of the key */
@ -302,7 +292,7 @@ struct Stat4Accum {
/* Reclaim memory used by a Stat4Sample
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static void sampleClear(sqlite3 *db, Stat4Sample *p){
assert( db!=0 );
if( p->nRowid ){
@ -314,7 +304,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){
/* Initialize the BLOB value of a ROWID
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
assert( db!=0 );
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
@ -330,7 +320,7 @@ static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
/* Initialize the INTEGER value of a ROWID.
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
assert( db!=0 );
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
@ -343,7 +333,7 @@ static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
/*
** Copy the contents of object (*pFrom) into (*pTo).
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
pTo->isPSample = pFrom->isPSample;
pTo->iCol = pFrom->iCol;
@ -364,7 +354,7 @@ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
*/
static void stat4Destructor(void *pOld){
Stat4Accum *p = (Stat4Accum*)pOld;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
int i;
for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
@ -384,7 +374,7 @@ static void stat4Destructor(void *pOld){
** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
** total number of columns in the table.
**
** Note 2: C is only used for STAT3 and STAT4.
** Note 2: C is only used for STAT4.
**
** For indexes on ordinary rowid tables, N==K+1. But for indexes on
** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
@ -407,7 +397,7 @@ static void statInit(
int nColUp; /* nCol rounded up for alignment */
int n; /* Bytes of space to allocate */
sqlite3 *db; /* Database connection */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
int mxSample = SQLITE_STAT4_SAMPLES;
#endif
@ -424,7 +414,7 @@ static void statInit(
n = sizeof(*p)
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
@ -444,7 +434,7 @@ static void statInit(
p->current.anDLt = (tRowcnt*)&p[1];
p->current.anEq = &p->current.anDLt[nColUp];
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
{
u8 *pSpace; /* Allocated space not yet assigned */
int i; /* Used to iterate through p->aSample[] */
@ -479,7 +469,7 @@ static void statInit(
sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
}
static const FuncDef statInitFuncdef = {
2+IsStat34, /* nArg */
2+IsStat4, /* nArg */
SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
@ -519,7 +509,7 @@ static int sampleIsBetterPost(
}
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Return true if pNew is to be preferred over pOld.
**
@ -538,15 +528,11 @@ static int sampleIsBetter(
assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );
if( (nEqNew>nEqOld) ) return 1;
#ifdef SQLITE_ENABLE_STAT4
if( nEqNew==nEqOld ){
if( pNew->iCol<pOld->iCol ) return 1;
return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
}
return 0;
#else
return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
#endif
}
/*
@ -559,7 +545,6 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
assert( IsStat4 || nEqZero==0 );
#ifdef SQLITE_ENABLE_STAT4
/* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
** values in the anEq[] array of any sample in Stat4Accum.a[]. In
** other words, if nMaxEqZero is n, then it is guaranteed that there
@ -593,7 +578,6 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
goto find_new_min;
}
}
#endif
/* If necessary, remove sample iMin to make room for the new sample. */
if( p->nSample>=p->mxSample ){
@ -614,10 +598,8 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
/* The "rows less-than" for the rowid column must be greater than that
** for the last sample in the p->a[] array. Otherwise, the samples would
** be out of order. */
#ifdef SQLITE_ENABLE_STAT4
assert( p->nSample==0
|| pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
#endif
/* Insert the new sample */
pSample = &p->a[p->nSample];
@ -627,9 +609,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
/* Zero the first nEqZero entries in the anEq[] array. */
memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);
#ifdef SQLITE_ENABLE_STAT4
find_new_min:
#endif
find_new_min:
if( p->nSample>=p->mxSample ){
int iMin = -1;
for(i=0; i<p->mxSample; i++){
@ -642,7 +622,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
p->iMin = iMin;
}
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/*
** Field iChng of the index being scanned has changed. So at this point
@ -683,28 +663,7 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
#endif
#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
if( iChng==0 ){
tRowcnt nLt = p->current.anLt[0];
tRowcnt nEq = p->current.anEq[0];
/* Check if this is to be a periodic sample. If so, add it. */
if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
p->current.isPSample = 1;
sampleInsert(p, &p->current, 0);
p->current.isPSample = 0;
}else
/* Or if it is a non-periodic sample. Add it in this case too. */
if( p->nSample<p->mxSample
|| sampleIsBetter(p, &p->current, &p->a[p->iMin])
){
sampleInsert(p, &p->current, 0);
}
}
#endif
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#ifndef SQLITE_ENABLE_STAT4
UNUSED_PARAMETER( p );
UNUSED_PARAMETER( iChng );
#endif
@ -724,7 +683,7 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
** index being analyzed. The stat_get() SQL function will later be used to
** extract relevant information for constructing the sqlite_statN tables.
**
** The R parameter is only used for STAT3 and STAT4
** The R parameter is only used for STAT4
*/
static void statPush(
sqlite3_context *context,
@ -756,14 +715,14 @@ static void statPush(
}
for(i=iChng; i<p->nCol; i++){
p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
p->current.anLt[i] += p->current.anEq[i];
#endif
p->current.anEq[i] = 1;
}
}
p->nRow++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
}else{
@ -796,7 +755,7 @@ static void statPush(
#endif
}
static const FuncDef statPushFuncdef = {
2+IsStat34, /* nArg */
2+IsStat4, /* nArg */
SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
@ -827,7 +786,7 @@ static const FuncDef statPushFuncdef = {
** parameter will always be a poiner to a Stat4Accum object, never a
** NULL.
**
** If neither STAT3 nor STAT4 are enabled, then J is always
** If STAT4 is not 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
** stat1 table entry information.
@ -838,8 +797,8 @@ static void statGet(
sqlite3_value **argv
){
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/* STAT3 and STAT4 have a parameter on this routine. */
#ifdef SQLITE_ENABLE_STAT4
/* STAT4 has a parameter on this routine. */
int eCall = sqlite3_value_int(argv[1]);
assert( argc==2 );
assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
@ -894,7 +853,7 @@ static void statGet(
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
else if( eCall==STAT_GET_ROWID ){
if( p->iGet<0 ){
samplePushPrevious(p, 0);
@ -923,9 +882,7 @@ static void statGet(
}
}
if( IsStat3 ){
sqlite3_result_int64(context, (i64)aCnt[0]);
}else{
{
char *zRet = sqlite3MallocZero(p->nCol * 25);
if( zRet==0 ){
sqlite3_result_error_nomem(context);
@ -942,13 +899,13 @@ static void statGet(
}
}
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( argc );
#endif
}
static const FuncDef statGetFuncdef = {
1+IsStat34, /* nArg */
1+IsStat4, /* nArg */
SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
@ -961,7 +918,7 @@ static const FuncDef statGetFuncdef = {
static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
assert( regOut!=regStat4 && regOut!=regStat4+1 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
#elif SQLITE_DEBUG
assert( iParam==STAT_GET_STAT1 );
@ -970,7 +927,7 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
#endif
sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
(char*)&statGetFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 1 + IsStat34);
sqlite3VdbeChangeP5(v, 1 + IsStat4);
}
/*
@ -997,7 +954,7 @@ static void analyzeOneTable(
int regNewRowid = iMem++; /* Rowid for the inserted record */
int regStat4 = iMem++; /* Register to hold Stat4Accum object */
int regChng = iMem++; /* Index of changed index field */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
#endif
int regTemp = iMem++; /* Temporary use register */
@ -1131,16 +1088,16 @@ static void analyzeOneTable(
** (3) the number of rows in the index,
**
**
** The third argument is only used for STAT3 and STAT4
** The third argument is only used for STAT4
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
#endif
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
(char*)&statInitFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 2+IsStat34);
sqlite3VdbeChangeP5(v, 2+IsStat4);
/* Implementation of the following:
**
@ -1211,12 +1168,12 @@ static void analyzeOneTable(
/*
** chng_addr_N:
** regRowid = idx(rowid) // STAT34 only
** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
** regRowid = idx(rowid) // STAT4 only
** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only
** Next csr
** if !eof(csr) goto next_row;
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
assert( regRowid==(regStat4+2) );
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
@ -1237,7 +1194,7 @@ static void analyzeOneTable(
assert( regChng==(regStat4+1) );
sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
(char*)&statPushFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 2+IsStat34);
sqlite3VdbeChangeP5(v, 2+IsStat4);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
/* Add the entry to the stat1 table. */
@ -1251,8 +1208,8 @@ static void analyzeOneTable(
#endif
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
/* Add the entries to the stat3 or stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/* Add the entries to the stat4 table. */
#ifdef SQLITE_ENABLE_STAT4
{
int regEq = regStat1;
int regLt = regStat1+1;
@ -1275,21 +1232,17 @@ static void analyzeOneTable(
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
VdbeCoverage(v);
#ifdef SQLITE_ENABLE_STAT3
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
#else
for(i=0; i<nCol; i++){
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
#endif
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
sqlite3VdbeJumpHere(v, addrIsNull);
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/* End of analysis */
sqlite3VdbeJumpHere(v, addrRewind);
@ -1464,7 +1417,7 @@ static void decodeIntArray(
int i;
tRowcnt v;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( z==0 ) z = "";
#else
assert( z!=0 );
@ -1475,7 +1428,7 @@ static void decodeIntArray(
v = v*10 + c - '0';
z++;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( aOut ) aOut[i] = v;
if( aLog ) aLog[i] = sqlite3LogEst(v);
#else
@ -1486,7 +1439,7 @@ static void decodeIntArray(
#endif
if( *z==' ' ) z++;
}
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#ifndef SQLITE_ENABLE_STAT4
assert( pIndex!=0 ); {
#else
if( pIndex ){
@ -1497,7 +1450,9 @@ static void decodeIntArray(
if( sqlite3_strglob("unordered*", z)==0 ){
pIndex->bUnordered = 1;
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
int sz = sqlite3Atoi(z+3);
if( sz<2 ) sz = 2;
pIndex->szIdxRow = sqlite3LogEst(sz);
}else if( sqlite3_strglob("noskipscan*", z)==0 ){
pIndex->noSkipScan = 1;
}
@ -1551,7 +1506,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
if( pIndex ){
tRowcnt *aiRowEst = 0;
int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/* Index.aiRowEst may already be set here if there are duplicate
** sqlite_stat1 entries for this index. In that case just clobber
** the old data with the new instead of allocating a new array. */
@ -1587,7 +1542,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
** and its contents.
*/
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( pIdx->aSample ){
int j;
for(j=0; j<pIdx->nSample; j++){
@ -1603,10 +1558,10 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
#else
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pIdx);
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Populate the pIdx->aAvgEq[] array based on the samples currently
** stored in pIdx->aSample[].
@ -1684,12 +1639,11 @@ static Index *findIndexOrPrimaryKey(
}
/*
** Load the content from either the sqlite_stat4 or sqlite_stat3 table
** Load the content from either the sqlite_stat4
** into the relevant Index.aSample[] arrays.
**
** Arguments zSql1 and zSql2 must point to SQL statements that return
** data equivalent to the following (statements are different for stat3,
** see the caller of this function for details):
** data equivalent to the following:
**
** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
@ -1698,7 +1652,6 @@ static Index *findIndexOrPrimaryKey(
*/
static int loadStatTbl(
sqlite3 *db, /* Database handle */
int bStat3, /* Assume single column records only */
const char *zSql1, /* SQL statement 1 (see above) */
const char *zSql2, /* SQL statement 2 (see above) */
const char *zDb /* Database name (e.g. "main") */
@ -1732,17 +1685,13 @@ static int loadStatTbl(
if( zIndex==0 ) continue;
nSample = sqlite3_column_int(pStmt, 1);
pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
/* Index.nSample is non-zero at this point if data has already been
** loaded from the stat4 table. In this case ignore stat3 data. */
if( pIdx==0 || pIdx->nSample ) continue;
if( bStat3==0 ){
assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
nIdxCol = pIdx->nKeyCol;
}else{
nIdxCol = pIdx->nColumn;
}
assert( pIdx==0 || pIdx->nSample==0 );
if( pIdx==0 ) continue;
assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
nIdxCol = pIdx->nKeyCol;
}else{
nIdxCol = pIdx->nColumn;
}
pIdx->nSampleCol = nIdxCol;
nByte = sizeof(IndexSample) * nSample;
@ -1784,9 +1733,8 @@ static int loadStatTbl(
pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
if( pIdx==0 ) continue;
/* This next condition is true if data has already been loaded from
** the sqlite_stat4 table. In this case ignore stat3 data. */
** the sqlite_stat4 table. */
nCol = pIdx->nSampleCol;
if( bStat3 && nCol>1 ) continue;
if( pIdx!=pPrevIdx ){
initAvgEq(pPrevIdx);
pPrevIdx = pIdx;
@ -1819,7 +1767,7 @@ static int loadStatTbl(
}
/*
** Load content from the sqlite_stat4 and sqlite_stat3 tables into
** Load content from the sqlite_stat4 table into
** the Index.aSample[] arrays of all indices.
*/
static int loadStat4(sqlite3 *db, const char *zDb){
@ -1827,37 +1775,28 @@ static int loadStat4(sqlite3 *db, const char *zDb){
assert( db->lookaside.bDisable );
if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
rc = loadStatTbl(db, 0,
rc = loadStatTbl(db,
"SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
"SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
zDb
);
}
if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
rc = loadStatTbl(db, 1,
"SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx",
"SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
zDb
);
}
return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/*
** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
** arrays. The contents of sqlite_stat3/4 are used to populate the
** arrays. The contents of sqlite_stat4 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined
** during compilation and the sqlite_stat3/4 table is present, no data is
** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined
** during compilation and the sqlite_stat4 table is present, no data is
** read from it.
**
** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the
** If SQLITE_ENABLE_STAT4 was defined during compilation and the
** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
@ -1885,7 +1824,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
pIdx->hasStat1 = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
#endif
@ -1913,7 +1852,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( rc==SQLITE_OK ){
db->lookaside.bDisable++;
rc = loadStat4(db, sInfo.zDatabase);

View File

@ -299,6 +299,7 @@ static void detachFunc(
sqlite3 *db = sqlite3_context_db_handle(context);
int i;
Db *pDb = 0;
HashElem *pEntry;
char zErr[128];
UNUSED_PARAMETER(NotUsed);
@ -323,6 +324,18 @@ static void detachFunc(
goto detach_error;
}
/* If any TEMP triggers reference the schema being detached, move those
** triggers to reference the TEMP schema itself. */
assert( db->aDb[1].pSchema );
pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash);
while( pEntry ){
Trigger *pTrig = (Trigger*)sqliteHashData(pEntry);
if( pTrig->pTabSchema==pDb->pSchema ){
pTrig->pTabSchema = pTrig->pSchema;
}
pEntry = sqliteHashNext(pEntry);
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
@ -560,6 +573,7 @@ int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
ExprSetProperty(pExpr, EP_Indirect);
if( pExpr->op==TK_VARIABLE ){
if( pFix->pParse->db->init.busy ){
pExpr->op = TK_NULL;

View File

@ -78,7 +78,7 @@ int sqlite3_set_authorizer(
sqlite3_mutex_enter(db->mutex);
db->xAuth = (sqlite3_xauth)xAuth;
db->pAuthArg = pArg;
sqlite3ExpirePreparedStatements(db, 0);
if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1);
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}

View File

@ -640,8 +640,10 @@ int sqlite3_backup_finish(sqlite3_backup *p){
}
if( p->isAttached ){
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
assert( pp!=0 );
while( *pp!=p ){
pp = &(*pp)->pNext;
assert( pp!=0 );
}
*pp = p->pNext;
}

View File

@ -1647,9 +1647,12 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
if( pSpace ){
assert( pSpace>=data && (pSpace - data)<65536 );
*pIdx = (int)(pSpace - data);
return SQLITE_OK;
assert( pSpace+nByte<=data+pPage->pBt->usableSize );
if( (*pIdx = (int)(pSpace-data))<=gap ){
return SQLITE_CORRUPT_PAGE(pPage);
}else{
return SQLITE_OK;
}
}else if( rc ){
return rc;
}
@ -4876,6 +4879,7 @@ static int accessPayload(
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
@ -6664,12 +6668,7 @@ static void insertCell(
assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* The cell should normally be sized correctly. However, when moving a
** malformed cell from a leaf page to an interior page, if the cell size
** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
** might be less than 8 (leaf-size + pointer) on the interior node. Hence
** the term after the || in the following assert(). */
assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB );
assert( pPage->nFree>=0 );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
@ -6901,7 +6900,7 @@ static int rebuildPage(
assert( i<iEnd );
j = get2byte(&aData[hdr+5]);
if( NEVER(j>(u32)usableSize) ){ j = 0; }
if( j>(u32)usableSize ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
@ -6993,7 +6992,8 @@ static int pageInsertArray(
while( 1 /*Exit by break*/ ){
int sz, rc;
u8 *pSlot;
sz = cachedCellSize(pCArray, i);
assert( pCArray->szCell[i]!=0 );
sz = pCArray->szCell[i];
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
if( (pData - pBegin)<sz ) return 1;
pData -= sz;
@ -7154,6 +7154,7 @@ static int editPage(
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
}
nCell++;
cachedCellSize(pCArray, iCell+iNew);
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iCell+iNew, 1, pCArray
@ -7676,7 +7677,7 @@ static int balance_nonroot(
*/
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
if( pOld->nOverflow>0 ){
if( limit<pOld->aiOvfl[0] ){
if( NEVER(limit<pOld->aiOvfl[0]) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
@ -7962,6 +7963,8 @@ static int balance_nonroot(
));
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
assert( nNew>=1 && nNew<=ArraySize(apNew) );
assert( apNew[nNew-1]!=0 );
put4byte(pRight, apNew[nNew-1]->pgno);
/* If the sibling pages are not leaves, ensure that the right-child pointer
@ -8307,11 +8310,13 @@ static int balance(BtCursor *pCur){
VVA_ONLY( int balance_deeper_called = 0 );
do {
int iPage = pCur->iPage;
int iPage;
MemPage *pPage = pCur->pPage;
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
if( iPage==0 ){
if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
break;
}else if( (iPage = pCur->iPage)==0 ){
if( pPage->nOverflow ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
@ -8332,8 +8337,6 @@ static int balance(BtCursor *pCur){
}else{
break;
}
}else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
break;
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
@ -8475,7 +8478,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
Pgno ovflPgno; /* Next overflow page to write */
u32 ovflPageSize; /* Size to write on overflow page */
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|| pCur->info.pPayload < pPage->aData + pPage->cellOffset
){
return SQLITE_CORRUPT_BKPT;
}
/* Overwrite the local portion first */
@ -8716,6 +8721,8 @@ int sqlite3BtreeInsert(
memcpy(newCell, oldCell, 4);
}
rc = clearCell(pPage, oldCell, &info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
&& (!ISAUTOVACUUM || szNew<pPage->minLocal)
){
@ -8729,7 +8736,12 @@ int sqlite3BtreeInsert(
** new entry uses overflow pages, as the insertCell() call below is
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
return SQLITE_CORRUPT_BKPT;
}
if( oldCell+szNew > pPage->aDataEnd ){
return SQLITE_CORRUPT_BKPT;
}
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
}

View File

@ -456,7 +456,7 @@ void sqlite3FreeIndex(sqlite3 *db, Index *p){
sqlite3ExprListDelete(db, p->aColExpr);
sqlite3DbFree(db, p->zColAff);
if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
sqlite3_free(p->aiRowEst);
#endif
sqlite3DbFree(db, p);
@ -829,13 +829,40 @@ int sqlite3WritableSchema(sqlite3 *db){
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
**
** When parsing the sqlite_master table, this routine also checks to
** make sure the "type", "name", and "tbl_name" columns are consistent
** with the SQL.
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
&& sqlite3WritableSchema(pParse->db)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
int sqlite3CheckObjectName(
Parse *pParse, /* Parsing context */
const char *zName, /* Name of the object to check */
const char *zType, /* Type of this object */
const char *zTblName /* Parent table name for triggers and indexes */
){
sqlite3 *db = pParse->db;
if( sqlite3WritableSchema(db) || db->init.imposterTable ){
/* Skip these error checks for writable_schema=ON */
return SQLITE_OK;
}
if( db->init.busy ){
if( sqlite3_stricmp(zType, db->init.azInit[0])
|| sqlite3_stricmp(zName, db->init.azInit[1])
|| sqlite3_stricmp(zTblName, db->init.azInit[2])
){
if( sqlite3Config.bExtraSchemaChecks ){
sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
return SQLITE_ERROR;
}
}
}else{
if( pParse->nested==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7)
){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
zName);
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
@ -916,7 +943,7 @@ void sqlite3StartTable(
}
pParse->sNameToken = *pName;
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
goto begin_table_error;
}
if( db->init.iDb==1 ) isTemp = 1;
@ -1416,7 +1443,7 @@ void sqlite3AddPrimaryKey(
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@ -1831,6 +1858,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
Index *pIdx;
Index *pPk;
int nPk;
int nExtra;
int i, j;
sqlite3 *db = pParse->db;
Vdbe *v = pParse->pVdbe;
@ -1866,13 +1894,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
pList->a[0].sortOrder = pParse->iPkSortOrder;
pList->a[0].sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( db->mallocFailed || pParse->nErr ) return;
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
@ -1887,6 +1916,8 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pPk->nColumn--;
}else{
testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) );
pPk->azColl[j] = pPk->azColl[i];
pPk->aSortOrder[j] = pPk->aSortOrder[i];
pPk->aiColumn[j++] = pPk->aiColumn[i];
}
}
@ -1895,7 +1926,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pPk!=0 );
pPk->isCovering = 1;
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
nPk = pPk->nKeyCol;
nPk = pPk->nColumn = pPk->nKeyCol;
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
** table entry. This is only required if currently generating VDBE
@ -1945,21 +1976,21 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
/* Add all table columns to the PRIMARY KEY index
*/
if( nPk<pTab->nCol ){
if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
for(i=0, j=nPk; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, j, i) ){
assert( j<pPk->nColumn );
pPk->aiColumn[j] = i;
pPk->azColl[j] = sqlite3StrBINARY;
j++;
}
}
assert( pPk->nColumn==j );
assert( pTab->nCol==j );
}else{
pPk->nColumn = pTab->nCol;
nExtra = 0;
for(i=0; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, nPk, i) ) nExtra++;
}
if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, j, i) ){
assert( j<pPk->nColumn );
pPk->aiColumn[j] = i;
pPk->azColl[j] = sqlite3StrBINARY;
j++;
}
}
assert( pPk->nColumn==j );
assert( pTab->nCol<=j );
recomputeColumnsNotIndexed(pPk);
}
@ -2156,7 +2187,7 @@ void sqlite3EndTable(
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
if( pParse->nErr ) return;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
@ -2420,10 +2451,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
db->xAuth = xAuth;
#else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = n;
if( pTable->pCheck ){
@ -2439,7 +2470,8 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
&& pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
}else if( pSelTab ){
/* CREATE VIEW name AS... without an argument list. Construct
@ -2784,7 +2816,8 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
#endif
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
&& sqlite3StrNICmp(pTab->zName+7, "stat", 4)!=0
&& sqlite3StrNICmp(pTab->zName+7, "parameters", 10)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@ -3121,6 +3154,27 @@ Index *sqlite3AllocateIndexObject(
return p;
}
/*
** If expression list pList contains an expression that was parsed with
** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
** pParse and return non-zero. Otherwise, return zero.
*/
int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].bNulls ){
u8 sf = pList->a[i].sortFlags;
sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
(sf==0 || sf==3) ? "FIRST" : "LAST"
);
return 1;
}
}
}
return 0;
}
/*
** Create a new index for an SQL table. pName1.pName2 is the name of the index
** and pTblList is the name of the table that is to be indexed. Both will
@ -3172,6 +3226,9 @@ void sqlite3CreateIndex(
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_create_index;
}
if( sqlite3HasExplicitNulls(pParse, pList) ){
goto exit_create_index;
}
/*
** Find the table that is to be indexed. Return early if not found.
@ -3270,7 +3327,7 @@ void sqlite3CreateIndex(
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) goto exit_create_index;
assert( pName->z!=0 );
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
goto exit_create_index;
}
if( !IN_RENAME_OBJECT ){
@ -3336,7 +3393,7 @@ void sqlite3CreateIndex(
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index;
assert( pList->nExpr==1 );
sqlite3ExprListSetSortOrder(pList, sortOrder);
sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
}else{
sqlite3ExprListCheckLength(pParse, pList, "index");
if( pParse->nErr ) goto exit_create_index;
@ -3454,7 +3511,7 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
requestedSortOrder = pListItem->sortFlags & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
@ -3629,6 +3686,7 @@ void sqlite3CreateIndex(
/* Gather the complete text of the CREATE INDEX statement into
** the zStmt variable
*/
assert( pName!=0 || pStart==0 );
if( pStart ){
int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
if( pName->z[n-1]==';' ) n--;
@ -4671,7 +4729,8 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
const char *zColl = pIdx->azColl[i];
pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
sqlite3LocateCollSeq(pParse, zColl);
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
pKey->aSortFlags[i] = pIdx->aSortOrder[i];
assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
}
if( pParse->nErr ){
assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );

View File

@ -306,8 +306,6 @@ static const char * const sqlite3azCompileOpt[] = {
#endif
#if defined(SQLITE_ENABLE_STAT4)
"ENABLE_STAT4",
#elif defined(SQLITE_ENABLE_STAT3)
"ENABLE_STAT3",
#endif
#if SQLITE_ENABLE_STMTVTAB
"ENABLE_STMTVTAB",

View File

@ -44,7 +44,6 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){
*/
char sqlite3ExprAffinity(Expr *pExpr){
int op;
if( pExpr->flags & EP_Generic ) return 0;
while( ExprHasProperty(pExpr, EP_Skip) ){
assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
@ -71,7 +70,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
return pExpr->affinity;
return pExpr->affExpr;
}
/*
@ -106,10 +105,22 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
}
/*
** Skip over any TK_COLLATE operators and any unlikely()
** or likelihood() function at the root of an expression.
** Skip over any TK_COLLATE operators.
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
return pExpr;
}
/*
** Skip over any TK_COLLATE operators and/or any unlikely()
** or likelihood() or likely() functions at the root of an
** expression.
*/
Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@ -144,7 +155,6 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
Expr *p = pExpr;
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
if( op==TK_REGISTER ) op = p->op2;
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
&& p->y.pTab!=0
@ -230,7 +240,7 @@ int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
*/
char sqlite3CompareAffinity(Expr *pExpr, char aff2){
char aff1 = sqlite3ExprAffinity(pExpr);
if( aff1 && aff2 ){
if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){
/* Both sides of the comparison are columns. If one has numeric
** affinity, use that. Otherwise use no affinity.
*/
@ -239,15 +249,10 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
}else{
return SQLITE_AFF_BLOB;
}
}else if( !aff1 && !aff2 ){
/* Neither side of the comparison is a column. Compare the
** results directly.
*/
return SQLITE_AFF_BLOB;
}else{
/* One side is a column, the other is not. Use the columns affinity. */
assert( aff1==0 || aff2==0 );
return (aff1 + aff2);
assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE );
return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE;
}
}
@ -280,14 +285,13 @@ static char comparisonAffinity(Expr *pExpr){
*/
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
char aff = comparisonAffinity(pExpr);
switch( aff ){
case SQLITE_AFF_BLOB:
return 1;
case SQLITE_AFF_TEXT:
return idx_affinity==SQLITE_AFF_TEXT;
default:
return sqlite3IsNumericAffinity(idx_affinity);
if( aff<SQLITE_AFF_TEXT ){
return 1;
}
if( aff==SQLITE_AFF_TEXT ){
return idx_affinity==SQLITE_AFF_TEXT;
}
return sqlite3IsNumericAffinity(idx_affinity);
}
/*
@ -901,7 +905,7 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
}else if( ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight) ){
sqlite3ExprUnmapAndDelete(pParse, pLeft);
sqlite3ExprUnmapAndDelete(pParse, pRight);
return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
}
@ -1040,15 +1044,18 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p->x.pList==0 || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
if( p->pRight ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlite3ExprDeleteNN(db, p->pRight);
}else if( ExprHasProperty(p, EP_xIsSelect) ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlite3SelectDelete(db, p->x.pSelect);
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
if( ExprHasProperty(p, EP_WinFunc) ){
assert( p->op==TK_FUNCTION );
sqlite3WindowDelete(db, p->y.pWin);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(p, EP_WinFunc) ){
sqlite3WindowDelete(db, p->y.pWin);
}
#endif
}
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
@ -1083,16 +1090,6 @@ static int exprStructSize(Expr *p){
return EXPR_FULLSIZE;
}
/*
** Copy the complete content of an Expr node, taking care not to read
** past the end of the structure for a reduced-size version of the source
** Expr.
*/
static void exprNodeCopy(Expr *pDest, Expr *pSrc){
memset(pDest, 0, sizeof(Expr));
memcpy(pDest, pSrc, exprStructSize(pSrc));
}
/*
** The dupedExpr*Size() routines each return the number of bytes required
** to store a copy of an expression or expression tree. They differ in
@ -1332,10 +1329,13 @@ static With *withDup(sqlite3 *db, With *p){
** objects found there, assembling them onto the linked list at Select->pWin.
*/
static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
assert( ExprHasProperty(pExpr, EP_WinFunc) );
pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
pWalker->u.pSelect->pWin = pExpr->y.pWin;
if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){
Select *pSelect = pWalker->u.pSelect;
Window *pWin = pExpr->y.pWin;
assert( pWin );
assert( IsWindowFunc(pExpr) );
assert( pWin->ppThis==0 );
sqlite3WindowLink(pSelect, pWin);
}
return WRC_Continue;
}
@ -1409,8 +1409,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
}
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
pItem->sortFlags = pOldItem->sortFlags;
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->u = pOldItem->u;
@ -1521,7 +1522,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin ) gatherSelectWindows(pNew);
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
*pp = pNew;
@ -1630,6 +1631,10 @@ ExprList *sqlite3ExprListAppendVector(
for(i=0; i<pColumns->nId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
assert( pSubExpr!=0 || db->mallocFailed );
assert( pSubExpr==0 || pSubExpr->iTable==0 );
if( pSubExpr==0 ) continue;
pSubExpr->iTable = pColumns->nId;
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
assert( pList->nExpr==iFirst+i+1 );
@ -1662,15 +1667,34 @@ vector_append_error:
/*
** Set the sort order for the last element on the given ExprList.
*/
void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){
struct ExprList_item *pItem;
if( p==0 ) return;
assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
assert( p->nExpr>0 );
if( iSortOrder<0 ){
assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
return;
assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 );
assert( iSortOrder==SQLITE_SO_UNDEFINED
|| iSortOrder==SQLITE_SO_ASC
|| iSortOrder==SQLITE_SO_DESC
);
assert( eNulls==SQLITE_SO_UNDEFINED
|| eNulls==SQLITE_SO_ASC
|| eNulls==SQLITE_SO_DESC
);
pItem = &p->a[p->nExpr-1];
assert( pItem->bNulls==0 );
if( iSortOrder==SQLITE_SO_UNDEFINED ){
iSortOrder = SQLITE_SO_ASC;
}
pItem->sortFlags = (u8)iSortOrder;
if( eNulls!=SQLITE_SO_UNDEFINED ){
pItem->bNulls = 1;
if( iSortOrder!=eNulls ){
pItem->sortFlags |= KEYINFO_ORDER_BIGNULL;
}
}
p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
}
/*
@ -2169,27 +2193,30 @@ int sqlite3ExprCanBeNull(const Expr *p){
*/
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
u8 op;
int unaryMinus = 0;
if( aff==SQLITE_AFF_BLOB ) return 1;
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
if( p->op==TK_UMINUS ) unaryMinus = 1;
p = p->pLeft;
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
switch( op ){
case TK_INTEGER: {
return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
return aff>=SQLITE_AFF_NUMERIC;
}
case TK_FLOAT: {
return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
return aff>=SQLITE_AFF_NUMERIC;
}
case TK_STRING: {
return aff==SQLITE_AFF_TEXT;
return !unaryMinus && aff==SQLITE_AFF_TEXT;
}
case TK_BLOB: {
return 1;
return !unaryMinus;
}
case TK_COLUMN: {
assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
return p->iColumn<0
&& (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0;
}
default: {
return 0;
@ -2372,7 +2399,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
Parse *pParse, /* Parsing context */
Expr *pX, /* The right-hand side (RHS) of the IN operator */
Expr *pX, /* The IN expression */
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
int *prRhsHasNull, /* Register holding NULL status. See notes */
int *aiMap, /* Mapping from Index fields to RHS fields */
@ -2797,9 +2824,9 @@ void sqlite3CodeRhsOfIN(
int i;
ExprList *pList = pExpr->x.pList;
struct ExprList_item *pItem;
int r1, r2, r3;
int r1, r2;
affinity = sqlite3ExprAffinity(pLeft);
if( !affinity ){
if( affinity<=SQLITE_AFF_NONE ){
affinity = SQLITE_AFF_BLOB;
}
if( pKeyInfo ){
@ -2825,9 +2852,9 @@ void sqlite3CodeRhsOfIN(
}
/* Evaluate the expression and insert it into the temp table */
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
sqlite3ExprCode(pParse, pE2, r1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
@ -2840,6 +2867,7 @@ void sqlite3CodeRhsOfIN(
/* Subroutine return */
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
}
}
#endif /* SQLITE_OMIT_SUBQUERY */
@ -2853,7 +2881,7 @@ void sqlite3CodeRhsOfIN(
**
** The pExpr parameter is the SELECT or EXISTS operator to be coded.
**
** The register that holds the result. For a multi-column SELECT,
** Return the register that holds the result. For a multi-column SELECT,
** the result is stored in a contiguous array of registers and the
** return value is the register of the left-most result column.
** Return 0 if an error occurs.
@ -2931,11 +2959,21 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result"));
}
pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
if( pSel->pLimit ){
sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
/* The subquery already has a limit. If the pre-existing limit is X
** then make the new limit X<>0 so that the new limit is either 1 or 0 */
sqlite3 *db = pParse->db;
pLimit = sqlite3Expr(db, TK_INTEGER, "0");
if( pLimit ){
pLimit->affExpr = SQLITE_AFF_NUMERIC;
pLimit = sqlite3PExpr(pParse, TK_NE,
sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
}
sqlite3ExprDelete(db, pSel->pLimit->pLeft);
pSel->pLimit->pLeft = pLimit;
}else{
/* If there is no pre-existing limit add a limit of 1 */
pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0;
@ -2950,6 +2988,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
/* Subroutine return */
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
}
return rReg;
@ -3097,13 +3136,21 @@ static void sqlite3ExprCodeIN(
int r2, regToFree;
int regCkNull = 0;
int ii;
int bLhsReal; /* True if the LHS of the IN has REAL affinity */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( destIfNull!=destIfFalse ){
regCkNull = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
}
bLhsReal = sqlite3ExprAffinity(pExpr->pLeft)==SQLITE_AFF_REAL;
for(ii=0; ii<pList->nExpr; ii++){
r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
if( bLhsReal ){
r2 = regToFree = sqlite3GetTempReg(pParse);
sqlite3ExprCode(pParse, pList->a[ii].pExpr, r2);
sqlite3VdbeAddOp4(v, OP_Affinity, r2, 1, 0, "E", P4_STATIC);
}else{
r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
}
if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
}
@ -3388,7 +3435,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
** the correct value for the expression.
*/
static void exprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollate(pExpr);
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
@ -3489,7 +3536,7 @@ expr_code_doover:
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
if( aff!=SQLITE_AFF_BLOB ){
if( aff>SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
assert( SQLITE_AFF_TEXT=='B' );
@ -3505,7 +3552,19 @@ expr_code_doover:
if( iTab<0 ){
if( pParse->iSelfTab<0 ){
/* Generating CHECK constraints or inserting into partial index */
return pExpr->iColumn - pParse->iSelfTab;
assert( pExpr->y.pTab!=0 );
assert( pExpr->iColumn>=XN_ROWID );
assert( pExpr->iColumn<pExpr->y.pTab->nCol );
if( pExpr->iColumn>=0
&& pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab,
target);
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
return target;
}else{
return pExpr->iColumn - pParse->iSelfTab;
}
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */
@ -3792,7 +3851,7 @@ expr_code_doover:
assert( nFarg==1 );
aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
sqlite3VdbeLoadString(v, target,
aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
(aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
return target;
}
#endif
@ -3900,8 +3959,8 @@ expr_code_doover:
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
if( pExpr->iTable
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
if( pExpr->iTable!=0
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
@ -4004,10 +4063,23 @@ expr_code_doover:
break;
}
/* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions
** that derive from the right-hand table of a LEFT JOIN. The
** Expr.iTable value is the table number for the right-hand table.
** The expression is only evaluated if that table is not currently
** on a LEFT JOIN NULL row.
*/
case TK_IF_NULL_ROW: {
int addrINR;
u8 okConstFactor = pParse->okConstFactor;
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
/* Temporarily disable factoring of constant expressions, since
** even though expressions may appear to be constant, they are not
** really constant because they originate from the right-hand side
** of a LEFT JOIN. */
pParse->okConstFactor = 0;
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
pParse->okConstFactor = okConstFactor;
sqlite3VdbeJumpHere(v, addrINR);
sqlite3VdbeChangeP3(v, addrINR, inReg);
break;
@ -4044,6 +4116,8 @@ expr_code_doover:
Expr opCompare; /* The X==Ei expression */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
Expr *pDel = 0;
sqlite3 *db = pParse->db;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert(pExpr->x.pList->nExpr > 0);
@ -4052,13 +4126,17 @@ expr_code_doover:
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(pParse);
if( (pX = pExpr->pLeft)!=0 ){
exprNodeCopy(&tempX, pX);
pDel = sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDel);
break;
}
testcase( pX->op==TK_COLUMN );
exprToRegister(&tempX, exprCodeVector(pParse, &tempX, &regFree1));
exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
testcase( regFree1==0 );
memset(&opCompare, 0, sizeof(opCompare));
opCompare.op = TK_EQ;
opCompare.pLeft = &tempX;
opCompare.pLeft = pDel;
pTest = &opCompare;
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
** The value in regFree1 might get SCopy-ed into the file result.
@ -4086,32 +4164,33 @@ expr_code_doover:
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
sqlite3ExprDelete(db, pDel);
sqlite3VdbeResolveLabel(v, endLabel);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
assert( pExpr->affinity==OE_Rollback
|| pExpr->affinity==OE_Abort
|| pExpr->affinity==OE_Fail
|| pExpr->affinity==OE_Ignore
assert( pExpr->affExpr==OE_Rollback
|| pExpr->affExpr==OE_Abort
|| pExpr->affExpr==OE_Fail
|| pExpr->affExpr==OE_Ignore
);
if( !pParse->pTriggerTab ){
sqlite3ErrorMsg(pParse,
"RAISE() may only be used within a trigger-program");
return 0;
}
if( pExpr->affinity==OE_Abort ){
if( pExpr->affExpr==OE_Abort ){
sqlite3MayAbort(pParse);
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->affinity==OE_Ignore ){
if( pExpr->affExpr==OE_Ignore ){
sqlite3VdbeAddOp4(
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
VdbeCoverage(v);
}else{
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
pExpr->affinity, pExpr->u.zToken, 0, 0);
pExpr->affExpr, pExpr->u.zToken, 0, 0);
}
break;
@ -4176,7 +4255,7 @@ int sqlite3ExprCodeAtInit(
*/
int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r2;
pExpr = sqlite3ExprSkipCollate(pExpr);
pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
if( ConstFactorOk(pParse)
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
@ -4367,40 +4446,44 @@ static void exprCodeBetween(
void (*xJump)(Parse*,Expr*,int,int), /* Action to take */
int jumpIfNull /* Take the jump if the BETWEEN is NULL */
){
Expr exprAnd; /* The AND operator in x>=y AND x<=z */
Expr exprAnd; /* The AND operator in x>=y AND x<=z */
Expr compLeft; /* The x>=y term */
Expr compRight; /* The x<=z term */
Expr exprX; /* The x subexpression */
int regFree1 = 0; /* Temporary use register */
Expr *pDel = 0;
sqlite3 *db = pParse->db;
memset(&compLeft, 0, sizeof(Expr));
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
exprNodeCopy(&exprX, pExpr->pLeft);
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprToRegister(&exprX, exprCodeVector(pParse, &exprX, &regFree1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
/* Mark the expression is being from the ON or USING clause of a join
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
** have to reuse the EP_FromJoin bit. Bummer. */
exprX.flags |= EP_FromJoin;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
pDel = sqlite3ExprDup(db, pExpr->pLeft, 0);
if( db->mallocFailed==0 ){
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.pLeft = pDel;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
compRight.pLeft = pDel;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprToRegister(pDel, exprCodeVector(pParse, pDel, &regFree1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
/* Mark the expression is being from the ON or USING clause of a join
** so that the sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
** have to reuse the EP_FromJoin bit. Bummer. */
pDel->flags |= EP_FromJoin;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
sqlite3ReleaseTempReg(pParse, regFree1);
}
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ExprDelete(db, pDel);
/* Ensure adequate test coverage */
testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 );
@ -4839,20 +4922,17 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
return 2;
}
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
if( pA->op==TK_FUNCTION ){
if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
#ifndef SQLITE_OMIT_WINDOWFUNC
/* Justification for the assert():
** window functions have p->op==TK_FUNCTION but aggregate functions
** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
** function and a window function should have failed before reaching
** this point. And, it is not possible to have a window function and
** a scalar function with the same name and number of arguments. So
** if we reach this point, either A and B both window functions or
** neither are a window functions. */
assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
assert( pA->op==pB->op );
if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){
return 2;
}
if( ExprHasProperty(pA,EP_WinFunc) ){
if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){
return 2;
}
}
#endif
}else if( pA->op==TK_NULL ){
@ -4876,7 +4956,8 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->op2!=pB->op2 ) return 2;
if( pA->iTable!=pB->iTable
if( pA->op!=TK_IN
&& pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
}
@ -4906,7 +4987,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
for(i=0; i<pA->nExpr; i++){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1;
if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
}
return 0;
@ -4918,42 +4999,47 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
*/
int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
return sqlite3ExprCompare(0,
sqlite3ExprSkipCollate(pA),
sqlite3ExprSkipCollate(pB),
sqlite3ExprSkipCollateAndLikely(pA),
sqlite3ExprSkipCollateAndLikely(pB),
iTab);
}
/*
** Return non-zero if Expr p can only be true if pNN is not NULL.
**
** Or if seenNot is true, return non-zero if Expr p can only be
** non-NULL if pNN is not NULL
*/
static int exprImpliesNotNull(
Parse *pParse, /* Parsing context */
Expr *p, /* The expression to be checked */
Expr *pNN, /* The expression that is NOT NULL */
int iTab, /* Table being evaluated */
int seenNot /* True if p is an operand of NOT */
int seenNot /* Return true only if p can be any non-NULL value */
){
assert( p );
assert( pNN );
if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ) return 1;
if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){
return pNN->op!=TK_NULL;
}
switch( p->op ){
case TK_IN: {
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
assert( ExprHasProperty(p,EP_xIsSelect)
|| (p->x.pList!=0 && p->x.pList->nExpr>0) );
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
case TK_BETWEEN: {
ExprList *pList = p->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
if( seenNot ) return 0;
if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, seenNot)
|| exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, seenNot)
if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1)
|| exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1)
){
return 1;
}
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
case TK_EQ:
case TK_NE:
@ -4963,20 +5049,21 @@ static int exprImpliesNotNull(
case TK_GE:
case TK_PLUS:
case TK_MINUS:
case TK_BITOR:
case TK_LSHIFT:
case TK_RSHIFT:
case TK_CONCAT:
seenNot = 1;
/* Fall thru */
case TK_STAR:
case TK_REM:
case TK_BITAND:
case TK_BITOR:
case TK_SLASH:
case TK_LSHIFT:
case TK_RSHIFT:
case TK_CONCAT: {
case TK_SLASH: {
if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1;
/* Fall thru into the next case */
}
case TK_SPAN:
case TK_COLLATE:
case TK_BITNOT:
case TK_UPLUS:
case TK_UMINUS: {
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
@ -4984,8 +5071,9 @@ static int exprImpliesNotNull(
case TK_TRUTH: {
if( seenNot ) return 0;
if( p->op2!=TK_IS ) return 0;
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
case TK_BITNOT:
case TK_NOT: {
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
@ -5051,7 +5139,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
case TK_NOT:
case TK_ISNULL:
case TK_NOTNULL:
case TK_IS:
@ -5059,8 +5146,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
case TK_CASE:
case TK_IN:
case TK_FUNCTION:
case TK_TRUTH:
testcase( pExpr->op==TK_ISNOT );
testcase( pExpr->op==TK_NOT );
testcase( pExpr->op==TK_ISNULL );
testcase( pExpr->op==TK_NOTNULL );
testcase( pExpr->op==TK_IS );
@ -5068,6 +5155,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_CASE );
testcase( pExpr->op==TK_IN );
testcase( pExpr->op==TK_FUNCTION );
testcase( pExpr->op==TK_TRUTH );
return WRC_Prune;
case TK_COLUMN:
if( pWalker->u.iCur==pExpr->iTable ){
@ -5076,6 +5164,18 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
}
return WRC_Prune;
case TK_AND:
if( sqlite3ExprImpliesNonNullRow(pExpr->pLeft, pWalker->u.iCur)
&& sqlite3ExprImpliesNonNullRow(pExpr->pRight, pWalker->u.iCur)
){
pWalker->eCode = 1;
}
return WRC_Prune;
case TK_BETWEEN:
sqlite3WalkExpr(pWalker, pExpr->pLeft);
return WRC_Prune;
/* Virtual tables are allowed to use constraints like x=NULL. So
** a term of the form x=y does not prove that y is not null if x
** is the column of a virtual table */
@ -5096,6 +5196,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
){
return WRC_Prune;
}
default:
return WRC_Continue;
}
@ -5125,7 +5226,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
*/
int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
Walker w;
p = sqlite3ExprSkipCollate(p);
p = sqlite3ExprSkipCollateAndLikely(p);
while( p ){
if( p->op==TK_NOTNULL ){
p = p->pLeft;
@ -5231,7 +5332,10 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){
}
if( i<nSrc ){
p->nThis++;
}else{
}else if( nSrc==0 || pExpr->iTable<pSrc->a[0].iCursor ){
/* In a well-formed parse tree (no name resolution errors),
** TK_COLUMN nodes with smaller Expr.iTable values are in an
** outer context. Those are the only ones to count as "other" */
p->nOther++;
}
}
@ -5248,8 +5352,9 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
Walker w;
struct SrcCount cnt;
assert( pExpr->op==TK_AGG_FUNCTION );
memset(&w, 0, sizeof(w));
w.xExprCallback = exprSrcCount;
w.xSelectCallback = 0;
w.xSelectCallback = sqlite3SelectWalkNoop;
w.u.pSrcCount = &cnt;
cnt.pSrc = pSrcList;
cnt.nThis = 0;
@ -5518,6 +5623,11 @@ void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
/*
** Mark all temporary registers as being unavailable for reuse.
**
** Always invoke this procedure after coding a subroutine or co-routine
** that might be invoked from other parts of the code, to ensure that
** the sub/co-routine does not use registers in common with the code that
** invokes the sub/co-routine.
*/
void sqlite3ClearTempRegCache(Parse *pParse){
pParse->nTempReg = 0;

View File

@ -478,13 +478,13 @@ static Expr *exprTableRegister(
if( iCol>=0 && iCol!=pTab->iPKey ){
pCol = &pTab->aCol[iCol];
pExpr->iTable = regBase + iCol + 1;
pExpr->affinity = pCol->affinity;
pExpr->affExpr = pCol->affinity;
zColl = pCol->zColl;
if( zColl==0 ) zColl = db->pDfltColl->zName;
pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
}else{
pExpr->iTable = regBase;
pExpr->affinity = SQLITE_AFF_INTEGER;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
}
return pExpr;
@ -1287,7 +1287,7 @@ static Trigger *fkActionTrigger(
tFrom.n = nFrom;
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affinity = OE_Abort;
pRaise->affExpr = OE_Abort;
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
@ -1332,6 +1332,7 @@ static Trigger *fkActionTrigger(
return 0;
}
assert( pStep!=0 );
assert( pTrigger!=0 );
switch( action ){
case OE_Restrict:

View File

@ -203,6 +203,8 @@ static void instrFunc(
int N = 1;
int isText;
unsigned char firstChar;
sqlite3_value *pC1 = 0;
sqlite3_value *pC2 = 0;
UNUSED_PARAMETER(argc);
typeHaystack = sqlite3_value_type(argv[0]);
@ -215,12 +217,22 @@ static void instrFunc(
zHaystack = sqlite3_value_blob(argv[0]);
zNeedle = sqlite3_value_blob(argv[1]);
isText = 0;
}else{
}else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){
zHaystack = sqlite3_value_text(argv[0]);
zNeedle = sqlite3_value_text(argv[1]);
isText = 1;
}else{
pC1 = sqlite3_value_dup(argv[0]);
zHaystack = sqlite3_value_text(pC1);
if( zHaystack==0 ) goto endInstrOOM;
nHaystack = sqlite3_value_bytes(pC1);
pC2 = sqlite3_value_dup(argv[1]);
zNeedle = sqlite3_value_text(pC2);
if( zNeedle==0 ) goto endInstrOOM;
nNeedle = sqlite3_value_bytes(pC2);
isText = 1;
}
if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM;
firstChar = zNeedle[0];
while( nNeedle<=nHaystack
&& (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0)
@ -234,6 +246,13 @@ static void instrFunc(
if( nNeedle>nHaystack ) N = 0;
}
sqlite3_result_int(context, N);
endInstr:
sqlite3_value_free(pC1);
sqlite3_value_free(pC2);
return;
endInstrOOM:
sqlite3_result_error_nomem(context);
goto endInstr;
}
/*
@ -1999,9 +2018,6 @@ void sqlite3RegisterBuiltinFunctions(void){
sqlite3AlterFunctions();
#endif
sqlite3WindowFunctions();
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
sqlite3AnalyzeFunctions();
#endif
sqlite3RegisterDateTimeFunctions();
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));

View File

@ -214,6 +214,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@ -260,6 +261,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
};
/*
@ -269,14 +271,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
*/
FuncDefHash sqlite3BuiltinFunctions;
/*
** Constant tokens for values 0 and 1.
*/
const Token sqlite3IntTokens[] = {
{ "0", 1 },
{ "1", 1 }
};
#ifdef VDBE_PROFILE
/*
** The following performance counter can be used in place of

View File

@ -88,18 +88,19 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
}
for(n=0; n<pIdx->nColumn; n++){
i16 x = pIdx->aiColumn[n];
char aff;
if( x>=0 ){
pIdx->zColAff[n] = pTab->aCol[x].affinity;
aff = pTab->aCol[x].affinity;
}else if( x==XN_ROWID ){
pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
aff = SQLITE_AFF_INTEGER;
}else{
char aff;
assert( x==XN_EXPR );
assert( pIdx->aColExpr!=0 );
aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
if( aff==0 ) aff = SQLITE_AFF_BLOB;
pIdx->zColAff[n] = aff;
}
if( aff<SQLITE_AFF_BLOB ) aff = SQLITE_AFF_BLOB;
if( aff>SQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC;
pIdx->zColAff[n] = aff;
}
pIdx->zColAff[n] = 0;
}
@ -139,11 +140,12 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}
for(i=0; i<pTab->nCol; i++){
assert( pTab->aCol[i].affinity!=0 );
zColAff[i] = pTab->aCol[i].affinity;
}
do{
zColAff[i--] = 0;
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
}while( i>=0 && zColAff[i]<=SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
assert( zColAff!=0 );
@ -832,6 +834,9 @@ void sqlite3Insert(
pTab->zName);
goto insert_cleanup;
}
if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
goto insert_cleanup;
}
pTabList->a[0].iCursor = iDataCur;
pUpsert->pUpsertSrc = pTabList;
pUpsert->regData = regData;

View File

@ -461,7 +461,13 @@ static const sqlite3_api_routines sqlite3Apis = {
#endif
/* Version 3.28.0 and later */
sqlite3_stmt_isexplain,
sqlite3_value_frombind
sqlite3_value_frombind,
/* Version 3.30.0 and later */
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_drop_modules,
#else
0,
#endif
};
/*

View File

@ -836,6 +836,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
} aFlagOp[] = {
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
{ SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView },
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
{ SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
@ -1235,11 +1236,8 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
Module *pMod = (Module *)sqliteHashData(i);
if( pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
sqlite3VtabEponymousTableClear(db, pMod);
sqlite3DbFree(db, pMod);
sqlite3VtabModuleUnref(db, pMod);
}
sqlite3HashClear(&db->aModule);
#endif
@ -1720,7 +1718,8 @@ int sqlite3CreateFunc(
}
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
extraFlags = enc & SQLITE_DETERMINISTIC;
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|SQLITE_SUBTYPE);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
#ifndef SQLITE_OMIT_UTF16
@ -1783,6 +1782,7 @@ int sqlite3CreateFunc(
p->u.pDestructor = pDestructor;
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
testcase( p->funcFlags & SQLITE_DETERMINISTIC );
testcase( p->funcFlags & SQLITE_DIRECTONLY );
p->xSFunc = xSFunc ? xSFunc : xStep;
p->xFinalize = xFinal;
p->xValue = xValue;
@ -3075,6 +3075,7 @@ static int openDatabase(
db->nMaxSorterMmap = 0x7FFFFFFF;
db->flags |= SQLITE_ShortColNames
| SQLITE_EnableTrigger
| SQLITE_EnableView
| SQLITE_CacheSpill
/* The SQLITE_DQS compile-time option determines the default settings
@ -3831,12 +3832,33 @@ int sqlite3_test_control(int op, ...){
break;
}
/*
** Reset the PRNG back to its uninitialized state. The next call
** to sqlite3_randomness() will reseed the PRNG using a single call
** to the xRandomness method of the default VFS.
/* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db);
**
** Control the seed for the pseudo-random number generator (PRNG) that
** is built into SQLite. Cases:
**
** x!=0 && db!=0 Seed the PRNG to the current value of the
** schema cookie in the main database for db, or
** x if the schema cookie is zero. This case
** is convenient to use with database fuzzers
** as it allows the fuzzer some control over the
** the PRNG seed.
**
** x!=0 && db==0 Seed the PRNG to the value of x.
**
** x==0 && db==0 Revert to default behavior of using the
** xRandomness method on the primary VFS.
**
** This test-control also resets the PRNG so that the new seed will
** be used for the next call to sqlite3_randomness().
*/
case SQLITE_TESTCTRL_PRNG_RESET: {
case SQLITE_TESTCTRL_PRNG_SEED: {
int x = va_arg(ap, int);
int y;
sqlite3 *db = va_arg(ap, sqlite3*);
assert( db==0 || db->aDb[0].pSchema!=0 );
if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; }
sqlite3Config.iPrngSeed = x;
sqlite3_randomness(0,0);
break;
}
@ -4049,6 +4071,17 @@ int sqlite3_test_control(int op, ...){
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int);
**
** Set or clear a flag that causes SQLite to verify that type, name,
** and tbl_name fields of the sqlite_master table. This is normally
** on, but it is sometimes useful to turn it off for testing.
*/
case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: {
sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int);
break;
}
/* Set the threshold at which OP_Once counters reset back to zero.
** By default this is 0x7ffffffe (over 2 billion), but that value is
** too big to test in a reasonable amount of time, so this control is

View File

@ -96,14 +96,9 @@ static int memjrnlRead(
int iChunkOffset;
FileChunk *pChunk;
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
}
#endif
assert( (iAmt+iOfst)<=p->endpoint.iOffset );
assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;

View File

@ -67,4 +67,5 @@
#define MUTEX_LOGIC(X)
#else
#define MUTEX_LOGIC(X) X
int sqlite3_mutex_held(sqlite3_mutex*);
#endif /* defined(SQLITE_MUTEX_OMIT) */

View File

@ -258,7 +258,15 @@ void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
return pVfs->xRandomness(pVfs, nByte, zBufOut);
if( sqlite3Config.iPrngSeed ){
memset(zBufOut, 0, nByte);
if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
return SQLITE_OK;
}else{
return pVfs->xRandomness(pVfs, nByte, zBufOut);
}
}
int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
return pVfs->xSleep(pVfs, nMicro);

View File

@ -105,13 +105,29 @@
# include <sys/param.h>
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
&& (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
# define HAVE_GETHOSTUUID 1
# else
# warning "gethostuuid() is disabled."
/*
** Try to determine if gethostuuid() is available based on standard
** macros. This might sometimes compute the wrong value for some
** obscure platforms. For those cases, simply compile with one of
** the following:
**
** -DHAVE_GETHOSTUUID=0
** -DHAVE_GETHOSTUUID=1
**
** None if this matters except when building on Apple products with
** -DSQLITE_ENABLE_LOCKING_STYLE.
*/
#ifndef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 0
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
&& (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
# undef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 1
# else
# warning "gethostuuid() is disabled."
# endif
# endif
#endif
@ -521,13 +537,14 @@ static struct unix_syscall {
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
# ifdef __ANDROID__
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
# else
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent)
# endif
#else
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
}; /* End of the overrideable system calls */
@ -5769,6 +5786,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
UnixUnusedFd **pp;
assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
sqlite3_mutex_enter(pInode->pLockMutex);
flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
@ -5822,7 +5840,7 @@ static int getFileMode(
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** original filename is unavailable. But 8_3_NAMES is only used for
** FAT filesystems and permissions do not matter there, so just use
** the default permissions.
** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero.
*/
static int findCreateFileMode(
const char *zPath, /* Path of file (possibly) being created */
@ -6057,11 +6075,19 @@ static int unixOpen(
goto open_finished;
}
/* If this process is running as root and if creating a new rollback
** journal or WAL file, set the ownership of the journal or WAL to be
** the same as the original database.
/* The owner of the rollback journal or WAL file should always be the
** same as the owner of the database file. Try to ensure that this is
** the case. The chown() system call will be a no-op if the current
** process lacks root privileges, be we should at least try. Without
** this step, if a root process opens a database file, it can leave
** behinds a journal/WAL that is owned by root and hence make the
** database inaccessible to unprivileged processes.
**
** If openMode==0, then that means uid and gid are not set correctly
** (probably because SQLite is configured to use 8+3 filename mode) and
** in that case we do not want to attempt the chown().
*/
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
robustFchown(fd, uid, gid);
}
}
@ -6072,7 +6098,8 @@ static int unixOpen(
if( p->pPreallocatedUnused ){
p->pPreallocatedUnused->fd = fd;
p->pPreallocatedUnused->flags = flags;
p->pPreallocatedUnused->flags =
flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
}
if( isDelete ){
@ -6918,7 +6945,7 @@ int sqlite3_hostid_num = 0;
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
#ifdef HAVE_GETHOSTUUID
#if HAVE_GETHOSTUUID
/* Not always defined in the headers as it ought to be */
extern int gethostuuid(uuid_t id, const struct timespec *wait);
#endif
@ -6929,7 +6956,7 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait);
static int proxyGetHostID(unsigned char *pHostID, int *pError){
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
memset(pHostID, 0, PROXY_HOSTIDLEN);
#ifdef HAVE_GETHOSTUUID
#if HAVE_GETHOSTUUID
{
struct timespec timeout = {1, 0}; /* 1 sec timeout */
if( gethostuuid(pHostID, &timeout) ){
@ -7603,7 +7630,7 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
assert( 0 ); /* The call assures that only valid opcodes are sent */
}
}
/*NOTREACHED*/
/*NOTREACHED*/ assert(0);
return SQLITE_ERROR;
}

View File

@ -4215,6 +4215,7 @@ static int winShmMap(
rc = winOpenSharedMemory(pDbFd);
if( rc!=SQLITE_OK ) return rc;
pShm = pDbFd->pShm;
assert( pShm!=0 );
}
pShmNode = pShm->pShmNode;
@ -4517,6 +4518,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
}
}
if( pFd->mmapSize >= iOff+nAmt ){
assert( pFd->pMapRegion!=0 );
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}

View File

@ -211,6 +211,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
NULLS FIRST LAST
%ifdef SQLITE_OMIT_COMPOUND_SELECT
EXCEPT INTERSECT UNION
%endif SQLITE_OMIT_COMPOUND_SELECT
@ -458,6 +459,7 @@ cmd ::= select(X). {
** SQLITE_LIMIT_COMPOUND_SELECT.
*/
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
assert( p!=0 );
if( p->pPrior ){
Select *pNext = 0, *pLoop;
int mxSelect, cnt = 0;
@ -780,13 +782,13 @@ using_opt(U) ::= . {U = 0;}
orderby_opt(A) ::= . {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). {
sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z) nulls(X). {
A = sqlite3ExprListAppend(pParse,A,Y);
sqlite3ExprListSetSortOrder(A,Z);
sqlite3ExprListSetSortOrder(A,Z,X);
}
sortlist(A) ::= expr(Y) sortorder(Z). {
sortlist(A) ::= expr(Y) sortorder(Z) nulls(X). {
A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/
sqlite3ExprListSetSortOrder(A,Z);
sqlite3ExprListSetSortOrder(A,Z,X);
}
%type sortorder {int}
@ -795,6 +797,11 @@ sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;}
%type nulls {int}
nulls(A) ::= NULLS FIRST. {A = SQLITE_SO_ASC;}
nulls(A) ::= NULLS LAST. {A = SQLITE_SO_DESC;}
nulls(A) ::= . {A = SQLITE_SO_UNDEFINED;}
%type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
groupby_opt(A) ::= . {A = 0;}
@ -948,7 +955,7 @@ idlist(A) ::= nm(Y).
if( p ){
/* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
p->affinity = 0;
p->affExpr = 0;
p->flags = EP_Leaf;
p->iAgg = -1;
p->pLeft = p->pRight = 0;
@ -1044,11 +1051,11 @@ expr(A) ::= id(X) LP STAR RP. {
}
%ifndef SQLITE_OMIT_WINDOWFUNC
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP over_clause(Z). {
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, Y, &X, D);
sqlite3WindowAttach(pParse, A, Z);
}
expr(A) ::= id(X) LP STAR RP over_clause(Z). {
expr(A) ::= id(X) LP STAR RP filter_over(Z). {
A = sqlite3ExprFunction(pParse, 0, &X, 0);
sqlite3WindowAttach(pParse, A, Z);
}
@ -1174,34 +1181,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
** regardless of the value of expr1.
*/
sqlite3ExprUnmapAndDelete(pParse, A);
A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
}else if( Y->nExpr==1 ){
/* Expressions of the form:
**
** expr1 IN (?1)
** expr1 NOT IN (?2)
**
** with exactly one value on the RHS can be simplified to something
** like this:
**
** expr1 == ?1
** expr1 <> ?2
**
** But, the RHS of the == or <> is marked with the EP_Generic flag
** so that it may not contribute to the computation of comparison
** affinity or the collating sequence to use for comparison. Otherwise,
** the semantics would be subtly different from IN or NOT IN.
*/
Expr *pRHS = Y->a[0].pExpr;
Y->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, Y);
/* pRHS cannot be NULL because a malloc error would have been detected
** before now and control would have never reached this point */
if( ALWAYS(pRHS) ){
pRHS->flags &= ~EP_Collate;
pRHS->flags |= EP_Generic;
}
A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS);
A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0");
}else{
A = sqlite3PExpr(pParse, TK_IN, A, 0);
if( A ){
@ -1507,13 +1487,13 @@ trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E).
expr(A) ::= RAISE LP IGNORE RP. {
A = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
if( A ){
A->affinity = OE_Ignore;
A->affExpr = OE_Ignore;
}
}
expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. {
A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1);
if( A ) {
A->affinity = (char)T;
A->affExpr = (char)T;
}
}
%endif !SQLITE_OMIT_TRIGGER
@ -1657,8 +1637,14 @@ windowdefn(A) ::= nm(X) AS LP window(Y) RP. {
%type part_opt {ExprList*}
%destructor part_opt {sqlite3ExprListDelete(pParse->db, $$);}
%type filter_opt {Expr*}
%destructor filter_opt {sqlite3ExprDelete(pParse->db, $$);}
%type filter_clause {Expr*}
%destructor filter_clause {sqlite3ExprDelete(pParse->db, $$);}
%type over_clause {Window*}
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}
%type filter_over {Window*}
%destructor filter_over {sqlite3WindowDelete(pParse->db, $$);}
%type range_or_rows {int}
@ -1724,25 +1710,35 @@ frame_exclude(A) ::= GROUP|TIES(X). {A = @X; /*A-overwrites-X*/}
%destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);}
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }
%type over_clause {Window*}
%destructor over_clause {sqlite3WindowDelete(pParse->db, $$);}
over_clause(A) ::= filter_opt(W) OVER LP window(Z) RP. {
A = Z;
assert( A!=0 );
A->pFilter = W;
filter_over(A) ::= filter_clause(F) over_clause(O). {
O->pFilter = F;
A = O;
}
over_clause(A) ::= filter_opt(W) OVER nm(Z). {
filter_over(A) ::= over_clause(O). {
A = O;
}
filter_over(A) ::= filter_clause(F). {
A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( A ){
A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n);
A->pFilter = W;
A->eFrmType = TK_FILTER;
A->pFilter = F;
}else{
sqlite3ExprDelete(pParse->db, W);
sqlite3ExprDelete(pParse->db, F);
}
}
filter_opt(A) ::= . { A = 0; }
filter_opt(A) ::= FILTER LP WHERE expr(X) RP. { A = X; }
over_clause(A) ::= OVER LP window(Z) RP. {
A = Z;
assert( A!=0 );
}
over_clause(A) ::= OVER nm(Z). {
A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( A ){
A->zName = sqlite3DbStrNDup(pParse->db, Z.z, Z.n);
}
}
filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; }
%endif /* SQLITE_OMIT_WINDOWFUNC */
/*
@ -1750,12 +1746,12 @@ filter_opt(A) ::= FILTER LP WHERE expr(X) RP. { A = X; }
** are synthesized and do not actually appear in the grammar:
*/
%token
TRUEFALSE /* True or false keyword */
ISNOT /* Combination of IS and NOT */
FUNCTION /* A function invocation */
COLUMN /* Reference to a table column */
AGG_FUNCTION /* An aggregate function */
AGG_COLUMN /* An aggregated column */
TRUEFALSE /* True or false keyword */
ISNOT /* Combination of IS and NOT */
FUNCTION /* A function invocation */
UMINUS /* Unary minus */
UPLUS /* Unary plus */
TRUTH /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */

View File

@ -262,6 +262,7 @@ int sqlite3PcacheInitialize(void){
** built-in default page cache is used instead of the application defined
** page cache. */
sqlite3PCacheSetDefault();
assert( sqlite3GlobalConfig.pcache2.xInit!=0 );
}
return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
}

View File

@ -424,6 +424,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
assert( pCache->pFree!=0 );
p = pCache->pFree;
pCache->pFree = p->pNext;
p->pNext = 0;

View File

@ -1172,6 +1172,15 @@ void sqlite3Pragma(
Index *pIdx;
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx==0 ){
/* If there is no index named zRight, check to see if there is a
** WITHOUT ROWID table named zRight, and if there is, show the
** structure of the PRIMARY KEY index for that table. */
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab && !HasRowid(pTab) ){
pIdx = sqlite3PrimaryKeyIndex(pTab);
}
}
if( pIdx ){
int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
int i;
@ -1251,7 +1260,7 @@ void sqlite3Pragma(
}
break;
#ifdef SQLITE_INTROSPECTION_PRAGMAS
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
case PragTyp_FUNCTION_LIST: {
int i;
HashElem *j;

View File

@ -311,7 +311,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_FullFSync },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
@ -435,7 +435,7 @@ static const PragmaName aPragmaName[] = {
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if !defined(SQLITE_OMIT_VIRTUALTABLE)
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
{/* zName: */ "module_list",
/* ePragTyp: */ PragTyp_MODULE_LIST,
/* ePragFlg: */ PragFlg_Result0,
@ -470,7 +470,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_ParserTrace },
#endif
#endif
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
{/* zName: */ "pragma_list",
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
/* ePragFlg: */ PragFlg_Result0,
@ -668,4 +668,4 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
/* Number of pragmas: 62 on by default, 81 total. */
/* Number of pragmas: 65 on by default, 81 total. */

View File

@ -64,9 +64,11 @@ int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
**
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. 0 for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[0] = type of object: "table", "index", "trigger", or "view".
** argv[1] = name of thing being created
** argv[2] = associated table if an index or trigger
** argv[3] = root page number for table or index. 0 for trigger or view.
** argv[4] = SQL text for the CREATE statement.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
@ -74,21 +76,21 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( argc==3 );
assert( argc==5 );
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
DbClearProperty(db, iDb, DB_Empty);
pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
corruptSchema(pData, argv[1], 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
}else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
if( argv[3]==0 ){
corruptSchema(pData, argv[1], 0);
}else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
@ -101,9 +103,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = sqlite3Atoi(argv[1]);
db->init.newTnum = sqlite3Atoi(argv[3]);
db->init.orphanTrigger = 0;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
db->init.azInit = argv;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@ -112,17 +115,17 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( db->init.orphanTrigger ){
assert( iDb==1 );
}else{
pData->rc = rc;
if( rc > pData->rc ) pData->rc = rc;
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
corruptSchema(pData, argv[0], sqlite3_errmsg(db));
corruptSchema(pData, argv[1], sqlite3_errmsg(db));
}
}
}
sqlite3_finalize(pStmt);
}else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
corruptSchema(pData, argv[0], 0);
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
corruptSchema(pData, argv[1], 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@ -131,13 +134,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0
|| sqlite3GetInt32(argv[1],&pIndex->tnum)==0
|| sqlite3GetInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
|| sqlite3IndexHasDuplicateRootPage(pIndex)
){
corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
}
}
return 0;
@ -158,7 +161,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
int size;
#endif
Db *pDb;
char const *azArg[4];
char const *azArg[6];
int meta[5];
InitData initData;
const char *zMasterName;
@ -177,18 +180,20 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** table name will be inserted automatically by the parser so we can just
** use the abbreviation "x" here. The parser will also automatically tag
** the schema table as read-only. */
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
azArg[1] = "1";
azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
azArg[0] = "table";
azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
azArg[2] = azArg[1];
azArg[3] = "1";
azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
"rootpage int,sql text)";
azArg[3] = 0;
azArg[5] = 0;
initData.db = db;
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
initData.nInitRow = 0;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
goto error_out;
@ -314,7 +319,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
"SELECT*FROM\"%w\".%s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
@ -635,7 +640,10 @@ static int sqlite3Prepare(
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
/* Justification for the ALWAYS(): The only way for rc to be SQLITE_OK and
** sParse.pVdbe to be NULL is if the input SQL is an empty string, but in
** that case, sParse.explain will be false. */
if( sParse.explain && rc==SQLITE_OK && ALWAYS(sParse.pVdbe) ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"id", "parent", "notused", "detail"
@ -660,8 +668,8 @@ static int sqlite3Prepare(
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(sParse.pVdbe);
if( rc!=SQLITE_OK || db->mallocFailed ){
if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
assert(!(*ppStmt));
}else{
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;

View File

@ -96,6 +96,13 @@ static void resolveAlias(
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags |= EP_MemToken;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
if( pExpr->y.pWin!=0 ){
pExpr->y.pWin->pOwner = pExpr;
}else{
assert( db->mallocFailed );
}
}
sqlite3DbFree(db, pDup);
}
ExprSetProperty(pExpr, EP_Alias);
@ -381,7 +388,7 @@ static int lookupName(
{
#ifndef SQLITE_OMIT_TRIGGER
if( iCol<0 ){
pExpr->affinity = SQLITE_AFF_INTEGER;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}else if( pExpr->iTable==0 ){
testcase( iCol==31 );
testcase( iCol==32 );
@ -413,7 +420,7 @@ static int lookupName(
){
cnt = 1;
pExpr->iColumn = -1;
pExpr->affinity = SQLITE_AFF_INTEGER;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
/*
@ -689,7 +696,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn = -1;
pExpr->affinity = SQLITE_AFF_INTEGER;
pExpr->affExpr = SQLITE_AFF_INTEGER;
break;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
@ -749,7 +756,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
#endif
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
@ -821,6 +830,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** SQL is being compiled using sqlite3NestedParse() */
no_such_func = 1;
pDef = 0;
}else
if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
&& ExprHasProperty(pExpr, EP_Indirect)
&& !IN_RENAME_OBJECT
){
/* Functions tagged with SQLITE_DIRECTONLY may not be used
** inside of triggers and views */
sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
pDef->zName);
}
}
@ -830,18 +848,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
if( pDef && pDef->xValue==0 && pWin ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
pNC->nErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
|| (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
|| (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0)
){
const char *zType;
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
zType = "window";
}else{
zType = "aggregate";
@ -869,34 +887,44 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
nId, zId);
pNC->nErr++;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ErrorMsg(pParse,
"FILTER may not be used with non-aggregate %.*s()",
nId, zId
);
pNC->nErr++;
}
#endif
if( is_agg ){
/* Window functions may not be arguments of aggregate functions.
** Or arguments of other window functions. But aggregate functions
** may be arguments for window functions. */
#ifndef SQLITE_OMIT_WINDOWFUNC
pNC->ncFlags &= ~(NC_AllowWin | (!pExpr->y.pWin ? NC_AllowAgg : 0));
pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0));
#else
pNC->ncFlags &= ~NC_AllowAgg;
#endif
}
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( ExprHasProperty(pExpr, EP_WinFunc) ){
is_agg = 1;
}
#endif
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pExpr->y.pWin ){
if( pWin ){
Select *pSel = pNC->pWinSelect;
assert( pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
}
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
if( 0==pSel->pWin
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
pExpr->y.pWin->pNextWin = pSel->pWin;
pSel->pWin = pExpr->y.pWin;
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pWin, pDef);
}
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pWin->pFilter);
sqlite3WindowLink(pSel, pWin);
pNC->ncFlags |= NC_HasWin;
}else
#endif /* SQLITE_OMIT_WINDOWFUNC */
@ -904,12 +932,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
NameContext *pNC2 = pNC;
pExpr->op = TK_AGG_FUNCTION;
pExpr->op2 = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
}
#endif
while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
pExpr->op2++;
pNC2 = pNC2->pNext;
}
assert( pDef!=0 );
if( pNC2 ){
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
@ -947,7 +980,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
case TK_IS:
case TK_ISNOT: {
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight);
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
@ -1158,7 +1191,7 @@ static int resolveCompoundOrderBy(
int iCol = -1;
Expr *pE, *pDup;
if( pItem->done ) continue;
pE = sqlite3ExprSkipCollate(pItem->pExpr);
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@ -1252,7 +1285,7 @@ int sqlite3ResolveOrderGroupBy(
ExprList *pEList;
struct ExprList_item *pItem;
if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0;
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
return 1;
@ -1274,17 +1307,13 @@ int sqlite3ResolveOrderGroupBy(
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Walker callback for resolveRemoveWindows().
** Walker callback for windowRemoveExprFromSelect().
*/
static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
UNUSED_PARAMETER(pWalker);
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window **pp;
for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
if( *pp==pExpr->y.pWin ){
*pp = (*pp)->pNextWin;
break;
}
}
Window *pWin = pExpr->y.pWin;
sqlite3WindowUnlinkFromSelect(pWin);
}
return WRC_Continue;
}
@ -1293,16 +1322,18 @@ static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
** Remove any Window objects owned by the expression pExpr from the
** Select.pWin list of Select object pSelect.
*/
static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.xExprCallback = resolveRemoveWindowsCb;
sWalker.u.pSelect = pSelect;
sqlite3WalkExpr(&sWalker, pExpr);
static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){
if( pSelect->pWin ){
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.xExprCallback = resolveRemoveWindowsCb;
sWalker.u.pSelect = pSelect;
sqlite3WalkExpr(&sWalker, pExpr);
}
}
#else
# define resolveRemoveWindows(x,y)
#endif
# define windowRemoveExprFromSelect(a, b)
#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
@ -1339,7 +1370,7 @@ static int resolveOrderGroupBy(
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
Expr *pE2 = sqlite3ExprSkipCollate(pE);
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
if( zType[0]!='G' ){
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
if( iCol>0 ){
@ -1373,7 +1404,7 @@ static int resolveOrderGroupBy(
/* Since this expresion is being changed into a reference
** to an identical expression in the result set, remove all Window
** objects belonging to the expression from the Select.pWin list. */
resolveRemoveWindows(pSelect, pE);
windowRemoveExprFromSelect(pSelect, pE);
pItem->u.x.iOrderByCol = j+1;
}
}

View File

@ -100,6 +100,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlite3WindowListDelete(db, p->pWinDefn);
}
assert( p->pWin==0 );
#endif
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
@ -663,7 +664,7 @@ static void pushOntoSorter(
if( pParse->db->mallocFailed ) return;
pOp->p2 = nKey + nData;
pKI = pOp->p4.pKeyInfo;
memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
testcase( pKI->nAllField > pKI->nKeyField+2 );
pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
@ -1274,7 +1275,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
p->aSortOrder = (u8*)&p->aColl[N+X];
p->aSortFlags = (u8*)&p->aColl[N+X];
p->nKeyField = (u16)N;
p->nAllField = (u16)(N+X);
p->enc = ENC(db);
@ -1351,7 +1352,7 @@ KeyInfo *sqlite3KeyInfoFromExprList(
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
pInfo->aSortFlags[i-iStart] = pItem->sortFlags;
}
}
return pInfo;
@ -1643,8 +1644,6 @@ static const char *columnTypeImpl(
assert( pExpr!=0 );
assert( pNC->pSrcList!=0 );
assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
** are processed */
switch( pExpr->op ){
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
@ -1961,12 +1960,11 @@ int sqlite3ColumnsFromExprList(
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
while( pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
assert( pColExpr->op!=TK_AGG_COLUMN );
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
@ -2034,7 +2032,8 @@ int sqlite3ColumnsFromExprList(
void sqlite3SelectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
Table *pTab, /* Add column type information to this table */
Select *pSelect /* SELECT used to determine types and collations */
Select *pSelect, /* SELECT used to determine types and collations */
char aff /* Default affinity for columns */
){
sqlite3 *db = pParse->db;
NameContext sNC;
@ -2067,7 +2066,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
pCol->colFlags |= COLFLAG_HASTYPE;
}
}
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
@ -2080,7 +2079,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
*/
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
Table *pTab;
sqlite3 *db = pParse->db;
u64 savedFlags;
@ -2100,7 +2099,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@ -2254,7 +2253,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
}
assert( sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags;
}
}
@ -2965,11 +2964,14 @@ static int generateOutputSubroutine(
/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell and break out
** of the scan loop.
** of the scan loop. Note that the select might return multiple columns
** if it is the RHS of a row-value IN operator.
*/
case SRT_Mem: {
assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
if( pParse->nErr==0 ){
testcase( pIn->nSdst>1 );
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
}
/* The LIMIT clause will jump out of the loop for us */
break;
}
@ -3226,7 +3228,7 @@ static int multiSelectOrderBy(
assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
for(i=0; i<nExpr; i++){
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
pKeyDup->aSortOrder[i] = 0;
pKeyDup->aSortFlags[i] = 0;
}
}
}
@ -3476,6 +3478,18 @@ static Expr *substExpr(
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
if( pExpr ){
if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
(pColl ? pColl->zName : "BINARY")
);
}
ExprClearProperty(pExpr, EP_Collate);
}
}
}
}else{
@ -3489,6 +3503,14 @@ static Expr *substExpr(
}else{
substExprList(pSubst, pExpr->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window *pWin = pExpr->y.pWin;
pWin->pFilter = substExpr(pSubst, pWin->pFilter);
substExprList(pSubst, pWin->pPartition);
substExprList(pSubst, pWin->pOrderBy);
}
#endif
}
return pExpr;
}
@ -3949,6 +3971,7 @@ static int flattenSubquery(
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
@ -4399,24 +4422,27 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
const char *zFunc; /* Name of aggregate function pFunc */
ExprList *pOrderBy;
u8 sortOrder;
u8 sortFlags;
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
if( pEList==0 || pEList->nExpr!=1 ) return eRet;
assert( !IsWindowFunc(pFunc) );
if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
return eRet;
}
zFunc = pFunc->u.zToken;
if( sqlite3StrICmp(zFunc, "min")==0 ){
eRet = WHERE_ORDERBY_MIN;
sortOrder = SQLITE_SO_ASC;
sortFlags = KEYINFO_ORDER_BIGNULL;
}else if( sqlite3StrICmp(zFunc, "max")==0 ){
eRet = WHERE_ORDERBY_MAX;
sortOrder = SQLITE_SO_DESC;
sortFlags = KEYINFO_ORDER_DESC;
}else{
return eRet;
}
*ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
assert( pOrderBy!=0 || db->mallocFailed );
if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags;
return eRet;
}
@ -4450,7 +4476,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( NEVER(pAggInfo->nFunc==0) ) return 0;
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
if( pExpr->flags&EP_Distinct ) return 0;
if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;
return pTab;
}
@ -4897,6 +4923,10 @@ static int selectExpander(Walker *pWalker, Select *p){
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
nCol = pTab->nCol;
pTab->nCol = -1;
@ -5190,7 +5220,8 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
if( pSel ){
while( pSel->pPrior ) pSel = pSel->pPrior;
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel,
SQLITE_AFF_NONE);
}
}
}
@ -5330,6 +5361,25 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
int regAgg;
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
assert( !IsWindowFunc(pF->pExpr) );
if( ExprHasProperty(pF->pExpr, EP_WinFunc) ){
Expr *pFilter = pF->pExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
){
if( regHit==0 ) regHit = ++pParse->nMem;
/* If this is the first row of the group (regAcc==0), clear the
** "magnet" register regHit so that the accumulator registers
** are populated if the FILTER clause jumps over the the
** invocation of min() or max() altogether. Or, if this is not
** the first row (regAcc==1), set the magnet register so that the
** accumulators are not populated unless the min()/max() is invoked and
** indicates that they should be. */
sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
}
addrNext = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL);
}
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
@ -5339,7 +5389,9 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
regAgg = 0;
}
if( pF->iDistinct>=0 ){
addrNext = sqlite3VdbeMakeLabel(pParse);
if( addrNext==0 ){
addrNext = sqlite3VdbeMakeLabel(pParse);
}
testcase( nArg==0 ); /* Error condition */
testcase( nArg>1 ); /* Also an error */
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
@ -5375,6 +5427,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
}
pAggInfo->directMode = 0;
if( addrHitTest ){
sqlite3VdbeJumpHere(v, addrHitTest);
@ -5420,7 +5473,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
Select *pS = pWalker->u.pSelect;
if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
sqlite3 *db = pWalker->pParse->db;
Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
if( pNew ){
Expr *pWhere = pS->pWhere;
SWAP(Expr, *pNew, *pExpr);
@ -5842,7 +5895,7 @@ int sqlite3Select(
** assume the column name is non-NULL and segfault. The use of an empty
** string for the fake column name seems safer.
*/
if( pItem->colUsed==0 ){
if( pItem->colUsed==0 && pItem->zName!=0 ){
sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
}
@ -5856,8 +5909,15 @@ int sqlite3Select(
** technically harmless for it to be generated multiple times. The
** following assert() will detect if something changes to cause
** the same subquery to be coded multiple times, as a signal to the
** developers to try to optimize the situation. */
assert( pItem->addrFillSub==0 );
** developers to try to optimize the situation.
**
** Update 2019-07-24:
** See ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311cec40.
** The dbsqlfuzz fuzzer found a case where the same subquery gets
** coded twice. So this assert() now becomes a testcase(). It should
** be very rare, though.
*/
testcase( pItem->addrFillSub!=0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@ -5931,7 +5991,7 @@ int sqlite3Select(
int retAddr;
struct SrcList_item *pPrior;
assert( pItem->addrFillSub==0 );
testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
@ -6171,23 +6231,35 @@ int sqlite3Select(
}
assert( 66==sqlite3LogEst(100) );
if( p->nSelectRow>66 ) p->nSelectRow = 66;
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY might use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
** variable. */
if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){
int ii;
/* The GROUP BY processing doesn't care whether rows are delivered in
** ASC or DESC order - only that each group is returned contiguously.
** So set the ASC/DESC flags in the GROUP BY to match those in the
** ORDER BY to maximize the chances of rows being delivered in an
** order that makes the ORDER BY redundant. */
for(ii=0; ii<pGroupBy->nExpr; ii++){
u8 sortFlags = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC;
pGroupBy->a[ii].sortFlags = sortFlags;
}
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
}
}
}else{
assert( 0==sqlite3LogEst(1) );
p->nSelectRow = 0;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY might use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
** variable. */
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
}
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(pParse);
@ -6222,9 +6294,16 @@ int sqlite3Select(
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
for(i=0; i<sAggInfo.nFunc; i++){
assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
Expr *pExpr = sAggInfo.aFunc[i].pExpr;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
sNC.ncFlags |= NC_InAggFunc;
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
assert( !IsWindowFunc(pExpr) );
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
}
#endif
sNC.ncFlags &= ~NC_InAggFunc;
}
sAggInfo.mxReg = pParse->nMem;
@ -6536,13 +6615,18 @@ int sqlite3Select(
{
int regAcc = 0; /* "populate accumulators" flag */
/* If there are accumulator registers but no min() or max() functions,
** allocate register regAcc. Register regAcc will contain 0 the first
** time the inner loop runs, and 1 thereafter. The code generated
** by updateAccumulator() only updates the accumulator registers if
** regAcc contains 0. */
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
** will contain 0 the first time the inner loop runs, and 1 thereafter.
** The code generated by updateAccumulator() uses this to ensure
** that the accumulator registers are (a) updated only once if
** there are no min() or max functions or (b) always updated for the
** first row visited by the aggregate, so that they are updated at
** least once even if the FILTER clause means the min() or max()
** function visits zero rows. */
if( sAggInfo.nAccumulator ){
for(i=0; i<sAggInfo.nFunc; i++){
if( ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_WinFunc) ) continue;
if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
}
if( i==sAggInfo.nFunc ){

View File

@ -1269,12 +1269,12 @@ static void editFunc(
}
sz = sqlite3_value_bytes(argv[0]);
if( bBin ){
x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
}else{
const char *z = (const char*)sqlite3_value_text(argv[0]);
/* Remember whether or not the value originally contained \r\n */
if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
}
fclose(f);
f = 0;
@ -1302,12 +1302,12 @@ static void editFunc(
fseek(f, 0, SEEK_END);
sz = ftell(f);
rewind(f);
p = sqlite3_malloc64( sz+(bBin==0) );
p = sqlite3_malloc64( sz+1 );
if( p==0 ){
sqlite3_result_error_nomem(context);
goto edit_func_end;
}
x = fread(p, 1, sz, f);
x = fread(p, 1, (size_t)sz, f);
fclose(f);
f = 0;
if( x!=sz ){
@ -1779,7 +1779,8 @@ static void eqp_render_level(ShellState *p, int iEqpId){
for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
pNext = eqp_next_row(p, iEqpId, pRow);
z = pRow->zText;
utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
pNext ? "|--" : "`--", z);
if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
eqp_render_level(p, pRow->iEqpId);
@ -1970,7 +1971,7 @@ static int shell_callback(
while( j>0 && IsSpace(z[j-1]) ){ j--; }
z[j] = 0;
if( strlen30(z)>=79 ){
for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */
for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
if( c==cEnd ){
cEnd = 0;
}else if( c=='"' || c=='\'' || c=='`' ){
@ -2549,7 +2550,7 @@ static int display_stats(
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
@ -3472,20 +3473,20 @@ static const char *(azHelp[]) = {
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add files or update files with changed mtime",
" -i, --insert Like -u but always add even if mtime unchanged",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Operate on archive FILE (default is current db)",
" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
" -C DIR, --directory DIR Change to directory DIR to read/extract files",
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
" .ar -tf archive.sar # List members of archive.sar",
" .ar -xvf archive.sar # Verbosely extract files from archive.sar",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
" http://sqlite.org/cli.html#sqlar_archive_support",
#endif
@ -3494,7 +3495,7 @@ static const char *(azHelp[]) = {
#endif
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
" --async Write to FILE without a journal and without fsync()",
" --async Write to FILE without journal and fsync()",
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
".cd DIRECTORY Change the working directory to DIRECTORY",
@ -3514,15 +3515,15 @@ static const char *(azHelp[]) = {
" Other Modes:",
#ifdef SQLITE_DEBUG
" test Show raw EXPLAIN QUERY PLAN output",
" trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
" trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
#endif
" trigger Like \"full\" but also show trigger bytecode",
".excel Display the output of next command in a spreadsheet",
".excel Display the output of next command in spreadsheet",
".exit ?CODE? Exit this program with return-code CODE",
".expert EXPERIMENTAL. Suggest indexes for specified queries",
".expert EXPERIMENTAL. Suggest indexes for queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen. It is still supported for legacy, however */
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
** is removed from the help screen. It is still supported for legacy, however */
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off",*/
".filectrl CMD ... Run various sqlite3_file_control() operations",
" Run \".filectrl\" with no arguments for details",
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
@ -3569,7 +3570,7 @@ static const char *(azHelp[]) = {
" --append Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
" --deserialize Load into memory useing sqlite3_deserialize()",
" --hexdb Load the output of \"dbtotxt\" as an in-memory database",
" --hexdb Load the output of \"dbtotxt\" as an in-memory db",
" --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
" --new Initialize FILE to an empty database",
@ -3582,7 +3583,7 @@ static const char *(azHelp[]) = {
" init Initialize the TEMP table that holds bindings",
" list List the current parameter bindings",
" set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
" PARAMETER should start with '$', ':', '@', or '?'",
" PARAMETER should start with one of: $ : @ ?",
" unset PARAMETER Remove PARAMETER from the binding table",
".print STRING... Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
@ -3597,6 +3598,11 @@ static const char *(azHelp[]) = {
".read FILE Read input from FILE",
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
".recover Recover as much data as possible from corrupt db.",
" --freelist-corrupt Assume the freelist is corrupt",
" --recovery-db NAME Store recovery metadata in database file NAME",
" --lost-and-found TABLE Alternative name for the lost-and-found table",
" --no-rowids Do not attempt to recover rowid values",
" that are not also INTEGER PRIMARY KEYs",
#endif
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
".save FILE Write in-memory database into FILE",
@ -3628,7 +3634,7 @@ static const char *(azHelp[]) = {
" Options:",
" --schema Also hash the sqlite_master table",
" --sha3-224 Use the sha3-224 algorithm",
" --sha3-256 Use the sha3-256 algorithm. This is the default.",
" --sha3-256 Use the sha3-256 algorithm (default)",
" --sha3-384 Use the sha3-384 algorithm",
" --sha3-512 Use the sha3-512 algorithm",
" Any other argument is a LIKE pattern for tables to hash",
@ -3662,6 +3668,10 @@ static const char *(azHelp[]) = {
" --row Trace each row (SQLITE_TRACE_ROW)",
" --close Trace connection close (SQLITE_TRACE_CLOSE)",
#endif /* SQLITE_OMIT_TRACE */
#ifdef SQLITE_DEBUG
".unmodule NAME ... Unregister virtual table modules",
" --allexcept Unregister everything except those named",
#endif
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
@ -3904,6 +3914,8 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
if( rc!=2 ) goto readHexDb_error;
if( n<0 ) goto readHexDb_error;
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
a = sqlite3_malloc( n ? n : 1 );
if( a==0 ){
utf8_printf(stderr, "Out of memory!\n");
@ -3988,6 +4000,23 @@ static void shellInt32(
}
}
/*
** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
** using "..." with internal double-quote characters doubled.
*/
static void shellIdQuote(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zName = (const char*)sqlite3_value_text(argv[0]);
UNUSED_PARAMETER(argc);
if( zName ){
char *z = sqlite3_mprintf("\"%w\"", zName);
sqlite3_result_text(context, z, -1, sqlite3_free);
}
}
/*
** Scalar function "shell_escape_crnl" used by the .recover command.
** The argument passed to this function is the output of built-in
@ -4164,6 +4193,8 @@ static void open_db(ShellState *p, int openFlags){
shellEscapeCrnl, 0, 0);
sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
shellInt32, 0, 0);
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
shellIdQuote, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
@ -5511,7 +5542,7 @@ void shellReset(
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
/*********************************************************************************
/******************************************************************************
** The ".archive" or ".ar" command.
*/
/*
@ -5709,7 +5740,8 @@ static int arParseCommand(
i = n;
}else{
if( iArg>=(nArg-1) ){
return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
return arErrorMsg(pAr, "option requires an argument: %c",
z[i]);
}
zArg = azArg[++iArg];
}
@ -6097,10 +6129,10 @@ end_ar_transaction:
** Implementation of ".ar" dot command.
*/
static int arDotCommand(
ShellState *pState, /* Current shell tool state */
int fromCmdLine, /* True if -A command-line option, not .ar cmd */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
ShellState *pState, /* Current shell tool state */
int fromCmdLine, /* True if -A command-line option, not .ar cmd */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
ArCommand cmd;
int rc;
@ -6200,7 +6232,7 @@ end_ar_command:
return rc;
}
/* End of the ".archive" or ".ar" command logic
**********************************************************************************/
*******************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
@ -6341,6 +6373,10 @@ static RecoverTable *recoverNewTable(
sqlite3_stmt *pStmt = 0;
rc = sqlite3_open("", &dbtmp);
if( rc==SQLITE_OK ){
sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
shellIdQuote, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
}
@ -6397,18 +6433,18 @@ static RecoverTable *recoverNewTable(
}
}
pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);
pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
pTab->nCol = nSqlCol;
if( bIntkey ){
pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
}else{
pTab->azlCol[0] = shellMPrintf(&rc, "");
}
i = 1;
shellPreparePrintf(dbtmp, &rc, &pStmt,
"SELECT %Q || group_concat(name, ', ') "
"SELECT %Q || group_concat(shell_idquote(name), ', ') "
" FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
"FROM pragma_table_info(%Q)",
bIntkey ? ", " : "", pTab->iPk,
@ -6522,7 +6558,7 @@ static RecoverTable *recoverOrphanTable(
pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
if( pTab ){
pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);
pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
pTab->nCol = nCol;
pTab->iPk = -2;
if( nCol>0 ){
@ -6571,6 +6607,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
RecoverTable *pOrphan = 0;
int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
int bRowids = 1; /* 0 if --no-rowids */
for(i=1; i<nArg; i++){
char *z = azArg[i];
int n;
@ -6586,13 +6623,13 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
i++;
zLostAndFound = azArg[i];
}else
if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
bRowids = 0;
}
else{
raw_printf(stderr, "unexpected option: %s\n", azArg[i]);
raw_printf(stderr, "options are:\n");
raw_printf(stderr, " --freelist-corrupt\n");
raw_printf(stderr, " --recovery-db DATABASE\n");
raw_printf(stderr, " --lost-and-found TABLE-NAME\n");
utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
showHelp(pState->out, azArg[0]);
return 1;
}
}
@ -6600,6 +6637,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
shellExecPrintf(pState->db, &rc,
/* Attach an in-memory database named 'recovery'. Create an indexed
** cache of the sqlite_dbptr virtual table. */
"PRAGMA writable_schema = on;"
"ATTACH %Q AS recovery;"
"DROP TABLE IF EXISTS recovery.dbptr;"
"DROP TABLE IF EXISTS recovery.freelist;"
@ -6630,6 +6668,21 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
);
}
/* If this is an auto-vacuum database, add all pointer-map pages to
** the freelist table. Do this regardless of whether or not
** --freelist-corrupt was specified. */
shellExec(pState->db, &rc,
"WITH ptrmap(pgno) AS ("
" SELECT 2 WHERE shell_int32("
" (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
" )"
" UNION ALL "
" SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
" FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
")"
"REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
);
shellExec(pState->db, &rc,
"CREATE TABLE recovery.dbptr("
" pgno, child, PRIMARY KEY(child, pgno)"
@ -6678,7 +6731,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
" )"
" SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
") "
"FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
"FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
"UPDATE recovery.map AS o SET intkey = ("
" SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
");"
@ -6703,6 +6756,11 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
** CREATE TABLE statements that extracted from the existing schema. */
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt = 0;
/* ".recover" might output content in an order which causes immediate
** foreign key constraints to be violated. So disable foreign-key
** constraint enforcement to prevent problems when running the output
** script. */
raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
raw_printf(pState->out, "BEGIN;\n");
raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
shellPrepare(pState->db, &rc,
@ -6733,8 +6791,12 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
shellPrepare(pState->db, &rc,
"SELECT pgno FROM recovery.map WHERE root=?", &pPages
);
shellPrepare(pState->db, &rc,
"SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"
"SELECT max(field), group_concat(shell_escape_crnl(quote"
"(case when (? AND field<0) then NULL else value end)"
"), ', ')"
", min(field) "
"FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
"GROUP BY cell", &pCells
);
@ -6753,6 +6815,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
int bNoop = 0;
RecoverTable *pTab;
assert( bIntkey==0 || bIntkey==1 );
pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
if( bNoop || rc ) continue;
if( pTab==0 ){
@ -6763,29 +6826,44 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
if( pTab==0 ) break;
}
if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){
if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
}
sqlite3_bind_int(pPages, 1, iRoot);
sqlite3_bind_int(pCells, 2, pTab->iPk);
if( bRowids==0 && pTab->iPk<0 ){
sqlite3_bind_int(pCells, 1, 1);
}else{
sqlite3_bind_int(pCells, 1, 0);
}
sqlite3_bind_int(pCells, 3, pTab->iPk);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
int iPgno = sqlite3_column_int(pPages, 0);
sqlite3_bind_int(pCells, 1, iPgno);
sqlite3_bind_int(pCells, 2, iPgno);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
int nField = sqlite3_column_int(pCells, 0);
int iMin = sqlite3_column_int(pCells, 2);
const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
RecoverTable *pTab2 = pTab;
if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
if( pOrphan==0 ){
pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
}
pTab2 = pOrphan;
if( pTab2==0 ) break;
}
nField = nField+1;
if( pTab==pOrphan ){
if( pTab2==pOrphan ){
raw_printf(pState->out,
"INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
pTab->zQuoted, iRoot, iPgno, nField,
bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]
pTab2->zQuoted, iRoot, iPgno, nField,
iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
);
}else{
raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
pTab->zQuoted, pTab->azlCol[nField], zVal
pTab2->zQuoted, pTab2->azlCol[nField], zVal
);
}
}
@ -6844,7 +6922,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int nArg = 0;
int n, c;
int rc = 0;
char *azArg[50];
char *azArg[52];
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( p->expert.pExpert ){
@ -6854,7 +6932,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Parse the input line into tokens.
*/
while( zLine[h] && nArg<ArraySize(azArg) ){
while( zLine[h] && nArg<ArraySize(azArg)-1 ){
while( IsSpace(zLine[h]) ){ h++; }
if( zLine[h]==0 ) break;
if( zLine[h]=='\'' || zLine[h]=='"' ){
@ -6875,6 +6953,7 @@ static int do_meta_command(char *zLine, ShellState *p){
resolve_backslashes(azArg[nArg-1]);
}
}
azArg[nArg] = 0;
/* Process the input line.
*/
@ -7090,6 +7169,7 @@ static int do_meta_command(char *zLine, ShellState *p){
} aDbConfig[] = {
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
{ "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
@ -7463,8 +7543,6 @@ static int do_meta_command(char *zLine, ShellState *p){
data.cMode = data.mode = MODE_Insert;
data.zDestTable = "sqlite_stat1";
shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
data.zDestTable = "sqlite_stat3";
shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);
data.zDestTable = "sqlite_stat4";
shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
raw_printf(p->out, "ANALYZE sqlite_master;\n");
@ -8083,12 +8161,8 @@ static int do_meta_command(char *zLine, ShellState *p){
** Clear all bind parameters by dropping the TEMP table that holds them.
*/
if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
int wrSchema = 0;
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
0, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
}else
/* .parameter list
@ -8401,7 +8475,7 @@ static int do_meta_command(char *zLine, ShellState *p){
zDiv = " UNION ALL ";
appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
if( sqlite3_stricmp(zDb, "main")!=0 ){
appendText(&sSelect, zDb, '"');
appendText(&sSelect, zDb, '\'');
}else{
appendText(&sSelect, "NULL", 0);
}
@ -8410,15 +8484,16 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&sSelect, " AS snum, ", 0);
appendText(&sSelect, zDb, '\'');
appendText(&sSelect, " AS sname FROM ", 0);
appendText(&sSelect, zDb, '"');
appendText(&sSelect, zDb, quoteChar(zDb));
appendText(&sSelect, ".sqlite_master", 0);
}
sqlite3_finalize(pStmt);
#ifdef SQLITE_INTROSPECTION_PRAGMAS
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
if( zName ){
appendText(&sSelect,
" UNION ALL SELECT shell_module_schema(name),"
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
0);
}
#endif
appendText(&sSelect, ") WHERE ", 0);
@ -8517,7 +8592,8 @@ static int do_meta_command(char *zLine, ShellState *p){
if( pSession->p==0 ) goto session_not_open;
out = fopen(azCmd[1], "wb");
if( out==0 ){
utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
azCmd[1]);
}else{
int szChng;
void *pChng;
@ -8838,8 +8914,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{
utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
azArg[i], azArg[0]);
raw_printf(stderr, "Should be one of: --schema"
" --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
showHelp(p->out, azArg[0]);
rc = 1;
goto meta_command_exit;
}
@ -8885,8 +8960,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else if( strcmp(zTab, "sqlite_stat1")==0 ){
appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
" ORDER BY tbl,idx;", 0);
}else if( strcmp(zTab, "sqlite_stat3")==0
|| strcmp(zTab, "sqlite_stat4")==0 ){
}else if( strcmp(zTab, "sqlite_stat4")==0 ){
appendText(&sQuery, "SELECT * FROM ", 0);
appendText(&sQuery, zTab, 0);
appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
@ -9118,25 +9192,26 @@ static int do_meta_command(char *zLine, ShellState *p){
int ctrlCode; /* Integer code for that option */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{ "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
{ "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
{ "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
#ifdef YYCOVERAGE
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" },
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
{ "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE"},
};
int testctrl = -1;
int iCtrl = -1;
@ -9217,6 +9292,27 @@ static int do_meta_command(char *zLine, ShellState *p){
}
break;
/* sqlite3_test_control(int, int, sqlite3*) */
case SQLITE_TESTCTRL_PRNG_SEED:
if( nArg==3 || nArg==4 ){
int ii = (int)integerValue(azArg[2]);
sqlite3 *db;
if( ii==0 && strcmp(azArg[2],"random")==0 ){
sqlite3_randomness(sizeof(ii),&ii);
printf("-- random seed: %d\n", ii);
}
if( nArg==3 ){
db = 0;
}else{
db = p->db;
/* Make sure the schema has been loaded */
sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
}
rc2 = sqlite3_test_control(testctrl, ii, db);
isOk = 3;
}
break;
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
@ -9258,7 +9354,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}
if( isOk==0 && iCtrl>=0 ){
utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
rc = 1;
}else if( isOk==1 ){
raw_printf(p->out, "%d\n", rc2);
@ -9336,6 +9432,31 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
#endif /* !defined(SQLITE_OMIT_TRACE) */
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
int ii;
int lenOpt;
char *zOpt;
if( nArg<2 ){
raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
zOpt = azArg[1];
if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
lenOpt = (int)strlen(zOpt);
if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
assert( azArg[nArg]==0 );
sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
}else{
for(ii=1; ii<nArg; ii++){
sqlite3_create_module(p->db, azArg[ii], 0, 0);
}
}
}else
#endif
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
if( nArg<2 ){
@ -9350,7 +9471,8 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
strlen30(azArg[3]));
if( rc ){
utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
rc = 1;

View File

@ -2093,6 +2093,17 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
** which case the view setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
@ -2265,7 +2276,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@ -3814,7 +3826,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** ^The specific value of WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
** </li>
** </ol>
**
@ -4849,6 +4861,12 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** perform additional optimizations on deterministic functions, so use
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
**
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
** flag, which if present prevents the function from being invoked from
** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY]
** flag is recommended for any application-defined SQL function that has
** side-effects.
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
@ -4965,8 +4983,30 @@ int sqlite3_create_window_function(
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
**
** The SQLITE_DETERMINISTIC flag means that the new function will always
** maps the same inputs into the same output. The abs() function is
** deterministic, for example, but randomblob() is not.
**
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is
** a security feature which is recommended for all
** [application-defined SQL functions] that have side-effects. This flag
** prevents an attacker from adding triggers and views to a schema then
** tricking a high-privilege application into causing unintended side-effects
** while performing ordinary queries.
**
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
** functions. However, if it is not specified for a user-defined window
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
*/
#define SQLITE_DETERMINISTIC 0x800
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
/*
** CAPI3REF: Deprecated Functions
@ -6628,6 +6668,12 @@ struct sqlite3_index_info {
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^If the third parameter (the pointer to the sqlite3_module object) is
** NULL then no new module is create and any existing modules with the
** same name are dropped.
**
** See also: [sqlite3_drop_modules()]
*/
int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
@ -6643,6 +6689,23 @@ int sqlite3_create_module_v2(
void(*xDestroy)(void*) /* Module destructor function */
);
/*
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
** METHOD: sqlite3
**
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
** table modules from database connection D except those named on list L.
** The L parameter must be either NULL or a pointer to an array of pointers
** to strings where the array is terminated by a single NULL pointer.
** ^If the L parameter is NULL, then all virtual table modules are removed.
**
** See also: [sqlite3_create_module()]
*/
int sqlite3_drop_modules(
sqlite3 *db, /* Remove modules from this connection */
const char **azKeep /* Except, do not remove the ones named here */
);
/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
@ -7351,7 +7414,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_FIRST 5
#define SQLITE_TESTCTRL_PRNG_SAVE 5
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
#define SQLITE_TESTCTRL_PRNG_RESET 7
#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
#define SQLITE_TESTCTRL_BITVEC_TEST 8
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
@ -7374,7 +7437,9 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_IMPOSTER 25
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking

View File

@ -322,6 +322,8 @@ struct sqlite3_api_routines {
/* Version 3.28.0 and later */
int (*stmt_isexplain)(sqlite3_stmt*);
int (*value_frombind)(sqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(sqlite3*,const char**);
};
/*
@ -614,6 +616,8 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain sqlite3_api->isexplain
#define sqlite3_value_frombind sqlite3_api->frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules sqlite3_api->drop_modules
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)

View File

@ -212,15 +212,15 @@
** So we have to define the macros in different ways depending on the
** compiler.
*/
#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
#else /* Generates a warning - but it always works */
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(X))
@ -935,20 +935,6 @@ typedef INT16_TYPE LogEst;
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif
/*
** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also
** define SQLITE_ENABLE_STAT3_OR_STAT4
*/
#ifdef SQLITE_ENABLE_STAT4
# undef SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3_OR_STAT4
# undef SQLITE_ENABLE_STAT3_OR_STAT4
#endif
/*
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
@ -1412,6 +1398,7 @@ struct sqlite3 {
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@ -1550,16 +1537,17 @@ struct sqlite3 {
#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
/* Flags used only if debugging */
#define HI(X) ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */
#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */
#endif
/*
@ -1587,8 +1575,8 @@ struct sqlite3 {
#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
/* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
/* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
#define SQLITE_PushDown 0x1000 /* The push-down optimization */
#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x4000 /* Skip-scans */
@ -1676,6 +1664,7 @@ struct FuncDestructor {
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@ -1696,6 +1685,8 @@ struct FuncDestructor {
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@ -1809,6 +1800,7 @@ struct Savepoint {
struct Module {
const sqlite3_module *pModule; /* Callback pointers */
const char *zName; /* Name passed to create_module() */
int nRefModule; /* Number of pointers to this object */
void *pAux; /* pAux passed to create_module() */
void (*xDestroy)(void *); /* Module destructor function */
Table *pEpoTab; /* Eponymous table for this module */
@ -1874,11 +1866,12 @@ struct CollSeq {
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison. And the BLOB type is first.
*/
#define SQLITE_AFF_BLOB 'A'
#define SQLITE_AFF_TEXT 'B'
#define SQLITE_AFF_NUMERIC 'C'
#define SQLITE_AFF_INTEGER 'D'
#define SQLITE_AFF_REAL 'E'
#define SQLITE_AFF_NONE 0x40 /* '@' */
#define SQLITE_AFF_BLOB 0x41 /* 'A' */
#define SQLITE_AFF_TEXT 0x42 /* 'B' */
#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@ -2146,10 +2139,16 @@ struct KeyInfo {
u16 nKeyField; /* Number of key columns in the index */
u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortOrder; /* Sort order for each column. */
u8 *aSortFlags; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
/*
** This object holds a record which has been parsed out into individual
** fields, for the purposes of doing a comparison.
@ -2257,7 +2256,7 @@ struct Index {
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
@ -2289,7 +2288,7 @@ struct Index {
#define XN_EXPR (-2) /* Indexed column is an expression */
/*
** Each sample stored in the sqlite_stat3 table is represented in memory
** Each sample stored in the sqlite_stat4 table is represented in memory
** using a structure of this type. See documentation at the top of the
** analyze.c source file for additional information.
*/
@ -2447,7 +2446,7 @@ typedef int ynVar;
*/
struct Expr {
u8 op; /* Operation performed by this node */
char affinity; /* The affinity of the column or 0 if not a column */
char affExpr; /* affinity, or RAISE type */
u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
@ -2478,6 +2477,8 @@ struct Expr {
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 134217728 times likelihood
** TK_IN: ephemerial table holding RHS
** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1).
@ -2491,7 +2492,7 @@ struct Expr {
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* TK_FUNCTION: Window definition for the func */
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
@ -2506,36 +2507,37 @@ struct Expr {
** EP_Agg == NC_HasAgg == SF_HasAgg
** EP_Win == NC_HasWin
*/
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
/* 0x000200 Available for reuse */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_Indirect 0x40000000 /* Contained within a TRIGGER or a VIEW */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@ -2579,6 +2581,18 @@ struct Expr {
*/
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
/*
** True if the expression passed as an argument was a function with
** an OVER() clause (a window function).
*/
#ifdef SQLITE_OMIT_WINDOWFUNC
# define IsWindowFunc(p) 0
#else
# define IsWindowFunc(p) ( \
ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
)
#endif
/*
** A list of expressions. Each expression may optionally have a
** name. An expr/name combination can be used in several ways, such
@ -2601,11 +2615,12 @@ struct ExprList {
Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
char *zSpan; /* Original text of the expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
union {
struct {
u16 iOrderByCol; /* For ORDER BY, column number in result set */
@ -2896,6 +2911,7 @@ struct Select {
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
#define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */
/*
** The results of a SELECT can be distributed in several ways, as defined
@ -3400,11 +3416,12 @@ typedef struct {
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
int bSmallMalloc; /* Avoid large memory allocations if true */
u8 bCoreMutex; /* True to enable core mutexing */
u8 bFullMutex; /* True to enable full mutexing */
u8 bOpenUri; /* True to interpret filenames as URIs */
u8 bUseCis; /* Use covering indices for full-scans */
u8 bSmallMalloc; /* Avoid large memory allocations if true */
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@ -3456,6 +3473,7 @@ struct Sqlite3Config {
int bInternalFunctions; /* Internal SQL functions are visible */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
};
/*
@ -3552,10 +3570,11 @@ struct TreeView {
#endif /* SQLITE_DEBUG */
/*
** This object is used in various ways, all related to window functions
** This object is used in various ways, most (but not all) related to window
** functions.
**
** (1) A single instance of this structure is attached to the
** the Expr.pWin field for each window function in an expression tree.
** the Expr.y.pWin field for each window function in an expression tree.
** This object holds the information contained in the OVER clause,
** plus additional fields used during code generation.
**
@ -3566,6 +3585,10 @@ struct TreeView {
** (3) The terms of the WINDOW clause of a SELECT are instances of this
** object on a linked list attached to Select.pWinDefn.
**
** (4) For an aggregate function with a FILTER clause, an instance
** of this object is stored in Expr.y.pWin with eFrmType set to
** TK_FILTER. In this case the only field used is Window.pFilter.
**
** The uses (1) and (2) are really the same Window object that just happens
** to be accessible in two different ways. Use case (3) are separate objects.
*/
@ -3581,12 +3604,13 @@ struct Window {
u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
Expr *pStart; /* Expression for "<expr> PRECEDING" */
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
Window **ppThis; /* Pointer to this object in Select.pWin list */
Window *pNextWin; /* Next window function belonging to this SELECT */
Expr *pFilter; /* The FILTER expression */
FuncDef *pFunc; /* The function */
int iEphCsr; /* Partition buffer or Peer buffer */
int regAccum;
int regResult;
int regAccum; /* Accumulator */
int regResult; /* Interim result */
int csrApp; /* Function cursor (used by min/max) */
int regApp; /* Function register (also used by min/max) */
int regPart; /* Array of registers for PARTITION BY values */
@ -3596,14 +3620,18 @@ struct Window {
int regOne; /* Register containing constant value 1 */
int regStartRowid;
int regEndRowid;
u8 bExprArgs; /* Defer evaluation of window function arguments
** due to the SQLITE_SUBTYPE flag */
};
#ifndef SQLITE_OMIT_WINDOWFUNC
void sqlite3WindowDelete(sqlite3*, Window*);
void sqlite3WindowUnlinkFromSelect(Window*);
void sqlite3WindowListDelete(sqlite3 *db, Window *p);
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
void sqlite3WindowAttach(Parse*, Expr*, Window*);
int sqlite3WindowCompare(Parse*, Window*, Window*);
void sqlite3WindowLink(Select *pSel, Window *pWin);
int sqlite3WindowCompare(Parse*, Window*, Window*, int);
void sqlite3WindowCodeInit(Parse*, Window*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
@ -3875,7 +3903,7 @@ void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
@ -3894,8 +3922,8 @@ void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
Table *sqlite3ResultSetOfSelect(Parse*,Select*);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenMasterTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3ColumnOfIndex(Index*, i16);
@ -4196,7 +4224,7 @@ LogEst sqlite3LogEstAdd(LogEst,LogEst);
LogEst sqlite3LogEstFromDouble(double);
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
defined(SQLITE_ENABLE_STAT4) || \
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
u64 sqlite3LogEstToInt(LogEst);
#endif
@ -4262,9 +4290,10 @@ int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3WritableSchema(sqlite3*);
int sqlite3CheckObjectName(Parse *, const char *);
int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
void sqlite3VdbeSetChanges(sqlite3 *, int);
int sqlite3AddInt64(i64*,i64);
int sqlite3SubInt64(i64*,i64);
@ -4297,7 +4326,6 @@ extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[];
extern const Token sqlite3IntTokens[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD
@ -4351,6 +4379,7 @@ void sqlite3KeyInfoUnref(KeyInfo*);
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
int sqlite3HasExplicitNulls(Parse*, ExprList*);
#ifdef SQLITE_DEBUG
int sqlite3KeyInfoIsWriteable(KeyInfo*);
@ -4383,8 +4412,7 @@ int sqlite3ExprCheckIN(Parse*, Expr*);
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
void sqlite3AnalyzeFunctions(void);
#ifdef SQLITE_ENABLE_STAT4
int sqlite3Stat4ProbeSetValue(
Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
@ -4431,6 +4459,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
# define sqlite3VtabInSync(db) 0
# define sqlite3VtabLock(X)
# define sqlite3VtabUnlock(X)
# define sqlite3VtabModuleUnref(D,X)
# define sqlite3VtabUnlockList(X)
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
# define sqlite3GetVTable(X,Y) ((VTable*)0)
@ -4442,6 +4471,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
int sqlite3VtabCommit(sqlite3 *db);
void sqlite3VtabLock(VTable *);
void sqlite3VtabUnlock(VTable *);
void sqlite3VtabModuleUnref(sqlite3*,Module*);
void sqlite3VtabUnlockList(sqlite3*);
int sqlite3VtabSavepoint(sqlite3 *, int, int);
void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);

View File

@ -1917,33 +1917,33 @@ static int SQLITE_TCLAPI DbObjCmd(
"authorizer", "backup", "bind_fallback",
"busy", "cache", "changes",
"close", "collate", "collation_needed",
"commit_hook", "complete", "copy",
"deserialize", "enable_load_extension", "errorcode",
"eval", "exists", "function",
"incrblob", "interrupt", "last_insert_rowid",
"nullvalue", "onecolumn", "preupdate",
"profile", "progress", "rekey",
"restore", "rollback_hook", "serialize",
"status", "timeout", "total_changes",
"trace", "trace_v2", "transaction",
"unlock_notify", "update_hook", "version",
"wal_hook", 0
"commit_hook", "complete", "config",
"copy", "deserialize", "enable_load_extension",
"errorcode", "eval", "exists",
"function", "incrblob", "interrupt",
"last_insert_rowid", "nullvalue", "onecolumn",
"preupdate", "profile", "progress",
"rekey", "restore", "rollback_hook",
"serialize", "status", "timeout",
"total_changes", "trace", "trace_v2",
"transaction", "unlock_notify", "update_hook",
"version", "wal_hook", 0
};
enum DB_enum {
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
DB_BUSY, DB_CACHE, DB_CHANGES,
DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY,
DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
DB_EVAL, DB_EXISTS, DB_FUNCTION,
DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID,
DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE,
DB_PROFILE, DB_PROGRESS, DB_REKEY,
DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE,
DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
DB_WAL_HOOK
DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
DB_ERRORCODE, DB_EVAL, DB_EXISTS,
DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
DB_PREUPDATE, DB_PROFILE, DB_PROGRESS,
DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK,
DB_SERIALIZE, DB_STATUS, DB_TIMEOUT,
DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2,
DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK,
DB_VERSION, DB_WAL_HOOK
};
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
@ -2331,6 +2331,74 @@ static int SQLITE_TCLAPI DbObjCmd(
break;
}
/* $db config ?OPTION? ?BOOLEAN?
**
** Configure the database connection using the sqlite3_db_config()
** interface.
*/
case DB_CONFIG: {
static const struct DbConfigChoices {
const char *zName;
int op;
} aDbConfig[] = {
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
{ "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
{ "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
{ "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
{ "defensive", SQLITE_DBCONFIG_DEFENSIVE },
{ "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
{ "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
{ "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
{ "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
};
Tcl_Obj *pResult;
int ii;
if( objc>4 ){
Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?");
return TCL_ERROR;
}
if( objc==2 ){
/* With no arguments, list all configuration options and with the
** current value */
pResult = Tcl_NewListObj(0,0);
for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
int v = 0;
sqlite3_db_config(pDb->db, aDbConfig[ii].op, -1, &v);
Tcl_ListObjAppendElement(interp, pResult,
Tcl_NewStringObj(aDbConfig[ii].zName,-1));
Tcl_ListObjAppendElement(interp, pResult,
Tcl_NewIntObj(v));
}
}else{
const char *zOpt = Tcl_GetString(objv[2]);
int onoff = -1;
int v = 0;
if( zOpt[0]=='-' ) zOpt++;
for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
if( strcmp(aDbConfig[ii].zName, zOpt)==0 ) break;
}
if( ii>=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){
Tcl_AppendResult(interp, "unknown config option: \"", zOpt,
"\"", (void*)0);
return TCL_ERROR;
}
if( objc==4 ){
if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){
return TCL_ERROR;
}
}
sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v);
pResult = Tcl_NewIntObj(v);
}
Tcl_SetObjResult(interp, pResult);
break;
}
/* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
**
** Copy data into table from filename, optionally using SEPARATOR
@ -2741,10 +2809,16 @@ deserialize_error:
}
/*
** $db function NAME [-argcount N] [-deterministic] SCRIPT
** $db function NAME [OPTIONS] SCRIPT
**
** Create a new SQL function called NAME. Whenever that function is
** called, invoke SCRIPT to evaluate the function.
**
** Options:
** --argcount N Function has exactly N arguments
** --deterministic The function is pure
** --directonly Prohibit use inside triggers and views
** --returntype TYPE Specify the return type of the function
*/
case DB_FUNCTION: {
int flags = SQLITE_UTF8;
@ -2777,6 +2851,9 @@ deserialize_error:
if( n>1 && strncmp(z, "-deterministic",n)==0 ){
flags |= SQLITE_DETERMINISTIC;
}else
if( n>1 && strncmp(z, "-directonly",n)==0 ){
flags |= SQLITE_DIRECTONLY;
}else
if( n>1 && strncmp(z, "-returntype", n)==0 ){
const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
@ -2792,7 +2869,8 @@ deserialize_error:
eType++;
}else{
Tcl_AppendResult(interp, "bad option \"", z,
"\": must be -argcount, -deterministic or -returntype", (char*)0
"\": must be -argcount, -deterministic, -directonly,"
" or -returntype", (char*)0
);
return TCL_ERROR;
}

View File

@ -1110,6 +1110,33 @@ static int SQLITE_TCLAPI test_create_function(
return TCL_OK;
}
/*
** Usage: sqlite3_drop_modules DB ?NAME ...?
**
** Invoke the sqlite3_drop_modules(D,L) interface on database
** connection DB, in order to drop all modules except those named in
** the argument.
*/
static int SQLITE_TCLAPI test_drop_modules(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
sqlite3 *db;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" DB\"", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0);
#endif
return TCL_OK;
}
/*
** Routines to implement the x_count() aggregate function.
**
@ -6373,7 +6400,41 @@ static int SQLITE_TCLAPI reset_prng_state(
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
sqlite3_randomness(0,0);
return TCL_OK;
}
/*
** tclcmd: prng_seed INT ?DB?
**
** Set up the SQLITE_TESTCTRL_PRNG_SEED pragma with parameter INT and DB.
** INT is an integer. DB is a database connection, or a NULL pointer if
** omitted.
**
** When INT!=0 and DB!=0, set the PRNG seed to the value of the schema
** cookie for DB, or to INT if the schema cookie happens to be zero.
**
** When INT!=0 and DB==0, set the PRNG seed to just INT.
**
** If INT==0 and DB==0 then use the default procedure of calling the
** xRandomness method on the default VFS to get the PRNG seed.
*/
static int SQLITE_TCLAPI prng_seed(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
int i = 0;
sqlite3 *db = 0;
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp,objv[0],&i) ) return TCL_ERROR;
if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
return TCL_ERROR;
}
sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, i, db);
return TCL_OK;
}
@ -7139,9 +7200,9 @@ static int SQLITE_TCLAPI optimization_control(
{ "order-by-idx-join", SQLITE_OrderByIdxJoin },
{ "transitive", SQLITE_Transitive },
{ "omit-noop-join", SQLITE_OmitNoopJoin },
{ "stat3", SQLITE_Stat34 },
{ "stat4", SQLITE_Stat34 },
{ "stat4", SQLITE_Stat4 },
{ "skip-scan", SQLITE_SkipScan },
{ "push-down", SQLITE_PushDown },
};
if( objc!=4 ){
@ -7740,6 +7801,11 @@ static int SQLITE_TCLAPI test_decode_hexdb(
int pgsz;
rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz);
if( rc!=2 ) continue;
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
Tcl_AppendResult(interp, "bad 'pagesize' field", (void*)0);
return TCL_ERROR;
}
n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
if( n<512 ){
Tcl_AppendResult(interp, "bad 'size' field", (void*)0);
return TCL_ERROR;
@ -7822,6 +7888,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
{ "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
{ "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
{ "sqlite3_drop_modules", (Tcl_CmdProc*)test_drop_modules },
{ "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
{ "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
{ "sqlite_bind", (Tcl_CmdProc*)test_bind },
@ -7918,6 +7985,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "save_prng_state", save_prng_state, 0 },
{ "restore_prng_state", restore_prng_state, 0 },
{ "reset_prng_state", reset_prng_state, 0 },
{ "prng_seed", prng_seed, 0 },
{ "database_never_corrupt", database_never_corrupt, 0},
{ "database_may_be_corrupt", database_may_be_corrupt, 0},
{ "optimization_control", optimization_control,0},

View File

@ -585,12 +585,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "stat4", "0", TCL_GLOBAL_ONLY);
#endif
#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
Tcl_SetVar2(interp, "sqlite_options", "stat3", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
#endif
#if defined(SQLITE_ENABLE_STMTVTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
Tcl_SetVar2(interp, "sqlite_options", "stmtvtab", "1", TCL_GLOBAL_ONLY);
#else

View File

@ -337,6 +337,17 @@ static int getFts3Varint(const char *p, sqlite_int64 *v){
return (int) (q - (unsigned char *)p);
}
static int putFts3Varint(char *p, sqlite_int64 v){
unsigned char *q = (unsigned char *) p;
sqlite_uint64 vu = v;
do{
*q++ = (unsigned char) ((vu & 0x7f) | 0x80);
vu >>= 7;
}while( vu!=0 );
q[-1] &= 0x7f; /* turn off high bit in final byte */
assert( q - (unsigned char *)p <= 10 );
return (int) (q - (unsigned char *)p);
}
/*
** USAGE: read_fts3varint BLOB VARNAME
@ -367,6 +378,67 @@ static int SQLITE_TCLAPI read_fts3varint(
return TCL_OK;
}
/*
** USAGE: make_fts3record ARGLIST
*/
static int SQLITE_TCLAPI make_fts3record(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
Tcl_Obj **aArg = 0;
int nArg = 0;
unsigned char *aOut = 0;
int nOut = 0;
int nAlloc = 0;
int i;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "LIST");
return TCL_ERROR;
}
if( Tcl_ListObjGetElements(interp, objv[1], &nArg, &aArg) ){
return TCL_ERROR;
}
for(i=0; i<nArg; i++){
sqlite3_int64 iVal;
if( TCL_OK==Tcl_GetWideIntFromObj(0, aArg[i], &iVal) ){
if( nOut+10>nAlloc ){
int nNew = nAlloc?nAlloc*2:128;
unsigned char *aNew = sqlite3_realloc(aOut, nNew);
if( aNew==0 ){
sqlite3_free(aOut);
return TCL_ERROR;
}
aOut = aNew;
nAlloc = nNew;
}
nOut += putFts3Varint((char*)&aOut[nOut], iVal);
}else{
int nVal = 0;
char *zVal = Tcl_GetStringFromObj(aArg[i], &nVal);
while( (nOut + nVal)>nAlloc ){
int nNew = nAlloc?nAlloc*2:128;
unsigned char *aNew = sqlite3_realloc(aOut, nNew);
if( aNew==0 ){
sqlite3_free(aOut);
return TCL_ERROR;
}
aOut = aNew;
nAlloc = nNew;
}
memcpy(&aOut[nOut], zVal, nVal);
nOut += nVal;
}
}
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aOut, nOut));
sqlite3_free(aOut);
return TCL_OK;
}
/*
** Register commands with the TCL interpreter.
@ -383,6 +455,7 @@ int Sqlitetest_hexio_Init(Tcl_Interp *interp){
{ "hexio_render_int32", hexio_render_int32 },
{ "utf8_to_utf8", utf8_to_utf8 },
{ "read_fts3varint", read_fts3varint },
{ "make_fts3record", make_fts3record },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){

View File

@ -176,13 +176,17 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
sqlite3TreeViewPush(pView, 1);
}
do{
sqlite3TreeViewLine(pView,
"SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
p->selId, p, p->selFlags,
(int)p->nSelectRow
);
if( p->selFlags & SF_WhereBegin ){
sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
}else{
sqlite3TreeViewLine(pView,
"SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
p->selId, p, p->selFlags,
(int)p->nSelectRow
);
}
if( cnt++ ) sqlite3TreeViewPop(pView);
if( p->pPrior ){
n = 1000;
@ -199,7 +203,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
if( p->pWinDefn ) n++;
#endif
}
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pEList ){
sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
}
n--;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
Window *pX;
@ -395,12 +402,14 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
sqlite3TreeViewPop(pView);
return;
}
if( pExpr->flags ){
if( pExpr->flags || pExpr->affExpr ){
if( ExprHasProperty(pExpr, EP_FromJoin) ){
sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
pExpr->flags, pExpr->iRightJoinTable);
sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c iRJT=%d",
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n',
pExpr->iRightJoinTable);
}else{
sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c",
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
}
}else{
zFlgs[0] = 0;
@ -527,7 +536,14 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
}
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
/* COLLATE operators without the EP_Collate flag are intended to
** emulate collation associated with a table column. These show
** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
** operators that appear in the original SQL always have the
** EP_Collate bit set and appear in treeview output as just "COLLATE" */
sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
!ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
pExpr->u.zToken, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
@ -548,10 +564,10 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
pExpr->op2, pExpr->u.zToken, zFlgs);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
@ -628,7 +644,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
switch( pExpr->affExpr ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
@ -669,7 +685,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}

View File

@ -177,7 +177,11 @@ void sqlite3BeginTrigger(
/* Check that the trigger name is not reserved and that no trigger of the
** specified name exists */
zName = sqlite3NameFromToken(db, pName);
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( zName==0 ){
assert( db->mallocFailed );
goto trigger_cleanup;
}
if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
goto trigger_cleanup;
}
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
@ -340,6 +344,7 @@ void sqlite3FinishTrigger(
Trigger *pLink = pTrig;
Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
assert( pLink!=0 );
pTrig = sqlite3HashInsert(pHash, zName, pTrig);
if( pTrig ){
sqlite3OomFault(db);
@ -458,6 +463,9 @@ TriggerStep *sqlite3TriggerInsertStep(
pTriggerStep->pIdList = pColumn;
pTriggerStep->pUpsert = pUpsert;
pTriggerStep->orconf = orconf;
if( pUpsert ){
sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget);
}
}else{
testcase( pColumn );
sqlite3IdListDelete(db, pColumn);
@ -613,10 +621,9 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
assert( iDb>=0 && iDb<db->nDb );
pTable = tableOfTrigger(pTrigger);
assert( pTable );
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
if( pTable ){
int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[iDb].zDbSName;
const char *zTab = SCHEMA_TABLE(iDb);
@ -630,7 +637,6 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
/* Generate code to destroy the database record of the trigger.
*/
assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
@ -654,9 +660,11 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
if( ALWAYS(pTrigger) ){
if( pTrigger->pSchema==pTrigger->pTabSchema ){
Table *pTab = tableOfTrigger(pTrigger);
Trigger **pp;
for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
*pp = (*pp)->pNext;
if( pTab ){
Trigger **pp;
for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
*pp = (*pp)->pNext;
}
}
sqlite3DeleteTrigger(db, pTrigger);
db->mDbFlags |= DBFLAG_SchemaChange;

View File

@ -715,28 +715,30 @@ void sqlite3Update(
}
if( !isView ){
int addr1 = 0; /* Address of jump instruction */
/* Do constraint checks. */
assert( regOldRowid>0 );
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
aXRef, 0);
/* If REPLACE conflict handling may have been used, or if the PK of the
** row is changing, then the GenerateConstraintChecks() above may have
** moved cursor iDataCur. Reseek it. */
if( bReplace || chngKey ){
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
VdbeCoverageNeverTaken(v);
}
/* Do FK constraint checks. */
if( hasFK ){
sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
}
/* Delete the index entries associated with the current record. */
if( bReplace || chngKey ){
if( pPk ){
addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
}else{
addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
}
VdbeCoverageNeverTaken(v);
}
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
/* If changing the rowid value, or if there are foreign key constraints
@ -766,9 +768,6 @@ void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
#endif
if( bReplace || chngKey ){
sqlite3VdbeJumpHere(v, addr1);
}
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);

View File

@ -205,6 +205,7 @@ void sqlite3UpsertDoUpdate(
sqlite3 *db = pParse->db;
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
assert( v!=0 );
assert( pUpsert!=0 );
@ -221,7 +222,6 @@ void sqlite3UpsertDoUpdate(
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol;
int iPk = pParse->nMem+1;
int i;
pParse->nMem += nPk;
for(i=0; i<nPk; i++){
int k;
@ -242,6 +242,12 @@ void sqlite3UpsertDoUpdate(
/* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
** we have to make a copy before passing it down into sqlite3Update() */
pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
}
}
sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */

View File

@ -1498,7 +1498,7 @@ LogEst sqlite3LogEstFromDouble(double x){
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
defined(SQLITE_ENABLE_STAT4) || \
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
/*
** Convert a LogEst into an integer.
@ -1516,7 +1516,7 @@ u64 sqlite3LogEstToInt(LogEst x){
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
if( x>60 ) return (u64)LARGEST_INT64;
#else
/* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
/* If only SQLITE_ENABLE_STAT4 is on, then the largest input
** possible to this routine is 310, resulting in a maximum x of 31 */
assert( x<=60 );
#endif

View File

@ -343,6 +343,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
** Convert pRec to a text representation.
**
** SQLITE_AFF_BLOB:
** SQLITE_AFF_NONE:
** No-op. pRec is unchanged.
*/
static void applyAffinity(
@ -482,13 +483,15 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
c = 's';
}
*(zCsr++) = c;
*(zCsr++) = 'x';
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
zCsr += sqlite3Strlen30(zCsr);
for(i=0; i<16 && i<pMem->n; i++){
for(i=0; i<25 && i<pMem->n; i++){
sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
zCsr += sqlite3Strlen30(zCsr);
}
for(i=0; i<16 && i<pMem->n; i++){
*zCsr++ = '|';
for(i=0; i<25 && i<pMem->n; i++){
char z = pMem->z[i];
if( z<32 || z>126 ) *zCsr++ = '.';
else *zCsr++ = z;
@ -518,7 +521,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
k += sqlite3Strlen30(&zBuf[k]);
zBuf[k++] = '[';
for(j=0; j<15 && j<pMem->n; j++){
for(j=0; j<25 && j<pMem->n; j++){
u8 c = pMem->z[j];
if( c>=0x20 && c<0x7f ){
zBuf[k++] = c;
@ -551,7 +554,7 @@ static void memTracePrint(Mem *p){
printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
printf(" r:%g", p->u.r);
printf(" r:%.17g", p->u.r);
#endif
}else if( sqlite3VdbeMemIsRowSet(p) ){
printf(" (rowset)");
@ -1140,7 +1143,6 @@ case OP_Real: { /* same as TK_FLOAT, out2 */
case OP_String8: { /* same as TK_STRING, out2 */
assert( pOp->p4.z!=0 );
pOut = out2Prerelease(p, pOp);
pOp->opcode = OP_String;
pOp->p1 = sqlite3Strlen30(pOp->p4.z);
#ifndef SQLITE_OMIT_UTF16
@ -1164,6 +1166,7 @@ case OP_String8: { /* same as TK_STRING, out2 */
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
pOp->opcode = OP_String;
assert( rc==SQLITE_OK );
/* Fall through to the next case, OP_String */
}
@ -1831,6 +1834,7 @@ case OP_RealAffinity: { /* in1 */
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_IntReal );
sqlite3VdbeMemRealify(pIn1);
REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
@ -2226,9 +2230,14 @@ case OP_Compare: {
REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
assert( i<pKeyInfo->nKeyField );
pColl = pKeyInfo->aColl[i];
bRev = pKeyInfo->aSortOrder[i];
bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC);
iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
if( iCompare ){
if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
&& ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null))
){
iCompare = -iCompare;
}
if( bRev ) iCompare = -iCompare;
break;
}
@ -2519,11 +2528,6 @@ case OP_Offset: { /* out3 */
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
** then the cache of the cursor is reset prior to extracting the column.
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
**
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively. The loading of large blobs can be
@ -2812,15 +2816,27 @@ case OP_Affinity: {
assert( pOp->p2>0 );
assert( zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
while( 1 /*edit-by-break*/ ){
while( 1 /*exit-by-break*/ ){
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
assert( memIsValid(pIn1) );
applyAffinity(pIn1, zAffinity[0], encoding);
if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){
/* When applying REAL affinity, if the result is still MEM_Int,
** indicate that REAL is actually desired */
pIn1->flags |= MEM_IntReal;
pIn1->flags &= ~MEM_Int;
/* When applying REAL affinity, if the result is still an MEM_Int
** that will fit in 6 bytes, then change the type to MEM_IntReal
** so that we keep the high-resolution integer value but know that
** the type really wants to be REAL. */
testcase( pIn1->u.i==140737488355328LL );
testcase( pIn1->u.i==140737488355327LL );
testcase( pIn1->u.i==-140737488355328LL );
testcase( pIn1->u.i==-140737488355329LL );
if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){
pIn1->flags |= MEM_IntReal;
pIn1->flags &= ~MEM_Int;
}else{
pIn1->u.r = (double)pIn1->u.i;
pIn1->flags |= MEM_Real;
pIn1->flags &= ~MEM_Int;
}
}
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
zAffinity++;
@ -2927,14 +2943,36 @@ case OP_MakeRecord: {
#endif
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
** out how much space is required for the new record. After this loop,
** the Mem.uTemp field of each term should hold the serial-type that will
** be used for that term in the generated record:
**
** Mem.uTemp value type
** --------------- ---------------
** 0 NULL
** 1 1-byte signed integer
** 2 2-byte signed integer
** 3 3-byte signed integer
** 4 4-byte signed integer
** 5 6-byte signed integer
** 6 8-byte signed integer
** 7 IEEE float
** 8 Integer constant 0
** 9 Integer constant 1
** 10,11 reserved for expansion
** N>=12 and even BLOB
** N>=13 and odd text
**
** The following additional values are computed:
** nHdr Number of bytes needed for the record header
** nData Number of bytes of data space needed for the record
** nZero Zero bytes at the end of the record
*/
pRec = pLast;
do{
assert( memIsValid(pRec) );
serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
if( pRec->flags & MEM_Zero ){
if( serial_type==0 ){
if( pRec->flags & MEM_Null ){
if( pRec->flags & MEM_Zero ){
/* Values with MEM_Null and MEM_Zero are created by xColumn virtual
** table methods that never invoke sqlite3_result_xxxxx() while
** computing an unchanging column value in an UPDATE statement.
@ -2942,19 +2980,83 @@ case OP_MakeRecord: {
** so that they can be passed through to xUpdate and have
** a true sqlite3_value_nochange(). */
assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
serial_type = 10;
}else if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
pRec->uTemp = 10;
}else{
nZero += pRec->u.nZero;
len -= pRec->u.nZero;
pRec->uTemp = 0;
}
nHdr++;
}else if( pRec->flags & (MEM_Int|MEM_IntReal) ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
i64 i = pRec->u.i;
u64 uu;
testcase( pRec->flags & MEM_Int );
testcase( pRec->flags & MEM_IntReal );
if( i<0 ){
uu = ~i;
}else{
uu = i;
}
nHdr++;
testcase( uu==127 ); testcase( uu==128 );
testcase( uu==32767 ); testcase( uu==32768 );
testcase( uu==8388607 ); testcase( uu==8388608 );
testcase( uu==2147483647 ); testcase( uu==2147483648 );
testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL );
if( uu<=127 ){
if( (i&1)==i && file_format>=4 ){
pRec->uTemp = 8+(u32)uu;
}else{
nData++;
pRec->uTemp = 1;
}
}else if( uu<=32767 ){
nData += 2;
pRec->uTemp = 2;
}else if( uu<=8388607 ){
nData += 3;
pRec->uTemp = 3;
}else if( uu<=2147483647 ){
nData += 4;
pRec->uTemp = 4;
}else if( uu<=140737488355327LL ){
nData += 6;
pRec->uTemp = 5;
}else{
nData += 8;
if( pRec->flags & MEM_IntReal ){
/* If the value is IntReal and is going to take up 8 bytes to store
** as an integer, then we might as well make it an 8-byte floating
** point value */
pRec->u.r = (double)pRec->u.i;
pRec->flags &= ~MEM_IntReal;
pRec->flags |= MEM_Real;
pRec->uTemp = 7;
}else{
pRec->uTemp = 6;
}
}
}else if( pRec->flags & MEM_Real ){
nHdr++;
nData += 8;
pRec->uTemp = 7;
}else{
assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) );
assert( pRec->n>=0 );
len = (u32)pRec->n;
serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
if( pRec->flags & MEM_Zero ){
serial_type += pRec->u.nZero*2;
if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
len += pRec->u.nZero;
}else{
nZero += pRec->u.nZero;
}
}
nData += len;
nHdr += sqlite3VarintLen(serial_type);
pRec->uTemp = serial_type;
}
nData += len;
testcase( serial_type==127 );
testcase( serial_type==128 );
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
pRec->uTemp = serial_type;
if( pRec==pData0 ) break;
pRec--;
}while(1);
@ -3290,7 +3392,7 @@ case OP_AutoCommit: {
rc = SQLITE_ERROR;
goto abort_due_to_error;
}
break;
/*NOTREACHED*/ assert(0);
}
/* Opcode: Transaction P1 P2 P3 P4 P5
@ -4028,6 +4130,7 @@ case OP_SeekGT: { /* jump, in3, group */
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( pC->isTable ){
u16 flags3, newType;
/* The BTREE_SEEK_EQ flag is only set on index cursors */
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
|| CORRUPT_DB );
@ -4036,18 +4139,21 @@ case OP_SeekGT: { /* jump, in3, group */
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
flags3 = pIn3->flags;
if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3);
iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */
newType = pIn3->flags; /* Record the type after applying numeric affinity */
pIn3->flags = flags3; /* But convert the type back to its original */
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
if( (pIn3->flags & MEM_Real)==0 ){
if( (pIn3->flags & MEM_Null) || oc>=OP_SeekGE ){
VdbeBranchTaken(1,2); goto jump_to_p2;
break;
if( (newType & (MEM_Int|MEM_IntReal))==0 ){
if( (newType & MEM_Real)==0 ){
if( (newType & MEM_Null) || oc>=OP_SeekGE ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}else{
rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
@ -4432,23 +4538,27 @@ case OP_SeekRowid: { /* jump, in3 */
pIn3 = &aMem[pOp->p3];
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_IntReal );
testcase( pIn3->flags & MEM_Real );
testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
/* Make sure pIn3->u.i contains a valid integer representation of
** the key value, but do not change the datatype of the register, as
** other parts of the perpared statement might be depending on the
** current datatype. */
u16 origFlags = pIn3->flags;
int isNotInt;
applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
isNotInt = (pIn3->flags & MEM_Int)==0;
pIn3->flags = origFlags;
if( isNotInt ) goto jump_to_p2;
/* If pIn3->u.i does not contain an integer, compute iKey as the
** integer value of pIn3. Jump to P2 if pIn3 cannot be converted
** into an integer without loss of information. Take care to avoid
** changing the datatype of pIn3, however, as it is used by other
** parts of the prepared statement. */
Mem x = pIn3[0];
applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
iKey = x.u.i;
goto notExistsWithKey;
}
/* Fall through into OP_NotExists */
case OP_NotExists: /* jump, in3 */
pIn3 = &aMem[pOp->p3];
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
iKey = pIn3->u.i;
notExistsWithKey:
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
@ -4459,7 +4569,6 @@ case OP_NotExists: /* jump, in3 */
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */
@ -5341,11 +5450,12 @@ case OP_Next: /* jump */
** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
assert( pOp->opcode!=OP_Next
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|| pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid);
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|| pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid
|| pC->seekOp==OP_IfNoHope);
assert( pOp->opcode!=OP_Prev
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last
|| pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope
|| pC->seekOp==OP_NullRow);
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
@ -5864,7 +5974,7 @@ case OP_ParseSchema: {
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
"SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;

View File

@ -222,10 +222,10 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
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 sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);

View File

@ -486,7 +486,6 @@ int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
int sqlite3VdbeCursorRestore(VdbeCursor*);
u32 sqlite3VdbeSerialTypeLen(u32);
u8 sqlite3VdbeOneByteSerialTypeLen(u8);
u32 sqlite3VdbeSerialType(Mem*, int, u32*);
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);

View File

@ -844,7 +844,7 @@ int sqlite3_vtab_nochange(sqlite3_context *p){
*/
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
int rc;
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
#ifndef SQLITE_ENABLE_STAT4
sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
assert( p->pVdbe!=0 );
#else
@ -909,7 +909,7 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#if SQLITE_ENABLE_STAT3_OR_STAT4
#if SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 0;
#else
assert( pCtx->pVdbe!=0 );
@ -943,7 +943,7 @@ void sqlite3_set_auxdata(
Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( pVdbe==0 ) goto failed;
#else
assert( pVdbe!=0 );

View File

@ -640,7 +640,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL)
|| (opcode==OP_ParseSchema && pOp->p4.z==0)
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@ -977,16 +977,16 @@ void sqlite3VdbeScanStatus(
** Change the value of the opcode, or P1, P2, P3, or P5 operands
** for a specific instruction.
*/
void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){
sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
}
void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p1 = val;
}
void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p2 = val;
}
void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
@ -1493,14 +1493,16 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
case P4_KEYINFO: {
int j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->aSortOrder!=0 );
assert( pKeyInfo->aSortFlags!=0 );
sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
for(j=0; j<pKeyInfo->nKeyField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "";
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
sqlite3_str_appendf(&x, ",%s%s",
pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
sqlite3_str_appendf(&x, ",%s%s%s",
(pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "",
(pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "",
zColl);
}
sqlite3_str_append(&x, ")", 1);
break;
@ -1907,8 +1909,11 @@ int sqlite3VdbeList(
** pick up the appropriate opcode. */
int j;
i -= p->nOp;
assert( apSub!=0 );
assert( nSub>0 );
for(j=0; i>=apSub[j]->nOp; j++){
i -= apSub[j]->nOp;
assert( i<apSub[j]->nOp || j+1<nSub );
}
pOp = &apSub[j]->aOp[i];
}
@ -3430,10 +3435,17 @@ int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
** of SQLite will not understand those serial types.
*/
#if 0 /* Inlined into the OP_MakeRecord opcode */
/*
** Return the serial-type for the value stored in pMem.
**
** This routine might convert a large MEM_IntReal value into MEM_Real.
**
** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord
** opcode in the byte-code engine. But by moving this routine in-line, we
** can omit some redundant tests and make that opcode a lot faster. So
** this routine is now only used by the STAT3 logic and STAT3 support has
** ended. The code is kept here for historical reference only.
*/
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
int flags = pMem->flags;
@ -3494,6 +3506,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
*pLen = n;
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
#endif /* inlined into OP_MakeRecord */
/*
** The sizes for serial types less than 128
@ -3802,7 +3815,7 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortOrder!=0 );
assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
@ -3901,7 +3914,7 @@ static int vdbeRecordCompareDebug(
if( szHdr1>98307 ) return SQLITE_CORRUPT;
d1 = szHdr1;
assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
assert( pKeyInfo->aSortOrder!=0 );
assert( pKeyInfo->aSortFlags!=0 );
assert( pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
@ -3932,7 +3945,12 @@ static int vdbeRecordCompareDebug(
pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0);
if( rc!=0 ){
assert( mem1.szMalloc==0 ); /* See comment below */
if( pKeyInfo->aSortOrder[i] ){
if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
&& ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null))
){
rc = -rc;
}
if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){
rc = -rc; /* Invert the result for DESC sort order. */
}
goto debugCompareEnd;
@ -4308,7 +4326,7 @@ int sqlite3VdbeRecordCompareWithSkip(
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
|| CORRUPT_DB );
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
assert( pPKey2->pKeyInfo->aSortFlags!=0 );
assert( pPKey2->pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
@ -4431,8 +4449,14 @@ int sqlite3VdbeRecordCompareWithSkip(
}
if( rc!=0 ){
if( pPKey2->pKeyInfo->aSortOrder[i] ){
rc = -rc;
int sortFlags = pPKey2->pKeyInfo->aSortFlags[i];
if( sortFlags ){
if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0
|| ((sortFlags & KEYINFO_ORDER_DESC)
!=(serial_type==0 || (pRhs->flags&MEM_Null)))
){
rc = -rc;
}
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
assert( mem1.szMalloc==0 ); /* See comment below */
@ -4600,7 +4624,11 @@ static int vdbeRecordCompareString(
nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
if( res==0 ){
if( res>0 ){
res = pPKey2->r2;
}else if( res<0 ){
res = pPKey2->r1;
}else{
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
@ -4614,10 +4642,6 @@ static int vdbeRecordCompareString(
}else{
res = pPKey2->r1;
}
}else if( res>0 ){
res = pPKey2->r2;
}else{
res = pPKey2->r1;
}
}
@ -4649,7 +4673,10 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** header size is (12*5 + 1 + 1) bytes. */
if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortOrder[0] ){
if( p->pKeyInfo->aSortFlags[0] ){
if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){
return sqlite3VdbeRecordCompare;
}
p->r1 = 1;
p->r2 = -1;
}else{
@ -4898,7 +4925,7 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
** features such as 'now'.
*/
int sqlite3NotPureFunc(sqlite3_context *pCtx){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 1;
#endif
if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
@ -4995,7 +5022,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.keyinfo.db = db;
preupdate.keyinfo.enc = ENC(db);
preupdate.keyinfo.nKeyField = pTab->nCol;
preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;

View File

@ -355,11 +355,12 @@ int sqlite3_blob_close(sqlite3_blob *pBlob){
sqlite3 *db;
if( p ){
sqlite3_stmt *pStmt = p->pStmt;
db = p->db;
sqlite3_mutex_enter(db->mutex);
rc = sqlite3_finalize(p->pStmt);
sqlite3DbFree(db, p);
sqlite3_mutex_leave(db->mutex);
rc = sqlite3_finalize(pStmt);
}else{
rc = SQLITE_OK;
}

View File

@ -232,7 +232,13 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
assert( pMem->szMalloc==0
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
}else{
pMem->zMalloc = sqlite3Realloc(pMem->z, n);
if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
pMem->z = pMem->zMalloc;
}
bPreserve = 0;
}else{
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
@ -1303,7 +1309,7 @@ struct ValueNewStat4Ctx {
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( p ){
UnpackedRecord *pRec = p->ppRec[0];
@ -1339,7 +1345,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
}
#else
UNUSED_PARAMETER(p);
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
#endif /* defined(SQLITE_ENABLE_STAT4) */
return sqlite3ValueNew(db);
}
@ -1363,7 +1369,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
** NULL and an SQLite error code returned.
*/
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
static int valueFromFunction(
sqlite3 *db, /* The database connection */
Expr *p, /* The expression to evaluate */
@ -1446,7 +1452,7 @@ static int valueFromFunction(
}
#else
# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
#endif /* defined(SQLITE_ENABLE_STAT4) */
/*
** Extract a value from the supplied expression in the manner described
@ -1475,7 +1481,7 @@ static int valueFromExpr(
assert( pExpr!=0 );
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
#if defined(SQLITE_ENABLE_STAT4)
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
@ -1568,7 +1574,7 @@ static int valueFromExpr(
0, SQLITE_DYNAMIC);
}
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
else if( op==TK_FUNCTION && pCtx!=0 ){
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
}
@ -1585,13 +1591,13 @@ static int valueFromExpr(
return rc;
no_mem:
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( pCtx==0 || pCtx->pParse->nErr==0 )
#endif
sqlite3OomFault(db);
sqlite3DbFree(db, zVal);
assert( *ppVal==0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
if( pCtx==0 ) sqlite3ValueFree(pVal);
#else
assert( pCtx==0 ); sqlite3ValueFree(pVal);
@ -1619,56 +1625,7 @@ int sqlite3ValueFromExpr(
return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** The implementation of the sqlite_record() function. This function accepts
** a single argument of any type. The return value is a formatted database
** record (a blob) containing the argument value.
**
** This is used to convert the value stored in the 'sample' column of the
** sqlite_stat3 table to the record format SQLite uses internally.
*/
static void recordFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const int file_format = 1;
u32 iSerial; /* Serial type */
int nSerial; /* Bytes of space for iSerial as varint */
u32 nVal; /* Bytes of space required for argv[0] */
int nRet;
sqlite3 *db;
u8 *aRet;
UNUSED_PARAMETER( argc );
iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
nSerial = sqlite3VarintLen(iSerial);
db = sqlite3_context_db_handle(context);
nRet = 1 + nSerial + nVal;
aRet = sqlite3DbMallocRawNN(db, nRet);
if( aRet==0 ){
sqlite3_result_error_nomem(context);
}else{
aRet[0] = nSerial+1;
putVarint32(&aRet[1], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
sqlite3DbFreeNN(db, aRet);
}
}
/*
** Register built-in functions used to help read ANALYZE data.
*/
void sqlite3AnalyzeFunctions(void){
static FuncDef aAnalyzeTableFuncs[] = {
FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
};
sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
}
#ifdef SQLITE_ENABLE_STAT4
/*
** Attempt to extract a value from pExpr and use it to construct *ppVal.
**

View File

@ -829,7 +829,8 @@ static int vdbeSorterCompareText(
);
}
}else{
if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
res = res * -1;
}
}
@ -897,7 +898,8 @@ static int vdbeSorterCompareInt(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
}
}else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
}else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
res = res * -1;
}
@ -1012,6 +1014,7 @@ int sqlite3VdbeSorterInit(
if( pKeyInfo->nAllField<13
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
&& (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0
){
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
}
@ -1728,13 +1731,16 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){
rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
}else{
/* Launch a background thread for this operation */
u8 *aMem = pTask->list.aMemory;
void *pCtx = (void*)pTask;
u8 *aMem;
void *pCtx;
assert( pTask!=0 );
assert( pTask->pThread==0 && pTask->bDone==0 );
assert( pTask->list.pList==0 );
assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );
aMem = pTask->list.aMemory;
pCtx = (void*)pTask;
pSorter->iPrev = (u8)(pTask - pSorter->aTask);
pTask->list = pSorter->list;
pSorter->list.pList = 0;

View File

@ -32,6 +32,9 @@ struct VtabCtx {
** Construct and install a Module object for a virtual table. When this
** routine is called, it is guaranteed that all appropriate locks are held
** and the module is not already part of the connection.
**
** If there already exists a module with zName, replace it with the new one.
** If pModule==0, then delete the module zName if it exists.
*/
Module *sqlite3VtabCreateModule(
sqlite3 *db, /* Database in which module is registered */
@ -41,25 +44,36 @@ Module *sqlite3VtabCreateModule(
void (*xDestroy)(void *) /* Module destructor function */
){
Module *pMod;
int nName = sqlite3Strlen30(zName);
pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
if( pMod==0 ){
sqlite3OomFault(db);
Module *pDel;
char *zCopy;
if( pModule==0 ){
zCopy = (char*)zName;
pMod = 0;
}else{
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
int nName = sqlite3Strlen30(zName);
pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
if( pMod==0 ){
sqlite3OomFault(db);
return 0;
}
zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
pMod->zName = zCopy;
pMod->pModule = pModule;
pMod->pAux = pAux;
pMod->xDestroy = xDestroy;
pMod->pEpoTab = 0;
pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
assert( pDel==0 || pDel==pMod );
if( pDel ){
pMod->nRefModule = 1;
}
pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
if( pDel ){
if( pDel==pMod ){
sqlite3OomFault(db);
sqlite3DbFree(db, pDel);
pMod = 0;
}else{
sqlite3VtabEponymousTableClear(db, pDel);
sqlite3VtabModuleUnref(db, pDel);
}
}
return pMod;
@ -80,11 +94,7 @@ static int createModule(
int rc = SQLITE_OK;
sqlite3_mutex_enter(db->mutex);
if( sqlite3HashFind(&db->aModule, zName) ){
rc = SQLITE_MISUSE_BKPT;
}else{
(void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
}
(void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
sqlite3_mutex_leave(db->mutex);
@ -123,6 +133,44 @@ int sqlite3_create_module_v2(
return createModule(db, zName, pModule, pAux, xDestroy);
}
/*
** External API to drop all virtual-table modules, except those named
** on the azNames list.
*/
int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
HashElem *pThis, *pNext;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){
Module *pMod = (Module*)sqliteHashData(pThis);
pNext = sqliteHashNext(pThis);
if( azNames ){
int ii;
for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){}
if( azNames[ii]!=0 ) continue;
}
createModule(db, pMod->zName, 0, 0, 0);
}
return SQLITE_OK;
}
/*
** Decrement the reference count on a Module object. Destroy the
** module when the reference count reaches zero.
*/
void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){
assert( pMod->nRefModule>0 );
pMod->nRefModule--;
if( pMod->nRefModule==0 ){
if( pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
assert( pMod->pEpoTab==0 );
sqlite3DbFree(db, pMod);
}
}
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
@ -162,6 +210,7 @@ void sqlite3VtabUnlock(VTable *pVTab){
pVTab->nRef--;
if( pVTab->nRef==0 ){
sqlite3_vtab *p = pVTab->pVtab;
sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod);
if( p ){
p->pModule->xDisconnect(p);
}
@ -566,6 +615,7 @@ static int vtabCallConstructor(
** the sqlite3_vtab object if successful. */
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
pVTable->pVtab->pModule = pMod->pModule;
pMod->nRefModule++;
pVTable->nRef = 1;
if( sCtx.bDeclared==0 ){
const char *zFormat = "vtable constructor did not declare schema: %s";

View File

@ -3478,6 +3478,7 @@ int sqlite3WalFrames(
if( rc ) return rc;
iOffset += szFrame;
nExtra++;
assert( pLast!=0 );
}
}
if( bSync ){
@ -3510,6 +3511,7 @@ int sqlite3WalFrames(
iFrame++;
rc = walIndexAppend(pWal, iFrame, p->pgno);
}
assert( pLast!=0 || nExtra==0 );
while( rc==SQLITE_OK && nExtra>0 ){
iFrame++;
nExtra--;

View File

@ -25,9 +25,22 @@
static int walkWindowList(Walker *pWalker, Window *pList){
Window *pWin;
for(pWin=pList; pWin; pWin=pWin->pNextWin){
if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
int rc;
rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
/* The next two are purely for calls to sqlite3RenameExprUnmap()
** within sqlite3WindowOffsetExpr(). Because of constraints imposed
** by sqlite3WindowOffsetExpr(), they can never fail. The results do
** not matter anyhow. */
rc = sqlite3WalkExpr(pWalker, pWin->pStart);
if( NEVER(rc) ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
if( NEVER(rc) ) return WRC_Abort;
}
return WRC_Continue;
}
@ -63,18 +76,22 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pRight ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
pExpr = pExpr->pRight;
continue;
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
}else if( pExpr->x.pList ){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
}else{
if( pExpr->x.pList ){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
}
#endif
}
}
break;
}
@ -116,8 +133,9 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
{
Parse *pParse = pWalker->pParse;
if( pParse && IN_RENAME_OBJECT ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
int rc = walkWindowList(pWalker, p->pWinDefn);
assert( rc==WRC_Continue );
return rc;
}
}

View File

@ -253,7 +253,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
&& (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
&& (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op
==TK_COLUMN
){
int j;
for(j=0; j<pScan->nEquiv; j++){
@ -449,7 +450,7 @@ static int findIndexCol(
const char *zColl = pIdx->azColl[iCol];
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( p->op==TK_COLUMN
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
@ -513,7 +514,7 @@ static int isDistinctRedundant(
** current SELECT is a correlated sub-query.
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
}
@ -933,6 +934,7 @@ static sqlite3_index_info *allocateIndexInfo(
for(i=0; i<n; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break;
}
if( i==n){
nOrderBy = n;
@ -1031,7 +1033,7 @@ static sqlite3_index_info *allocateIndexInfo(
for(i=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
pIdxOrderBy[i].iColumn = pExpr->iColumn;
pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC;
}
*pmNoOmit = mNoOmit;
@ -1077,7 +1079,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the location of a particular key among all keys in an
** index. Store the results in aStat as follows:
@ -1270,7 +1272,7 @@ static int whereKeyStats(
pRec->nField = nField;
return i;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/*
** If it is not NULL, pTerm is a term that provides an upper or lower
@ -1296,7 +1298,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Return the affinity for a single column of an index.
*/
@ -1305,12 +1307,13 @@ char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
if( !pIdx->zColAff ){
if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
}
assert( pIdx->zColAff[iCol]!=0 );
return pIdx->zColAff[iCol];
}
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** This function is called to estimate the number of rows visited by a
** range-scan on a skip-scan index. For example:
@ -1416,7 +1419,7 @@ static int whereRangeSkipScanEst(
return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/*
** This function is used to estimate the number of rows that will be visited
@ -1469,12 +1472,12 @@ static int whereRangeScanEst(
int nOut = pLoop->nOut;
LogEst nNew;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
Index *p = pLoop->u.btree.pIndex;
int nEq = pLoop->u.btree.nEq;
if( p->nSample>0 && nEq<p->nSampleCol
&& OptimizationEnabled(pParse->db, SQLITE_Stat34)
if( p->nSample>0 && ALWAYS(nEq<p->nSampleCol)
&& OptimizationEnabled(pParse->db, SQLITE_Stat4)
){
if( nEq==pBuilder->nRecValid ){
UnpackedRecord *pRec = pBuilder->pRec;
@ -1572,7 +1575,7 @@ static int whereRangeScanEst(
/* TUNING: If both iUpper and iLower are derived from the same
** sample, then assume they are 4x more selective. This brings
** the estimated selectivity more in line with what it would be
** if estimated without the use of STAT3/4 tables. */
** if estimated without the use of STAT4 tables. */
if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) );
}else{
nNew = 10; assert( 10==sqlite3LogEst(2) );
@ -1621,12 +1624,12 @@ static int whereRangeScanEst(
return rc;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data. This only works when x is the left-most
** column of an index and sqlite_stat3 histogram data is available
** column of an index and sqlite_stat4 histogram data is available
** for that index. When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
@ -1684,9 +1687,9 @@ static int whereEqualScanEst(
return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
@ -1733,7 +1736,7 @@ static int whereInScanEst(
assert( pBuilder->nRecValid==nRecValid );
return rc;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
#ifdef WHERETRACE_ENABLED
@ -2265,11 +2268,12 @@ static void whereLoopOutputAdjust(
){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j, k;
int i, j;
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
assert( pTerm!=0 );
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
@ -2290,6 +2294,7 @@ static void whereLoopOutputAdjust(
pLoop->nOut--;
if( pTerm->eOperator&(WO_EQ|WO_IS) ){
Expr *pRight = pTerm->pExpr->pRight;
int k = 0;
testcase( pTerm->pExpr->op==TK_IS );
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
k = 10;
@ -2453,7 +2458,7 @@ static int whereLoopAddBtreeIndex(
LogEst rCostIdx;
LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */
int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
int nRecValid = pBuilder->nRecValid;
#endif
if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
@ -2514,8 +2519,6 @@ static int whereLoopAddBtreeIndex(
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
** changes "x IN (?)" into "x=?". */
}
if( pProbe->hasStat1 ){
LogEst M, logK, safetyMargin;
@ -2611,7 +2614,7 @@ static int whereLoopAddBtreeIndex(
** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */
assert( pNew->nOut==saved_nOut );
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
/* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4
/* Adjust nOut using stat4 data. Or, if there is no stat4
** data, using some other estimate. */
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
}else{
@ -2625,13 +2628,13 @@ static int whereLoopAddBtreeIndex(
pNew->nOut += pTerm->truthProb;
pNew->nOut -= nIn;
}else{
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
tRowcnt nOut = 0;
if( nInMul==0
&& pProbe->nSample
&& pNew->u.btree.nEq<=pProbe->nSampleCol
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
&& OptimizationEnabled(db, SQLITE_Stat34)
&& OptimizationEnabled(db, SQLITE_Stat4)
){
Expr *pExpr = pTerm->pExpr;
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
@ -2668,6 +2671,7 @@ static int whereLoopAddBtreeIndex(
** it to pNew->rRun, which is currently set to the cost of the index
** seek only. Then, if this is a non-covering index, add the cost of
** visiting the rows in the main table. */
assert( pSrc->pTab->szTabRow>0 );
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
@ -2693,7 +2697,7 @@ static int whereLoopAddBtreeIndex(
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
pBuilder->nRecValid = nRecValid;
#endif
}
@ -2766,7 +2770,7 @@ static int indexMightHelpWithOrderBy(
if( pIndex->bUnordered ) return 0;
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
for(ii=0; ii<pOB->nExpr; ii++){
Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
if( pExpr->iColumn<0 ) return 1;
for(jj=0; jj<pIndex->nKeyCol; jj++){
@ -2797,7 +2801,9 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
}
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr = pTerm->pExpr;
Expr *pExpr;
if( pTerm->wtFlags & TERM_NOPARTIDX ) continue;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
){
@ -3066,7 +3072,7 @@ static int whereLoopAddBtree(
** plan */
pTab->tabFlags |= TF_StatsUsed;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
sqlite3Stat4ProbeFree(pBuilder->pRec);
pBuilder->nRecValid = 0;
pBuilder->pRec = 0;
@ -3694,8 +3700,8 @@ static i8 wherePathSatisfiesOrderBy(
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
if( pLoop->u.vtab.isOrdered ) obSat = obDone;
break;
}else{
pLoop->u.btree.nIdxCol = 0;
}else if( wctrlFlags & WHERE_DISTINCTBY ){
pLoop->u.btree.nDistinctCol = 0;
}
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
@ -3706,7 +3712,7 @@ static i8 wherePathSatisfiesOrderBy(
*/
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
@ -3743,7 +3749,8 @@ static i8 wherePathSatisfiesOrderBy(
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
isOrderDistinct = IsUniqueIndex(pIndex);
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
/* Loop through all columns of the index and deal with the ones
@ -3761,15 +3768,21 @@ static i8 wherePathSatisfiesOrderBy(
u16 eOp = pLoop->aLTerm[j]->eOperator;
/* Skip over == and IS and ISNULL terms. (Also skip IN terms when
** doing WHERE_ORDERBY_LIMIT processing).
** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL
** terms imply that the index is not UNIQUE NOT NULL in which case
** the loop need to be marked as not order-distinct because it can
** have repeated NULL rows.
**
** If the current term is a column of an ((?,?) IN (SELECT...))
** expression for which the SELECT returns more than one column,
** check that it is the only column used by this loop. Otherwise,
** if it is one of two or more, none of the columns can be
** considered to match an ORDER BY term. */
** considered to match an ORDER BY term.
*/
if( (eOp & eqOpMask)!=0 ){
if( eOp & WO_ISNULL ){
if( eOp & (WO_ISNULL|WO_IS) ){
testcase( eOp & WO_ISNULL );
testcase( eOp & WO_IS );
testcase( isOrderDistinct );
isOrderDistinct = 0;
}
@ -3795,7 +3808,7 @@ static i8 wherePathSatisfiesOrderBy(
*/
if( pIndex ){
iColumn = pIndex->aiColumn[j];
revIdx = pIndex->aSortOrder[j];
revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC;
if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
}else{
iColumn = XN_ROWID;
@ -3819,7 +3832,7 @@ static i8 wherePathSatisfiesOrderBy(
isMatch = 0;
for(i=0; bOnce && i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
@ -3837,7 +3850,9 @@ static i8 wherePathSatisfiesOrderBy(
pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
pLoop->u.btree.nIdxCol = j+1;
if( wctrlFlags & WHERE_DISTINCTBY ){
pLoop->u.btree.nDistinctCol = j+1;
}
isMatch = 1;
break;
}
@ -3845,13 +3860,22 @@ static i8 wherePathSatisfiesOrderBy(
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if( revSet ){
if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
if( (rev ^ revIdx)!=(pOrderBy->a[i].sortFlags&KEYINFO_ORDER_DESC) ){
isMatch = 0;
}
}else{
rev = revIdx ^ pOrderBy->a[i].sortOrder;
rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC);
if( rev ) *pRevMask |= MASKBIT(iLoop);
revSet = 1;
}
}
if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){
if( j==pLoop->u.btree.nEq ){
pLoop->wsFlags |= WHERE_BIGNULL_SORT;
}else{
isMatch = 0;
}
}
if( isMatch ){
if( iColumn==XN_ROWID ){
testcase( distinctColumns==0 );
@ -4765,6 +4789,16 @@ WhereInfo *sqlite3WhereBegin(
sqlite3DebugPrintf(", limit: %d", iAuxArg);
}
sqlite3DebugPrintf(")\n");
if( sqlite3WhereTrace & 0x100 ){
Select sSelect;
memset(&sSelect, 0, sizeof(sSelect));
sSelect.selFlags = SF_WhereBegin;
sSelect.pSrc = pTabList;
sSelect.pWhere = pWhere;
sSelect.pOrderBy = pOrderBy;
sSelect.pEList = pResultSet;
sqlite3TreeViewSelect(0, &sSelect, 0);
}
}
if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
sqlite3WhereClausePrint(sWLB.pWC);
@ -5041,6 +5075,7 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
){
@ -5158,7 +5193,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
&& i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */
&& (pLoop->wsFlags & WHERE_INDEXED)!=0
&& (pIdx = pLoop->u.btree.pIndex)->hasStat1
&& (n = pLoop->u.btree.nIdxCol)>0
&& (n = pLoop->u.btree.nDistinctCol)>0
&& pIdx->aiRowLogEst[n]>=36
){
int r1 = pParse->nMem+1;
@ -5182,6 +5217,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeCoverageIf(v, pLevel->op==OP_Next);
VdbeCoverageIf(v, pLevel->op==OP_Prev);
VdbeCoverageIf(v, pLevel->op==OP_VNext);
if( pLevel->regBignull ){
sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
VdbeCoverage(v);
}
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif

View File

@ -71,13 +71,15 @@ struct WhereLevel {
int addrCont; /* Jump here to continue with the next loop cycle */
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
@ -128,7 +130,7 @@ struct WhereLoop {
u16 nEq; /* Number of equality constraints */
u16 nBtm; /* Size of BTM vector */
u16 nTop; /* Size of TOP vector */
u16 nIdxCol; /* Index column used for ORDER BY */
u16 nDistinctCol; /* Index columns used to sort for DISTINCT */
Index *pIndex; /* Index used, or NULL */
} btree;
struct { /* Information for virtual tables */
@ -279,16 +281,17 @@ struct WhereTerm {
#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
#else
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
# define TERM_VNULL 0x00 /* Disabled if not using stat4 */
#endif
#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
#define TERM_NOPARTIDX 0x2000 /* Not for use to enable a partial index */
/*
** An instance of the WhereScan object is used as an iterator for locating
@ -399,7 +402,7 @@ struct WhereLoopBuilder {
ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#ifdef SQLITE_ENABLE_STAT4
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
int nRecValid; /* Number of valid fields currently in pRec */
#endif
@ -586,5 +589,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
#endif /* !defined(SQLITE_WHEREINT_H) */

View File

@ -318,9 +318,9 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
** Code an OP_Affinity opcode to apply the column affinity string zAff
** to the n registers starting at base.
**
** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the
** beginning and end of zAff are ignored. If all entries in zAff are
** SQLITE_AFF_BLOB, then no code gets generated.
** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which
** are no-ops) at the beginning and end of zAff are ignored. If all entries
** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated.
**
** This routine makes its own copy of zAff so that the caller is free
** to modify zAff after this routine returns.
@ -333,15 +333,16 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
}
assert( v!=0 );
/* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning
** and end of the affinity string.
/* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE
** entries at the beginning and end of the affinity string.
*/
while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
assert( SQLITE_AFF_NONE<SQLITE_AFF_BLOB );
while( n>0 && zAff[0]<=SQLITE_AFF_BLOB ){
n--;
base++;
zAff++;
}
while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){
n--;
}
@ -1116,6 +1117,7 @@ typedef struct IdxExprTrans {
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
@ -1548,32 +1550,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
int omitTable; /* True if we use the index only */
int regBignull = 0; /* big-null flag register */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
assert( nEq>=pLoop->nSkip );
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
** a single iteration. This means that the first row returned
** should not have a NULL value stored in 'x'. If column 'x' is
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
assert( pWInfo->pOrderBy==0
|| pWInfo->pOrderBy->nExpr==1
|| (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
&& pWInfo->nOBSat>0
&& (pIdx->nKeyCol>nEq)
){
assert( pLoop->nSkip==0 );
bSeekPastNull = 1;
nExtraReg = 1;
}
/* Find any inequality constraint terms for the start and end
** of the range.
*/
@ -1614,6 +1596,25 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
/* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses
** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS
** FIRST). In both cases separate ordered scans are made of those
** index entries for which the column is null and for those for which
** it is not. For an ASC sort, the non-NULL entries are scanned first.
** For DESC, NULL entries are scanned first.
*/
if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0
){
assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
assert( pRangeEnd==0 && pRangeStart==0 );
assert( pLoop->nSkip==0 );
nExtraReg = 1;
bSeekPastNull = 1;
pLevel->regBignull = regBignull = ++pParse->nMem;
pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
}
/* If we are doing a reverse order scan on an ascending index, or
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
@ -1636,7 +1637,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( zStartAff && nTop ){
zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]);
}
addrNxt = pLevel->addrNxt;
addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt);
testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
@ -1670,10 +1671,14 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
bSeekPastNull = 0;
}else if( bSeekPastNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
nConstraint++;
startEq = 0;
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
start_constraints = 1;
nConstraint++;
}else if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
start_constraints = 1;
nConstraint++;
}
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
@ -1684,6 +1689,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
}
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
}
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
@ -1694,6 +1704,23 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
assert( bSeekPastNull==0 || bStopAtNull==0 );
if( regBignull ){
assert( bSeekPastNull==1 || bStopAtNull==1 );
assert( bSeekPastNull==!bStopAtNull );
assert( bStopAtNull==startEq );
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
op = aStartOp[(nConstraint>1)*4 + 2 + bRev];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
nConstraint-startEq);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE);
}
}
/* Load the value for the inequality constraint at the end of the
@ -1725,8 +1752,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
endEq = 1;
}
}else if( bStopAtNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
endEq = 0;
if( regBignull==0 ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
endEq = 0;
}
nConstraint++;
}
sqlite3DbFree(db, zStartAff);
@ -1737,6 +1766,12 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* Check if the index cursor is past the end of the range. */
if( nConstraint ){
if( regBignull ){
/* Except, skip the end-of-range check while doing the NULL-scan */
sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
VdbeComment((v, "If NULL-scan 2nd pass"));
VdbeCoverage(v);
}
op = aEndOp[bRev*2 + endEq];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
@ -1744,6 +1779,23 @@ Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
if( regBignull ){
/* During a NULL-scan, check to see if we have reached the end of
** the NULLs */
assert( bSeekPastNull==!bStopAtNull );
assert( bSeekPastNull+bStopAtNull==1 );
assert( nConstraint+bSeekPastNull>0 );
sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2);
VdbeComment((v, "If NULL-scan 1st pass"));
VdbeCoverage(v);
op = aEndOp[bRev*2 + bSeekPastNull];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
nConstraint+bSeekPastNull);
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);

View File

@ -84,7 +84,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
}else{
pTerm->truthProb = 1;
}
pTerm->pExpr = sqlite3ExprSkipCollate(p);
pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p);
pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC;
pTerm->iParent = -1;
@ -117,10 +117,16 @@ static int allowedOp(int op){
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
**
** The return value is extra flags that are added to the WhereTerm object
** after it is commuted. The only extra flag ever added is TERM_NOPARTIDX
** which prevents the term from being used to enable a partial index if
** COLLATE changes have been made.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
static u16 exprCommute(Parse *pParse, Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_Collate);
u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
u16 wtFlags = 0;
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
if( expRight==expLeft ){
/* Either X and Y both have COLLATE operator or neither do */
@ -128,11 +134,13 @@ static void exprCommute(Parse *pParse, Expr *pExpr){
/* Both X and Y have COLLATE operators. Make sure X is always
** used by clearing the EP_Collate flag from Y. */
pExpr->pRight->flags &= ~EP_Collate;
wtFlags |= TERM_NOPARTIDX;
}else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
/* Neither X nor Y have COLLATE operators, but X has a non-default
** collating sequence. So add the EP_Collate marker on X to cause
** it to be searched first. */
pExpr->pLeft->flags |= EP_Collate;
wtFlags |= TERM_NOPARTIDX;
}
}
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
@ -144,6 +152,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){
assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
}
return wtFlags;
}
/*
@ -275,6 +284,7 @@ static int isLikeOrGlob(
** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
*/
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
@ -284,9 +294,13 @@ static int isLikeOrGlob(
double rDummy;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
if( isNum<=0 ){
zNew[iTo-1]++;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
zNew[iTo-1]--;
if( iTo==1 && zNew[0]=='-' ){
isNum = +1;
}else{
zNew[iTo-1]++;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
zNew[iTo-1]--;
}
}
if( isNum>0 ){
sqlite3ExprDelete(db, pPrefix);
@ -1140,7 +1154,7 @@ static void exprAnalyze(
pDup = pExpr;
pNew = pTerm;
}
exprCommute(pParse, pDup);
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
pNew->u.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
@ -1381,8 +1395,8 @@ static void exprAnalyze(
}
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/* When sqlite_stat3 histogram data is available an operator of the
#ifdef SQLITE_ENABLE_STAT4
/* When sqlite_stat4 histogram data is available an operator of the
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
@ -1393,7 +1407,7 @@ static void exprAnalyze(
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
&& !ExprHasProperty(pExpr, EP_FromJoin)
&& OptimizationEnabled(db, SQLITE_Stat34)
&& OptimizationEnabled(db, SQLITE_Stat4)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
@ -1418,7 +1432,7 @@ static void exprAnalyze(
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#endif /* SQLITE_ENABLE_STAT4 */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@ -1451,7 +1465,7 @@ static void exprAnalyze(
** all terms of the WHERE clause.
*/
void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
pWC->op = op;
if( pE2==0 ) return;
if( pE2->op!=op ){

View File

@ -748,6 +748,8 @@ struct WindowRewrite {
static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
struct WindowRewrite *p = pWalker->u.pRewrite;
Parse *pParse = pWalker->pParse;
assert( p!=0 );
assert( p->pWin!=0 );
/* If this function is being called from within a scalar sub-select
** that used by the SELECT statement being processed, only process
@ -847,6 +849,7 @@ static void selectWindowRewriteEList(
Walker sWalker;
WindowRewrite sRewrite;
assert( pWin!=0 );
memset(&sWalker, 0, sizeof(Walker));
memset(&sRewrite, 0, sizeof(WindowRewrite));
@ -885,7 +888,7 @@ static ExprList *exprListAppendList(
pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder;
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
}
}
return pList;
@ -931,11 +934,14 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
** redundant, remove the ORDER BY from the parent SELECT. */
pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
if( pSort && p->pOrderBy ){
if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
int nSave = pSort->nExpr;
pSort->nExpr = p->pOrderBy->nExpr;
if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
}
pSort->nExpr = nSave;
}
/* Assign a cursor number for the ephemeral table used to buffer rows.
@ -959,8 +965,15 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
** window function - one for the accumulator, another for interim
** results. */
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList, 0);
ExprList *pArgs = pWin->pOwner->x.pList;
if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pWin->bExprArgs = 1;
}else{
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pSublist = exprListAppendList(pParse, pSublist, pArgs, 0);
}
if( pWin->pFilter ){
Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
@ -978,7 +991,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
*/
if( pSublist==0 ){
pSublist = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0)
sqlite3Expr(db, TK_INTEGER, "0")
);
}
@ -991,7 +1004,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub);
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
if( pTab2==0 ){
rc = SQLITE_NOMEM;
}else{
@ -1014,11 +1027,24 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
return rc;
}
/*
** Unlink the Window object from the Select to which it is attached,
** if it is attached.
*/
void sqlite3WindowUnlinkFromSelect(Window *p){
if( p->ppThis ){
*p->ppThis = p->pNextWin;
if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis;
p->ppThis = 0;
}
}
/*
** Free the Window object passed as the second argument.
*/
void sqlite3WindowDelete(sqlite3 *db, Window *p){
if( p ){
sqlite3WindowUnlinkFromSelect(p);
sqlite3ExprDelete(db, p->pFilter);
sqlite3ExprListDelete(db, p->pPartition);
sqlite3ExprListDelete(db, p->pOrderBy);
@ -1196,28 +1222,44 @@ void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
if( p ){
assert( p->op==TK_FUNCTION );
/* This routine is only called for the parser. If pWin was not
** allocated due to an OOM, then the parser would fail before ever
** invoking this routine */
if( ALWAYS(pWin) ){
p->y.pWin = pWin;
ExprSetProperty(p, EP_WinFunc);
pWin->pOwner = p;
if( p->flags & EP_Distinct ){
sqlite3ErrorMsg(pParse,
"DISTINCT is not supported for window functions");
}
assert( pWin );
p->y.pWin = pWin;
ExprSetProperty(p, EP_WinFunc);
pWin->pOwner = p;
if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){
sqlite3ErrorMsg(pParse,
"DISTINCT is not supported for window functions"
);
}
}else{
sqlite3WindowDelete(pParse->db, pWin);
}
}
/*
** Possibly link window pWin into the list at pSel->pWin (window functions
** to be processed as part of SELECT statement pSel). The window is linked
** in if either (a) there are no other windows already linked to this
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
void sqlite3WindowLink(Select *pSel, Window *pWin){
if( 0==pSel->pWin
|| 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0)
){
pWin->pNextWin = pSel->pWin;
if( pSel->pWin ){
pSel->pWin->ppThis = &pWin->pNextWin;
}
pSel->pWin = pWin;
pWin->ppThis = &pSel->pWin;
}
}
/*
** Return 0 if the two window objects are identical, or non-zero otherwise.
** Identical window objects can be processed in a single scan.
*/
int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
if( p1->eFrmType!=p2->eFrmType ) return 1;
if( p1->eStart!=p2->eStart ) return 1;
if( p1->eEnd!=p2->eEnd ) return 1;
@ -1226,6 +1268,9 @@ int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
if( bFilter ){
if( sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1) ) return 1;
}
return 0;
}
@ -1277,8 +1322,8 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
pWin->regApp = pParse->nMem+1;
pParse->nMem += 3;
if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
assert( pKeyInfo->aSortOrder[0]==0 );
pKeyInfo->aSortOrder[0] = 1;
assert( pKeyInfo->aSortFlags[0]==0 );
pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
}
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2);
sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
@ -1363,6 +1408,108 @@ static int windowArgCount(Window *pWin){
return (pList ? pList->nExpr : 0);
}
typedef struct WindowCodeArg WindowCodeArg;
typedef struct WindowCsrAndReg WindowCsrAndReg;
/*
** See comments above struct WindowCodeArg.
*/
struct WindowCsrAndReg {
int csr; /* Cursor number */
int reg; /* First in array of peer values */
};
/*
** A single instance of this structure is allocated on the stack by
** sqlite3WindowCodeStep() and a pointer to it passed to the various helper
** routines. This is to reduce the number of arguments required by each
** helper function.
**
** regArg:
** Each window function requires an accumulator register (just as an
** ordinary aggregate function does). This variable is set to the first
** in an array of accumulator registers - one for each window function
** in the WindowCodeArg.pMWin list.
**
** eDelete:
** The window functions implementation sometimes caches the input rows
** that it processes in a temporary table. If it is not zero, this
** variable indicates when rows may be removed from the temp table (in
** order to reduce memory requirements - it would always be safe just
** to leave them there). Possible values for eDelete are:
**
** WINDOW_RETURN_ROW:
** An input row can be discarded after it is returned to the caller.
**
** WINDOW_AGGINVERSE:
** An input row can be discarded after the window functions xInverse()
** callbacks have been invoked in it.
**
** WINDOW_AGGSTEP:
** An input row can be discarded after the window functions xStep()
** callbacks have been invoked in it.
**
** start,current,end
** Consider a window-frame similar to the following:
**
** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING)
**
** The windows functions implmentation caches the input rows in a temp
** table, sorted by "a, b" (it actually populates the cache lazily, and
** aggressively removes rows once they are no longer required, but that's
** a mere detail). It keeps three cursors open on the temp table. One
** (current) that points to the next row to return to the query engine
** once its window function values have been calculated. Another (end)
** points to the next row to call the xStep() method of each window function
** on (so that it is 2 groups ahead of current). And a third (start) that
** points to the next row to call the xInverse() method of each window
** function on.
**
** Each cursor (start, current and end) consists of a VDBE cursor
** (WindowCsrAndReg.csr) and an array of registers (starting at
** WindowCodeArg.reg) that always contains a copy of the peer values
** read from the corresponding cursor.
**
** Depending on the window-frame in question, all three cursors may not
** be required. In this case both WindowCodeArg.csr and reg are set to
** 0.
*/
struct WindowCodeArg {
Parse *pParse; /* Parse context */
Window *pMWin; /* First in list of functions being processed */
Vdbe *pVdbe; /* VDBE object */
int addrGosub; /* OP_Gosub to this address to return one row */
int regGosub; /* Register used with OP_Gosub(addrGosub) */
int regArg; /* First in array of accumulator registers */
int eDelete; /* See above */
WindowCsrAndReg start;
WindowCsrAndReg current;
WindowCsrAndReg end;
};
/*
** Generate VM code to read the window frames peer values from cursor csr into
** an array of registers starting at reg.
*/
static void windowReadPeerValues(
WindowCodeArg *p,
int csr,
int reg
){
Window *pMWin = p->pMWin;
ExprList *pOrderBy = pMWin->pOrderBy;
if( pOrderBy ){
Vdbe *v = sqlite3GetVdbe(p->pParse);
ExprList *pPart = pMWin->pPartition;
int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
int i;
for(i=0; i<pOrderBy->nExpr; i++){
sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
}
}
}
/*
** Generate VM code to invoke either xStep() (if bInverse is 0) or
** xInverse (if bInverse is non-zero) for each window function in the
@ -1383,20 +1530,27 @@ static int windowArgCount(Window *pWin){
** number of rows in the current partition.
*/
static void windowAggStep(
Parse *pParse,
WindowCodeArg *p,
Window *pMWin, /* Linked list of window functions */
int csr, /* Read arguments from this cursor */
int bInverse, /* True to invoke xInverse instead of xStep */
int reg /* Array of registers */
){
Parse *pParse = p->pParse;
Vdbe *v = sqlite3GetVdbe(pParse);
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pFunc;
int regArg;
int nArg = windowArgCount(pWin);
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
int i;
assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
/* All OVER clauses in the same window function aggregate step must
** be the same. */
assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)==0 );
for(i=0; i<nArg; i++){
if( i!=1 || pFunc->zName!=nth_valueName ){
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
@ -1434,14 +1588,30 @@ static void windowAggStep(
int addrIf = 0;
if( pWin->pFilter ){
int regTmp;
assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr );
assert( nArg || pWin->pOwner->x.pList==0 );
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
regTmp = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regTmp);
}
if( pWin->bExprArgs ){
int iStart = sqlite3VdbeCurrentAddr(v);
VdbeOp *pOp, *pEnd;
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
pEnd = sqlite3VdbeGetOp(v, -1);
for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
pOp->p1 = csr;
}
}
}
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
assert( nArg>0 );
@ -1452,32 +1622,14 @@ static void windowAggStep(
bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
if( pWin->bExprArgs ){
sqlite3ReleaseTempRange(pParse, regArg, nArg);
}
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
}
}
typedef struct WindowCodeArg WindowCodeArg;
typedef struct WindowCsrAndReg WindowCsrAndReg;
struct WindowCsrAndReg {
int csr;
int reg;
};
struct WindowCodeArg {
Parse *pParse;
Window *pMWin;
Vdbe *pVdbe;
int regGosub;
int addrGosub;
int regArg;
int eDelete;
WindowCsrAndReg start;
WindowCsrAndReg current;
WindowCsrAndReg end;
};
/*
** Values that may be passed as the second argument to windowCodeOp().
*/
@ -1485,28 +1637,6 @@ struct WindowCodeArg {
#define WINDOW_AGGINVERSE 2
#define WINDOW_AGGSTEP 3
/*
** Generate VM code to read the window frames peer values from cursor csr into
** an array of registers starting at reg.
*/
static void windowReadPeerValues(
WindowCodeArg *p,
int csr,
int reg
){
Window *pMWin = p->pMWin;
ExprList *pOrderBy = pMWin->pOrderBy;
if( pOrderBy ){
Vdbe *v = sqlite3GetVdbe(p->pParse);
ExprList *pPart = pMWin->pPartition;
int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
int i;
for(i=0; i<pOrderBy->nExpr; i++){
sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
}
}
}
/*
** Generate VM code to invoke either xValue() (bFin==0) or xFinalize()
** (bFin==1) for each window function in the linked list starting at
@ -1567,8 +1697,12 @@ static void windowFullScan(WindowCodeArg *p){
int lblNext;
int lblBrk;
int addrNext;
int csr = pMWin->csrApp;
int csr;
VdbeModuleComment((v, "windowFullScan begin"));
assert( pMWin!=0 );
csr = pMWin->csrApp;
nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
lblNext = sqlite3VdbeMakeLabel(pParse);
@ -1623,7 +1757,7 @@ static void windowFullScan(WindowCodeArg *p){
if( addrEq ) sqlite3VdbeJumpHere(v, addrEq);
}
windowAggStep(pParse, pMWin, csr, 0, p->regArg);
windowAggStep(p, pMWin, csr, 0, p->regArg);
sqlite3VdbeResolveLabel(v, lblNext);
sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext);
@ -1638,6 +1772,7 @@ static void windowFullScan(WindowCodeArg *p){
}
windowAggFinal(p, 1);
VdbeModuleComment((v, "windowFullScan end"));
}
/*
@ -1812,34 +1947,46 @@ static void windowIfNewPeer(
/*
** This function is called as part of generating VM programs for RANGE
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
** the ORDER BY term in the window, it generates code equivalent to:
** the ORDER BY term in the window, and that argument op is OP_Ge, it generates
** code equivalent to:
**
** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr.peerVal is not
** a numeric type (real or integer), then the result of the addition is
** a copy of csr1.peerVal.
** The value of parameter op may also be OP_Gt or OP_Le. In these cases the
** operator in the above pseudo-code is replaced with ">" or "<=", respectively.
**
** If the sort-order for the ORDER BY term in the window is DESC, then the
** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is
** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
WindowCodeArg *p,
int op, /* OP_Ge or OP_Gt */
int csr1,
int regVal,
int csr2,
int lbl
int op, /* OP_Ge, OP_Gt, or OP_Le */
int csr1, /* Cursor number for cursor 1 */
int regVal, /* Register containing non-negative number */
int csr2, /* Cursor number for cursor 2 */
int lbl /* Jump destination if condition is true */
){
Parse *pParse = p->pParse;
Vdbe *v = sqlite3GetVdbe(pParse);
int reg1 = sqlite3GetTempReg(pParse);
int reg2 = sqlite3GetTempReg(pParse);
int arith = OP_Add;
int addrGe;
int regString = ++pParse->nMem;
ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */
int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */
int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 );
if( p->pMWin->pOrderBy->a[0].sortOrder ){
assert( pOrderBy && pOrderBy->nExpr==1 );
if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
switch( op ){
case OP_Ge: op = OP_Le; break;
case OP_Gt: op = OP_Lt; break;
@ -1848,27 +1995,95 @@ static void windowCodeRangeTest(
arith = OP_Subtract;
}
/* Read the peer-value from each cursor into a register */
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
/* Check if the peer value for csr1 value is a text or blob by comparing
** it to the smallest possible string - ''. If it is, jump over the
** OP_Add or OP_Subtract operation and proceed directly to the comparison. */
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
/* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
** This block adds (or subtracts for DESC) the numeric value in regVal
** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
** then leave reg1 as it is. In pseudo-code, this is implemented as:
**
** if( reg1>='' ) goto addrGe;
** reg1 = reg1 +/- regVal
** addrGe:
**
** Since all strings and blobs are greater-than-or-equal-to an empty string,
** the add/subtract is skipped for these, as required. If reg1 is a NULL,
** then the arithmetic is performed, but since adding or subtracting from
** NULL is always NULL anyway, this case is handled as required too. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
sqlite3VdbeJumpHere(v, addrGe);
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
** (and adding that capability causes a performance regression), so
** instead if the BIGNULL flag is set then cases where either reg1 or
** reg2 are NULL are handled separately in the following block. The code
** generated is equivalent to:
**
** if( reg1 IS NULL ){
** if( op==OP_Ge ) goto lbl;
** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl;
** if( op==OP_Le && reg2 IS NULL ) goto lbl;
** }else if( reg2 IS NULL ){
** if( op==OP_Le ) goto lbl;
** }
**
** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
** not taken, control jumps over the comparison operator coded below this
** block. */
if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){
/* This block runs if reg1 contains a NULL. */
int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
switch( op ){
case OP_Ge:
sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl);
break;
case OP_Gt:
sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl);
VdbeCoverage(v);
break;
case OP_Le:
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
VdbeCoverage(v);
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
if( op==OP_Gt || op==OP_Ge ){
sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
}
}
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
sqlite3ReleaseTempReg(pParse, reg1);
sqlite3ReleaseTempReg(pParse, reg2);
VdbeModuleComment((v, "CodeRangeTest: end"));
}
/*
@ -1888,9 +2103,7 @@ static int windowCodeOp(
Window *pMWin = p->pMWin;
int ret = 0;
Vdbe *v = p->pVdbe;
int addrIf = 0;
int addrContinue = 0;
int addrGoto = 0;
int bPeer = (pMWin->eFrmType!=TK_ROWS);
int lblDone = sqlite3VdbeMakeLabel(pParse);
@ -1923,7 +2136,7 @@ static int windowCodeOp(
);
}
}else{
addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1);
sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1);
VdbeCoverage(v);
}
}
@ -1932,6 +2145,25 @@ static int windowCodeOp(
windowAggFinal(p, 0);
}
addrContinue = sqlite3VdbeCurrentAddr(v);
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
** temporary table. It otherwise might, if (a>b). */
if( pMWin->eStart==pMWin->eEnd && regCountdown
&& pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
){
int regRowid1 = sqlite3GetTempReg(pParse);
int regRowid2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
}
switch( op ){
case WINDOW_RETURN_ROW:
csr = p->current.csr;
@ -1946,7 +2178,7 @@ static int windowCodeOp(
assert( pMWin->regEndRowid );
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1);
}else{
windowAggStep(pParse, pMWin, csr, 1, p->regArg);
windowAggStep(p, pMWin, csr, 1, p->regArg);
}
break;
@ -1958,7 +2190,7 @@ static int windowCodeOp(
assert( pMWin->regEndRowid );
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1);
}else{
windowAggStep(pParse, pMWin, csr, 0, p->regArg);
windowAggStep(p, pMWin, csr, 0, p->regArg);
}
break;
}
@ -1976,7 +2208,7 @@ static int windowCodeOp(
sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer);
VdbeCoverage(v);
if( bPeer ){
addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone);
}
}
@ -1992,8 +2224,6 @@ static int windowCodeOp(
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange);
}
sqlite3VdbeResolveLabel(v, lblDone);
if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
return ret;
}
@ -2009,6 +2239,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
pNew = sqlite3DbMallocZero(db, sizeof(Window));
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
pNew->zBase = sqlite3DbStrDup(db, p->zBase);
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
pNew->pFunc = p->pFunc;
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
@ -2017,9 +2248,11 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
pNew->eEnd = p->eEnd;
pNew->eStart = p->eStart;
pNew->eExclude = p->eExclude;
pNew->regResult = p->regResult;
pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);
pNew->pOwner = pOwner;
pNew->bImplicitFrame = p->bImplicitFrame;
}
}
return pNew;
@ -2343,7 +2576,7 @@ static int windowExprGtZero(Parse *pParse, Expr *pExpr){
** regEnd = <expr2>
** regStart = <expr1>
** }else{
** if( (csrEnd.key + regEnd) <= csrCurrent.key ){
** while( (csrEnd.key + regEnd) <= csrCurrent.key ){
** AGGSTEP
** }
** while( (csrStart.key + regStart) < csrCurrent.key ){
@ -2416,8 +2649,6 @@ void sqlite3WindowCodeStep(
int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */
int addrInteger = 0; /* Address of OP_Integer */
int addrEmpty; /* Address of OP_Rewind in flush: */
int regStart = 0; /* Value of <expr> PRECEDING */
int regEnd = 0; /* Value of <expr> FOLLOWING */
int regNew; /* Array of registers holding new input row */
int regRecord; /* regNew array in record form */
int regRowid; /* Rowid for regRecord in eph table */
@ -2426,6 +2657,8 @@ void sqlite3WindowCodeStep(
int regFlushPart = 0; /* Register for "Gosub flush_partition" */
WindowCodeArg s; /* Context object for sub-routines */
int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */
int regStart = 0; /* Value of <expr> PRECEDING */
int regEnd = 0; /* Value of <expr> FOLLOWING */
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT
|| pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED
@ -2556,14 +2789,14 @@ void sqlite3WindowCodeStep(
if( regStart ){
sqlite3ExprCode(pParse, pMWin->pStart, regStart);
windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE ? 3 : 0));
windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
}
if( regEnd ){
sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0));
windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
}
if( pMWin->eStart==pMWin->eEnd && regStart ){
if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound <expr> */

View File

@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix affinity2
do_execsql_test affinity2-100 {
CREATE TABLE t1(
@ -58,4 +59,78 @@ do_execsql_test affinity2-300 {
SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid;
} {1 1 1 0 2 1 1 1 3 0 1 1}
#-------------------------------------------------------------------------
do_execsql_test 400 {
CREATE TABLE ttt(c0, c1);
CREATE INDEX ii ON ttt(CAST(c0 AS NUMERIC));
INSERT INTO ttt VALUES('abc', '-1');
}
do_execsql_test 410 {
SELECT * FROM ttt WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid;
} {abc -1}
do_execsql_test 420 {
SELECT * FROM ttt INDEXED BY ii WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid;
} {abc -1}
do_execsql_test 430 {
CREATE TABLE t3(a, b, c INTEGER);
CREATE INDEX t3ac ON t3(a, c-1);
INSERT INTO t3 VALUES(1, 1, 1);
INSERT INTO t3 VALUES(2, 1, 0);
INSERT INTO t3 VALUES(3, 1, 1);
INSERT INTO t3 VALUES(4, 1, 0);
INSERT INTO t3 VALUES(5, 1, 1);
}
do_execsql_test 440 {
SELECT * FROM t3 WHERE c='0' ORDER BY a;
} {2 1 0 4 1 0}
# 2019-08-22 ticket https://sqlite.org/src/info/d99f1ffe836c591ac57f
# False positive in sqlite3ExprNeedsNoAffinityChange()
#
do_execsql_test 500 {
DROP TABLE IF EXISTS t0;
CREATE TABLE t0(c0 TEXT UNIQUE, c1);
INSERT INTO t0(c0) VALUES (-1);
SELECT quote(- x'ce'), quote(t0.c0), quote(- x'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 501 {
SELECT * FROM t0 WHERE - x'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 502 {
SELECT quote(+-+x'ce'), quote(t0.c0), quote(+-+x'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 503 {
SELECT * FROM t0 WHERE +-+x'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 504 {
SELECT quote(- 'ce'), quote(t0.c0), quote(- 'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 505 {
SELECT * FROM t0 WHERE - 'ce' >= t0.c0;
} {-1 {}}
do_execsql_test 506 {
SELECT quote(+-+'ce'), quote(t0.c0), quote(+-+'ce' >= t0.c0) FROM t0;
} {0 '-1' 1}
do_execsql_test 507 {
SELECT * FROM t0 WHERE +-+'ce' >= t0.c0;
} {-1 {}}
# 2019-08-30 ticket https://www.sqlite.org/src/info/40812aea1fde9594
#
# Due to some differences in floating point computations, these tests do not
# work under valgrind.
#
if {![info exists ::G(valgrind)]} {
do_execsql_test 600 {
DROP TABLE IF EXISTS t0;
CREATE TABLE t0(c0 REAL UNIQUE);
INSERT INTO t0(c0) VALUES (3175546974276630385);
SELECT 3175546974276630385 < c0 FROM t0;
} {1}
do_execsql_test 601 {
SELECT 1 FROM t0 WHERE 3175546974276630385 < c0;
} {1}
}
finish_test

View File

@ -1,4 +1,4 @@
# 2012 August 23
# 2012-08-23
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@ -232,6 +232,34 @@ do_test aggnested-3.16 {
GROUP BY id1;
}
} {12 2 34 4}
# 2019-08-31
# Problem found by dbsqlfuzz
#
do_execsql_test aggnested-4.1 {
DROP TABLE IF EXISTS aa;
DROP TABLE IF EXISTS bb;
CREATE TABLE aa(x INT); INSERT INTO aa(x) VALUES(123);
CREATE TABLE bb(y INT); INSERT INTO bb(y) VALUES(456);
SELECT (SELECT sum(x+(SELECT y)) FROM bb) FROM aa;
} {579}
do_execsql_test aggnested-4.2 {
SELECT (SELECT sum(x+y) FROM bb) FROM aa;
} {579}
do_execsql_test aggnested-4.3 {
DROP TABLE IF EXISTS tx;
DROP TABLE IF EXISTS ty;
CREATE TABLE tx(x INT);
INSERT INTO tx VALUES(1),(2),(3),(4),(5);
CREATE TABLE ty(y INT);
INSERT INTO ty VALUES(91),(92),(93);
SELECT min((SELECT count(y) FROM ty)) FROM tx;
} {3}
do_execsql_test aggnested-4.4 {
SELECT max((SELECT a FROM (SELECT count(*) AS a FROM ty) AS s)) FROM tx;
} {3}
finish_test

Some files were not shown because too many files have changed in this diff Show More