Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf025a8c18 | |||
| f1949b6634 | |||
| 056f5396fe | |||
| 64c1f77a8e | |||
| 3c49eaf4be | |||
| f7b0a5f3c3 | |||
| bd573c459b | |||
| df12595c09 | |||
| 6eb3480bd7 | |||
| d882108a01 | |||
| 4011c44322 | |||
| 685a50ad74 | |||
| 397776a823 | |||
| bb2d9b1bf1 | |||
| 0cfd46a1ad | |||
| bb777d517d | |||
| 48baed4f77 | |||
| 8c2b6d784b | |||
| 280c894b74 | |||
| 86d0ea7558 | |||
| 995bbbf993 | |||
| 8e9deb61af | |||
| 00583291bd | |||
| 6b27f5fab7 | |||
| eb7df46e32 | |||
| 1fb7a60ca0 | |||
| 69a4b383a2 | |||
| 5ba5f5b5d2 | |||
| 789df14b11 | |||
| e893e2e4ee | |||
| 4344dbd3ab | |||
| 0f86c9d8fa | |||
| 416a801600 | |||
| 8cdafc384e | |||
| fc232d6f65 | |||
| 5d3112872d | |||
| 8e02a180b9 | |||
| 6a8b94e266 | |||
| 3e62ddbf13 | |||
| a0368d9396 | |||
| ea93e2804d | |||
| 867e6de4d7 | |||
| 59ee43a78e | |||
| 1d40cdbd4b | |||
| d3e17ffbb7 | |||
| 66e82b47d9 | |||
| fecfb3189b | |||
| 50baf3d525 | |||
| 341141c339 | |||
| 4031bafafb | |||
| 9201184711 | |||
| 7fc86b96ba | |||
| 338e311acb | |||
| 30fc7f8009 | |||
| c8c9cdd9dd | |||
| b9cd2c4536 | |||
| bbd574bc37 | |||
| cf8784cd8f | |||
| 7458a9f3f7 | |||
| 4c57e326ef | |||
| 186ebd41cf | |||
| e8cf689df3 | |||
| 16d261b3ef | |||
| 9e80403bfc | |||
| a02fd67b99 | |||
| 136c9903bf | |||
| 252f39619a | |||
| bc30e2023b | |||
| 26fb126622 | |||
| 7578456c25 | |||
| 1e76c22b4a | |||
| e297196524 |
@@ -14,7 +14,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_D
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
pkgconfig_DATA = sqlite3.pc
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/make
|
||||
#
|
||||
# If the configure script does not work, then this Makefile is available
|
||||
# as a backup. Manually configure the variables below.
|
||||
#
|
||||
# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar)
|
||||
#
|
||||
CC = gcc
|
||||
CFLAGS = -O0 -I.
|
||||
LIBS = -lz
|
||||
COPTS += -D_BSD_SOURCE
|
||||
COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0
|
||||
COPTS += -DSQLITE_THREADSAFE=0
|
||||
COPTS += -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
COPTS += -DSQLITE_WITHOUT_ZONEMALLOC
|
||||
COPTS += -DSQLITE_ENABLE_RTREE
|
||||
|
||||
sqlite3: shell.c sqlite3.c
|
||||
$(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS)
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.24.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.25.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.24.0'
|
||||
PACKAGE_STRING='sqlite 3.24.0'
|
||||
PACKAGE_VERSION='3.25.0'
|
||||
PACKAGE_STRING='sqlite 3.25.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1465,7 +1465,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.24.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.25.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1530,7 +1530,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.24.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.25.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1655,7 +1655,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.24.0
|
||||
sqlite configure 3.25.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2074,7 +2074,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.24.0, which was
|
||||
It was created by sqlite $as_me 3.25.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12242,7 +12242,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.24.0, which was
|
||||
This file was extended by sqlite $as_me 3.25.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12308,7 +12308,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.24.0
|
||||
sqlite config.status 3.25.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -286,7 +286,6 @@ do_setup_rec_test $tn.14 {
|
||||
INSERT INTO t9 VALUES(?, ?, ?);
|
||||
} {
|
||||
CREATE INDEX t10_idx_00000062 ON t10(b);
|
||||
-- TRIGGER t9t
|
||||
SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
|
||||
@@ -1152,7 +1152,9 @@ int idxFindIndexes(
|
||||
}
|
||||
}
|
||||
|
||||
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
|
||||
if( zDetail[0]!='-' ){
|
||||
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
|
||||
}
|
||||
}
|
||||
|
||||
for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
|
||||
|
||||
+4
-5
@@ -205,7 +205,8 @@ static int csv_append(CsvReader *p, char c){
|
||||
** + Store the character that terminates the field in p->cTerm. Store
|
||||
** EOF on end-of-file.
|
||||
**
|
||||
** Return "" at EOF. Return 0 on an OOM error.
|
||||
** Return 0 at EOF or on OOM. On EOF, the p->cTerm character will have
|
||||
** been set to EOF.
|
||||
*/
|
||||
static char *csv_read_one_field(CsvReader *p){
|
||||
int c;
|
||||
@@ -213,7 +214,7 @@ static char *csv_read_one_field(CsvReader *p){
|
||||
c = csv_getc(p);
|
||||
if( c==EOF ){
|
||||
p->cTerm = EOF;
|
||||
return "";
|
||||
return 0;
|
||||
}
|
||||
if( c=='"' ){
|
||||
int pc, ppc;
|
||||
@@ -544,8 +545,7 @@ static int csvtabConnect(
|
||||
pNew->nCol = nCol;
|
||||
}else{
|
||||
do{
|
||||
const char *z = csv_read_one_field(&sRdr);
|
||||
if( z==0 ) goto csvtab_connect_oom;
|
||||
csv_read_one_field(&sRdr);
|
||||
pNew->nCol++;
|
||||
}while( sRdr.cTerm==',' );
|
||||
}
|
||||
@@ -663,7 +663,6 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
|
||||
do{
|
||||
z = csv_read_one_field(&pCur->rdr);
|
||||
if( z==0 ){
|
||||
csv_xfer_error(pTab, &pCur->rdr);
|
||||
break;
|
||||
}
|
||||
if( i<pTab->nCol ){
|
||||
|
||||
+244
-88
@@ -24,14 +24,15 @@
|
||||
**
|
||||
** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
|
||||
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
|
||||
**
|
||||
** The data for each node of the r-tree structure is stored in the %_node
|
||||
** table. For each node that is not the root node of the r-tree, there is
|
||||
** an entry in the %_parent table associating the node with its parent.
|
||||
** And for each row of data in the table, there is an entry in the %_rowid
|
||||
** table that maps from the entries rowid to the id of the node that it
|
||||
** is stored on.
|
||||
** is stored on. If the r-tree contains auxiliary columns, those are stored
|
||||
** on the end of the %_rowid table.
|
||||
**
|
||||
** The root node of an r-tree always exists, even if the r-tree table is
|
||||
** empty. The nodeno of the root node is always 1. All other nodes in the
|
||||
@@ -94,6 +95,9 @@ typedef struct RtreeSearchPoint RtreeSearchPoint;
|
||||
/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
|
||||
#define RTREE_MAX_DIMENSIONS 5
|
||||
|
||||
/* Maximum number of auxiliary columns */
|
||||
#define RTREE_MAX_AUX_COLUMN 100
|
||||
|
||||
/* Size of hash table Rtree.aHash. This hash table is not expected to
|
||||
** ever contain very many entries, so a fixed number of buckets is
|
||||
** used.
|
||||
@@ -122,12 +126,15 @@ struct Rtree {
|
||||
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
|
||||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
int iDepth; /* Current depth of the r-tree structure */
|
||||
char *zDb; /* Name of database containing r-tree table */
|
||||
char *zName; /* Name of r-tree table */
|
||||
u32 nBusy; /* Current number of users of this structure */
|
||||
i64 nRowEst; /* Estimated number of rows in this table */
|
||||
u32 nCursor; /* Number of open cursors */
|
||||
u32 nNodeRef; /* Number RtreeNodes with positive nRef */
|
||||
char *zReadAuxSql; /* SQL for statement to read aux data */
|
||||
|
||||
/* List of nodes removed during a CondenseTree operation. List is
|
||||
** linked together via the pointer normally used for hash chains -
|
||||
@@ -154,6 +161,9 @@ struct Rtree {
|
||||
sqlite3_stmt *pWriteParent;
|
||||
sqlite3_stmt *pDeleteParent;
|
||||
|
||||
/* Statement for writing to the "aux:" fields, if there are any */
|
||||
sqlite3_stmt *pWriteAux;
|
||||
|
||||
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
|
||||
};
|
||||
|
||||
@@ -230,6 +240,7 @@ struct RtreeCursor {
|
||||
sqlite3_vtab_cursor base; /* Base class. Must be first */
|
||||
u8 atEOF; /* True if at end of search */
|
||||
u8 bPoint; /* True if sPoint is valid */
|
||||
u8 bAuxValid; /* True if pReadAux is valid */
|
||||
int iStrategy; /* Copy of idxNum search parameter */
|
||||
int nConstraint; /* Number of entries in aConstraint */
|
||||
RtreeConstraint *aConstraint; /* Search constraints. */
|
||||
@@ -237,6 +248,7 @@ struct RtreeCursor {
|
||||
int nPoint; /* Number of slots used in aPoint[] */
|
||||
int mxLevel; /* iLevel value for root of the tree */
|
||||
RtreeSearchPoint *aPoint; /* Priority queue for search points */
|
||||
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
|
||||
RtreeSearchPoint sPoint; /* Cached next search point */
|
||||
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
|
||||
u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
|
||||
@@ -523,6 +535,7 @@ static int writeInt64(u8 *p, i64 i){
|
||||
*/
|
||||
static void nodeReference(RtreeNode *p){
|
||||
if( p ){
|
||||
assert( p->nRef>0 );
|
||||
p->nRef++;
|
||||
}
|
||||
}
|
||||
@@ -590,6 +603,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
|
||||
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
|
||||
pNode->zData = (u8 *)&pNode[1];
|
||||
pNode->nRef = 1;
|
||||
pRtree->nNodeRef++;
|
||||
pNode->pParent = pParent;
|
||||
pNode->isDirty = 1;
|
||||
nodeReference(pParent);
|
||||
@@ -623,10 +637,10 @@ static int nodeAcquire(
|
||||
/* Check if the requested node is already in the hash table. If so,
|
||||
** increase its reference count and return it.
|
||||
*/
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode)) ){
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
||||
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
|
||||
if( pParent && !pNode->pParent ){
|
||||
nodeReference(pParent);
|
||||
pParent->nRef++;
|
||||
pNode->pParent = pParent;
|
||||
}
|
||||
pNode->nRef++;
|
||||
@@ -665,6 +679,7 @@ static int nodeAcquire(
|
||||
pNode->pParent = pParent;
|
||||
pNode->zData = (u8 *)&pNode[1];
|
||||
pNode->nRef = 1;
|
||||
pRtree->nNodeRef++;
|
||||
pNode->iNode = iNode;
|
||||
pNode->isDirty = 0;
|
||||
pNode->pNext = 0;
|
||||
@@ -705,7 +720,10 @@ static int nodeAcquire(
|
||||
}
|
||||
*ppNode = pNode;
|
||||
}else{
|
||||
sqlite3_free(pNode);
|
||||
if( pNode ){
|
||||
pRtree->nNodeRef--;
|
||||
sqlite3_free(pNode);
|
||||
}
|
||||
*ppNode = 0;
|
||||
}
|
||||
|
||||
@@ -802,8 +820,10 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
|
||||
int rc = SQLITE_OK;
|
||||
if( pNode ){
|
||||
assert( pNode->nRef>0 );
|
||||
assert( pRtree->nNodeRef>0 );
|
||||
pNode->nRef--;
|
||||
if( pNode->nRef==0 ){
|
||||
pRtree->nNodeRef--;
|
||||
if( pNode->iNode==1 ){
|
||||
pRtree->iDepth = -1;
|
||||
}
|
||||
@@ -920,8 +940,9 @@ static void rtreeRelease(Rtree *pRtree){
|
||||
pRtree->nBusy--;
|
||||
if( pRtree->nBusy==0 ){
|
||||
pRtree->inWrTrans = 0;
|
||||
pRtree->nCursor = 0;
|
||||
assert( pRtree->nCursor==0 );
|
||||
nodeBlobReset(pRtree);
|
||||
assert( pRtree->nNodeRef==0 );
|
||||
sqlite3_finalize(pRtree->pWriteNode);
|
||||
sqlite3_finalize(pRtree->pDeleteNode);
|
||||
sqlite3_finalize(pRtree->pReadRowid);
|
||||
@@ -930,6 +951,8 @@ static void rtreeRelease(Rtree *pRtree){
|
||||
sqlite3_finalize(pRtree->pReadParent);
|
||||
sqlite3_finalize(pRtree->pWriteParent);
|
||||
sqlite3_finalize(pRtree->pDeleteParent);
|
||||
sqlite3_finalize(pRtree->pWriteAux);
|
||||
sqlite3_free(pRtree->zReadAuxSql);
|
||||
sqlite3_free(pRtree);
|
||||
}
|
||||
}
|
||||
@@ -1018,6 +1041,7 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
|
||||
RtreeCursor *pCsr = (RtreeCursor *)cur;
|
||||
assert( pRtree->nCursor>0 );
|
||||
freeCursorConstraints(pCsr);
|
||||
sqlite3_finalize(pCsr->pReadAux);
|
||||
sqlite3_free(pCsr->aPoint);
|
||||
for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
|
||||
sqlite3_free(pCsr);
|
||||
@@ -1389,7 +1413,7 @@ static RtreeSearchPoint *rtreeSearchPointNew(
|
||||
if( ii<RTREE_CACHE_SZ ){
|
||||
assert( pCur->aNode[ii]==0 );
|
||||
pCur->aNode[ii] = pCur->aNode[0];
|
||||
}else{
|
||||
}else{
|
||||
nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
|
||||
}
|
||||
pCur->aNode[0] = 0;
|
||||
@@ -1560,6 +1584,10 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
|
||||
|
||||
/* Move to the next entry that matches the configured constraints. */
|
||||
RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
|
||||
if( pCsr->bAuxValid ){
|
||||
pCsr->bAuxValid = 0;
|
||||
sqlite3_reset(pCsr->pReadAux);
|
||||
}
|
||||
rtreeSearchPointPop(pCsr);
|
||||
rc = rtreeStepToLeaf(pCsr);
|
||||
return rc;
|
||||
@@ -1594,7 +1622,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
if( i==0 ){
|
||||
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
}else{
|
||||
}else if( i<=pRtree->nDim2 ){
|
||||
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
|
||||
#ifndef SQLITE_RTREE_INT_ONLY
|
||||
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
||||
@@ -1605,7 +1633,27 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
assert( pRtree->eCoordType==RTREE_COORD_INT32 );
|
||||
sqlite3_result_int(ctx, c.i);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( !pCsr->bAuxValid ){
|
||||
if( pCsr->pReadAux==0 ){
|
||||
rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
|
||||
&pCsr->pReadAux, 0);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
sqlite3_bind_int64(pCsr->pReadAux, 1,
|
||||
nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
rc = sqlite3_step(pCsr->pReadAux);
|
||||
if( rc==SQLITE_ROW ){
|
||||
pCsr->bAuxValid = 1;
|
||||
}else{
|
||||
sqlite3_reset(pCsr->pReadAux);
|
||||
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
sqlite3_result_value(ctx,
|
||||
sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1));
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1683,14 +1731,17 @@ static int rtreeFilter(
|
||||
int ii;
|
||||
int rc = SQLITE_OK;
|
||||
int iCell = 0;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
rtreeReference(pRtree);
|
||||
|
||||
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
||||
freeCursorConstraints(pCsr);
|
||||
sqlite3_free(pCsr->aPoint);
|
||||
pStmt = pCsr->pReadAux;
|
||||
memset(pCsr, 0, sizeof(RtreeCursor));
|
||||
pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
||||
pCsr->pReadAux = pStmt;
|
||||
|
||||
pCsr->iStrategy = idxNum;
|
||||
if( idxNum==1 ){
|
||||
@@ -1853,10 +1904,14 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
*/
|
||||
pIdxInfo->estimatedCost = 30.0;
|
||||
pIdxInfo->estimatedRows = 1;
|
||||
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){
|
||||
if( p->usable
|
||||
&& ((p->iColumn>0 && p->iColumn<=pRtree->nDim2)
|
||||
|| p->op==SQLITE_INDEX_CONSTRAINT_MATCH)
|
||||
){
|
||||
u8 op;
|
||||
switch( p->op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
|
||||
@@ -2429,7 +2484,7 @@ static int SplitNode(
|
||||
}else{
|
||||
pLeft = pNode;
|
||||
pRight = nodeNew(pRtree, pLeft->pParent);
|
||||
nodeReference(pLeft);
|
||||
pLeft->nRef++;
|
||||
}
|
||||
|
||||
if( !pLeft || !pRight ){
|
||||
@@ -2919,6 +2974,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
||||
rc = reinsertNodeContent(pRtree, pLeaf);
|
||||
}
|
||||
pRtree->pDeleted = pLeaf->pNext;
|
||||
pRtree->nNodeRef--;
|
||||
sqlite3_free(pLeaf);
|
||||
}
|
||||
|
||||
@@ -3015,7 +3071,7 @@ static int rtreeConstraintError(Rtree *pRtree, int iCol){
|
||||
static int rtreeUpdate(
|
||||
sqlite3_vtab *pVtab,
|
||||
int nData,
|
||||
sqlite3_value **azData,
|
||||
sqlite3_value **aData,
|
||||
sqlite_int64 *pRowid
|
||||
){
|
||||
Rtree *pRtree = (Rtree *)pVtab;
|
||||
@@ -3023,6 +3079,12 @@ static int rtreeUpdate(
|
||||
RtreeCell cell; /* New cell to insert if nData>1 */
|
||||
int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
|
||||
|
||||
if( pRtree->nNodeRef ){
|
||||
/* Unable to write to the btree while another cursor is reading from it,
|
||||
** since the write might do a rebalance which would disrupt the read
|
||||
** cursor. */
|
||||
return SQLITE_LOCKED_VTAB;
|
||||
}
|
||||
rtreeReference(pRtree);
|
||||
assert(nData>=1);
|
||||
|
||||
@@ -3041,8 +3103,10 @@ static int rtreeUpdate(
|
||||
*/
|
||||
if( nData>1 ){
|
||||
int ii;
|
||||
int nn = nData - 4;
|
||||
|
||||
/* Populate the cell.aCoord[] array. The first coordinate is azData[3].
|
||||
if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
|
||||
/* Populate the cell.aCoord[] array. The first coordinate is aData[3].
|
||||
**
|
||||
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
|
||||
** with "column" that are interpreted as table constraints.
|
||||
@@ -3050,13 +3114,12 @@ static int rtreeUpdate(
|
||||
** This problem was discovered after years of use, so we silently ignore
|
||||
** these kinds of misdeclared tables to avoid breaking any legacy.
|
||||
*/
|
||||
assert( nData<=(pRtree->nDim2 + 3) );
|
||||
|
||||
#ifndef SQLITE_RTREE_INT_ONLY
|
||||
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
||||
for(ii=0; ii<nData-4; ii+=2){
|
||||
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
|
||||
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
|
||||
for(ii=0; ii<nn; ii+=2){
|
||||
cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
|
||||
cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
|
||||
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
|
||||
rc = rtreeConstraintError(pRtree, ii+1);
|
||||
goto constraint;
|
||||
@@ -3065,9 +3128,9 @@ static int rtreeUpdate(
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
for(ii=0; ii<nData-4; ii+=2){
|
||||
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
|
||||
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
|
||||
for(ii=0; ii<nn; ii+=2){
|
||||
cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
|
||||
cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
|
||||
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
|
||||
rc = rtreeConstraintError(pRtree, ii+1);
|
||||
goto constraint;
|
||||
@@ -3077,10 +3140,10 @@ static int rtreeUpdate(
|
||||
|
||||
/* If a rowid value was supplied, check if it is already present in
|
||||
** the table. If so, the constraint has failed. */
|
||||
if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
|
||||
cell.iRowid = sqlite3_value_int64(azData[2]);
|
||||
if( sqlite3_value_type(azData[0])==SQLITE_NULL
|
||||
|| sqlite3_value_int64(azData[0])!=cell.iRowid
|
||||
if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){
|
||||
cell.iRowid = sqlite3_value_int64(aData[2]);
|
||||
if( sqlite3_value_type(aData[0])==SQLITE_NULL
|
||||
|| sqlite3_value_int64(aData[0])!=cell.iRowid
|
||||
){
|
||||
int steprc;
|
||||
sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
|
||||
@@ -3099,16 +3162,16 @@ static int rtreeUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
/* If azData[0] is not an SQL NULL value, it is the rowid of a
|
||||
/* If aData[0] is not an SQL NULL value, it is the rowid of a
|
||||
** record to delete from the r-tree table. The following block does
|
||||
** just that.
|
||||
*/
|
||||
if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
|
||||
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
|
||||
if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
|
||||
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
|
||||
}
|
||||
|
||||
/* If the azData[] array contains more than one element, elements
|
||||
** (azData[2]..azData[argc-1]) contain a new record to insert into
|
||||
/* If the aData[] array contains more than one element, elements
|
||||
** (aData[2]..aData[argc-1]) contain a new record to insert into
|
||||
** the r-tree structure.
|
||||
*/
|
||||
if( rc==SQLITE_OK && nData>1 ){
|
||||
@@ -3133,6 +3196,16 @@ static int rtreeUpdate(
|
||||
rc = rc2;
|
||||
}
|
||||
}
|
||||
if( pRtree->nAux ){
|
||||
sqlite3_stmt *pUp = pRtree->pWriteAux;
|
||||
int jj;
|
||||
sqlite3_bind_int64(pUp, 1, *pRowid);
|
||||
for(jj=0; jj<pRtree->nAux; jj++){
|
||||
sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
|
||||
}
|
||||
sqlite3_step(pUp);
|
||||
rc = sqlite3_reset(pUp);
|
||||
}
|
||||
}
|
||||
|
||||
constraint:
|
||||
@@ -3289,18 +3362,18 @@ static int rtreeSqlInit(
|
||||
#define N_STATEMENT 8
|
||||
static const char *azSql[N_STATEMENT] = {
|
||||
/* Write the xxx_node table */
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1",
|
||||
|
||||
/* Read and write the xxx_rowid table */
|
||||
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
|
||||
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1",
|
||||
|
||||
/* Read and write the xxx_parent table */
|
||||
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
|
||||
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
|
||||
};
|
||||
sqlite3_stmt **appStmt[N_STATEMENT];
|
||||
int i;
|
||||
@@ -3308,14 +3381,25 @@ static int rtreeSqlInit(
|
||||
pRtree->db = db;
|
||||
|
||||
if( isCreate ){
|
||||
char *zCreate = sqlite3_mprintf(
|
||||
"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
|
||||
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
|
||||
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,"
|
||||
" parentnode INTEGER);"
|
||||
"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
|
||||
zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
|
||||
);
|
||||
char *zCreate;
|
||||
sqlite3_str *p = sqlite3_str_new(db);
|
||||
int ii;
|
||||
sqlite3_str_appendf(p,
|
||||
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno",
|
||||
zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
sqlite3_str_appendf(p,",a%d",ii);
|
||||
}
|
||||
sqlite3_str_appendf(p,
|
||||
");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);",
|
||||
zDb, zPrefix);
|
||||
sqlite3_str_appendf(p,
|
||||
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);",
|
||||
zDb, zPrefix);
|
||||
sqlite3_str_appendf(p,
|
||||
"INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))",
|
||||
zDb, zPrefix, pRtree->iNodeSize);
|
||||
zCreate = sqlite3_str_finish(p);
|
||||
if( !zCreate ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -3337,7 +3421,17 @@ static int rtreeSqlInit(
|
||||
|
||||
rc = rtreeQueryStat1(db, pRtree);
|
||||
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
|
||||
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
|
||||
char *zSql;
|
||||
const char *zFormat;
|
||||
if( i!=3 || pRtree->nAux==0 ){
|
||||
zFormat = azSql[i];
|
||||
}else {
|
||||
/* An UPSERT is very slightly slower than REPLACE, but it is needed
|
||||
** if there are auxiliary columns */
|
||||
zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)"
|
||||
"ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno";
|
||||
}
|
||||
zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
|
||||
if( zSql ){
|
||||
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
appStmt[i], 0);
|
||||
@@ -3346,6 +3440,32 @@ static int rtreeSqlInit(
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( pRtree->nAux ){
|
||||
pRtree->zReadAuxSql = sqlite3_mprintf(
|
||||
"SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
|
||||
zDb, zPrefix);
|
||||
if( pRtree->zReadAuxSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_str *p = sqlite3_str_new(db);
|
||||
int ii;
|
||||
char *zSql;
|
||||
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
if( ii ) sqlite3_str_append(p, ",", 1);
|
||||
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
|
||||
}
|
||||
sqlite3_str_appendf(p, " WHERE rowid=?1");
|
||||
zSql = sqlite3_str_finish(p);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
&pRtree->pWriteAux, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3448,17 +3568,22 @@ static int rtreeInit(
|
||||
int nDb; /* Length of string argv[1] */
|
||||
int nName; /* Length of string argv[2] */
|
||||
int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
|
||||
sqlite3_str *pSql;
|
||||
char *zSql;
|
||||
int ii = 4;
|
||||
int iErr;
|
||||
|
||||
const char *aErrMsg[] = {
|
||||
0, /* 0 */
|
||||
"Wrong number of columns for an rtree table", /* 1 */
|
||||
"Too few columns for an rtree table", /* 2 */
|
||||
"Too many columns for an rtree table" /* 3 */
|
||||
"Too many columns for an rtree table", /* 3 */
|
||||
"Auxiliary rtree columns must be last" /* 4 */
|
||||
};
|
||||
|
||||
int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
|
||||
if( aErrMsg[iErr] ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
|
||||
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
|
||||
if( argc>RTREE_MAX_AUX_COLUMN+3 ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
@@ -3476,53 +3601,73 @@ static int rtreeInit(
|
||||
pRtree->base.pModule = &rtreeModule;
|
||||
pRtree->zDb = (char *)&pRtree[1];
|
||||
pRtree->zName = &pRtree->zDb[nDb+1];
|
||||
pRtree->nDim = (u8)((argc-4)/2);
|
||||
pRtree->nDim2 = pRtree->nDim*2;
|
||||
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
|
||||
pRtree->eCoordType = (u8)eCoordType;
|
||||
memcpy(pRtree->zDb, argv[1], nDb);
|
||||
memcpy(pRtree->zName, argv[2], nName);
|
||||
|
||||
/* Figure out the node size to use. */
|
||||
rc = getNodeSize(db, pRtree, isCreate, pzErr);
|
||||
|
||||
/* Create/Connect to the underlying relational database schema. If
|
||||
** that is successful, call sqlite3_declare_vtab() to configure
|
||||
** the r-tree table schema.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
pSql = sqlite3_str_new(db);
|
||||
sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
|
||||
for(ii=4; ii<argc; ii++){
|
||||
if( argv[ii][0]=='+' ){
|
||||
pRtree->nAux++;
|
||||
sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
|
||||
}else if( pRtree->nAux>0 ){
|
||||
break;
|
||||
}else{
|
||||
sqlite3_str *pSql = sqlite3_str_new(db);
|
||||
char *zSql;
|
||||
int ii;
|
||||
if( pSql==0 ){
|
||||
zSql = 0;
|
||||
}else{
|
||||
sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
|
||||
for(ii=4; ii<argc; ii++){
|
||||
sqlite3_str_appendf(pSql, ", %s", argv[ii]);
|
||||
}
|
||||
sqlite3_str_appendf(pSql, ");");
|
||||
zSql = sqlite3_str_finish(pSql);
|
||||
}
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
pRtree->nDim2++;
|
||||
sqlite3_str_appendf(pSql, ",%s", argv[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
*ppVtab = (sqlite3_vtab *)pRtree;
|
||||
}else{
|
||||
assert( *ppVtab==0 );
|
||||
assert( pRtree->nBusy==1 );
|
||||
rtreeRelease(pRtree);
|
||||
sqlite3_str_appendf(pSql, ");");
|
||||
zSql = sqlite3_str_finish(pSql);
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( ii<argc ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[4]);
|
||||
rc = SQLITE_ERROR;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) goto rtreeInit_fail;
|
||||
pRtree->nDim = pRtree->nDim2/2;
|
||||
if( pRtree->nDim<1 ){
|
||||
iErr = 2;
|
||||
}else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){
|
||||
iErr = 3;
|
||||
}else if( pRtree->nDim2 % 2 ){
|
||||
iErr = 1;
|
||||
}else{
|
||||
iErr = 0;
|
||||
}
|
||||
if( iErr ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
|
||||
goto rtreeInit_fail;
|
||||
}
|
||||
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
|
||||
|
||||
/* Figure out the node size to use. */
|
||||
rc = getNodeSize(db, pRtree, isCreate, pzErr);
|
||||
if( rc ) goto rtreeInit_fail;
|
||||
rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
|
||||
if( rc ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
goto rtreeInit_fail;
|
||||
}
|
||||
|
||||
*ppVtab = (sqlite3_vtab *)pRtree;
|
||||
return SQLITE_OK;
|
||||
|
||||
rtreeInit_fail:
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
assert( *ppVtab==0 );
|
||||
assert( pRtree->nBusy==1 );
|
||||
rtreeRelease(pRtree);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3751,7 +3896,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
|
||||
** two tables are:
|
||||
**
|
||||
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
|
||||
**
|
||||
** In both cases, this function checks that there exists an entry with
|
||||
** IPK value iKey and the second column set to iVal.
|
||||
@@ -3766,8 +3911,8 @@ static void rtreeCheckMapping(
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
const char *azSql[2] = {
|
||||
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?",
|
||||
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?"
|
||||
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1",
|
||||
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1"
|
||||
};
|
||||
|
||||
assert( bLeaf==0 || bLeaf==1 );
|
||||
@@ -3951,6 +4096,7 @@ static int rtreeCheckTable(
|
||||
RtreeCheck check; /* Common context for various routines */
|
||||
sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
|
||||
int bEnd = 0; /* True if transaction should be closed */
|
||||
int nAux = 0; /* Number of extra columns. */
|
||||
|
||||
/* Initialize the context object */
|
||||
memset(&check, 0, sizeof(check));
|
||||
@@ -3966,11 +4112,21 @@ static int rtreeCheckTable(
|
||||
bEnd = 1;
|
||||
}
|
||||
|
||||
/* Find the number of auxiliary columns */
|
||||
if( check.rc==SQLITE_OK ){
|
||||
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
|
||||
if( pStmt ){
|
||||
nAux = sqlite3_column_count(pStmt) - 2;
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Find number of dimensions in the rtree table. */
|
||||
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
|
||||
if( pStmt ){
|
||||
int rc;
|
||||
check.nDim = (sqlite3_column_count(pStmt) - 1) / 2;
|
||||
check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2;
|
||||
if( check.nDim<1 ){
|
||||
rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
|
||||
}else if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
|
||||
+43
-5
@@ -476,11 +476,11 @@ foreach {tn sql_template testdata} {
|
||||
}
|
||||
|
||||
3 "UPDATE %CONF% t1 SET idx = 2 WHERE idx = 4" {
|
||||
ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
|
||||
ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
REPLACE 1 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
|
||||
ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
|
||||
ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
REPLACE 0 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
|
||||
}
|
||||
|
||||
3 "UPDATE %CONF% t1 SET idx = ((idx+1)%5)+1 WHERE idx > 2" {
|
||||
@@ -609,5 +609,43 @@ do_execsql_test 15.2 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
# Test cases for the new auxiliary columns feature
|
||||
#
|
||||
do_catchsql_test 16.100 {
|
||||
CREATE VIRTUAL TABLE t16 USING rtree(id,x0,x1,y0,+aux1,x1);
|
||||
} {1 {Auxiliary rtree columns must be last}}
|
||||
do_test 16.110 {
|
||||
set sql {
|
||||
CREATE VIRTUAL TABLE t16 USING rtree(
|
||||
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
|
||||
}
|
||||
for {set i 12} {$i<=100} {incr i} {
|
||||
append sql ", +a$i"
|
||||
}
|
||||
append sql ");"
|
||||
execsql $sql
|
||||
} {}
|
||||
do_test 16.120 {
|
||||
set sql {
|
||||
CREATE VIRTUAL TABLE t16b USING rtree(
|
||||
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
|
||||
}
|
||||
for {set i 12} {$i<=101} {incr i} {
|
||||
append sql ", +a$i"
|
||||
}
|
||||
append sql ");"
|
||||
catchsql $sql
|
||||
} {1 {Too many columns for an rtree table}}
|
||||
|
||||
do_execsql_test 16.130 {
|
||||
DROP TABLE IF EXISTS rt1;
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree(id, x1, x2, +aux);
|
||||
INSERT INTO rt1 VALUES(1, 1, 2, 'aux1');
|
||||
INSERT INTO rt1 VALUES(2, 2, 3, 'aux2');
|
||||
INSERT INTO rt1 VALUES(3, 3, 4, 'aux3');
|
||||
INSERT INTO rt1 VALUES(4, 4, 5, 'aux4');
|
||||
SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
|
||||
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -81,7 +81,7 @@ do_faultsim_test rtree3-2 -faults oom* -prep {
|
||||
do_malloc_test rtree3-3.prep {
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, +a1, +a2);
|
||||
INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
+36
-3
@@ -38,11 +38,20 @@ do_test rtree8-1.1.1 {
|
||||
} {}
|
||||
do_test rtree8-1.1.2 {
|
||||
set res [list]
|
||||
db eval { SELECT * FROM t1 } {
|
||||
lappend res $x1 $x2
|
||||
set rc [catch {
|
||||
db eval { SELECT * FROM t1 } {
|
||||
lappend res $x1 $x2
|
||||
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
|
||||
}
|
||||
} msg];
|
||||
lappend rc $msg
|
||||
set rc
|
||||
} {1 {database table is locked}}
|
||||
do_test rtree8-1.1.2b {
|
||||
db eval { SELECT * FROM t1 ORDER BY +id } {
|
||||
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
|
||||
}
|
||||
set res
|
||||
db eval {SELECT x1, x2 FROM t1}
|
||||
} {1 3 2 4 3 5}
|
||||
do_test rtree8-1.1.3 {
|
||||
execsql { SELECT * FROM t1 }
|
||||
@@ -170,5 +179,29 @@ do_test rtree8-5.4 {
|
||||
} {}
|
||||
do_rtree_integrity_test rtree8-5.5 t2
|
||||
|
||||
# 2018-05-24
|
||||
# The following script caused an assertion fault and/or segfault
|
||||
# prior to the fix that prevents simultaneous reads and writes on
|
||||
# the same rtree virtual table.
|
||||
#
|
||||
do_test rtree8-6.1 {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
db eval {
|
||||
PRAGMA page_size=512;
|
||||
CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
|
||||
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
|
||||
INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
|
||||
}
|
||||
set rc [catch {
|
||||
db eval {SELECT id FROM t1} x {
|
||||
db eval {DELETE FROM t1 WHERE id=$x(id)}
|
||||
}
|
||||
} msg]
|
||||
lappend rc $msg
|
||||
} {1 {database table is locked}}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -178,7 +178,7 @@ do_execsql_test 4.3 {
|
||||
reset_db
|
||||
do_execsql_test 5.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY, y);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, +d1);
|
||||
|
||||
INSERT INTO t1(x) VALUES(1);
|
||||
INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
|
||||
@@ -192,7 +192,7 @@ do_execsql_test 5.1 {
|
||||
INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
|
||||
INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
|
||||
|
||||
INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
|
||||
INSERT INTO rt SELECT x, x, x+1, printf('x%04xy',x) FROM t1 WHERE x<=5;
|
||||
}
|
||||
do_rtree_integrity_test 5.1.1 rt
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 2018-05-16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file contains tests for the r-tree module, specifically the
|
||||
# auxiliary column mechanism.
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
do_execsql_test rtreeH-100 {
|
||||
CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1,+label,+other);
|
||||
INSERT INTO t1(x0,x1,y0,y1,label) VALUES
|
||||
(0,10,0,10,'lower-left corner'),
|
||||
(0,10,90,100,'upper-left corner'),
|
||||
(90,100,0,10,'lower-right corner'),
|
||||
(90,100,90,100,'upper-right corner'),
|
||||
(40,60,40,60,'center'),
|
||||
(0,5,0,100,'left edge'),
|
||||
(95,100,0,100,'right edge'),
|
||||
(0,100,0,5,'bottom edge'),
|
||||
(0,100,95,100,'top edge'),
|
||||
(0,100,0,100,'the whole thing'),
|
||||
(0,50,0,100,'left half'),
|
||||
(51,100,0,100,'right half'),
|
||||
(0,100,0,50,'bottom half'),
|
||||
(0,100,51,100,'top half');
|
||||
} {}
|
||||
do_execsql_test rtreeH-101 {
|
||||
SELECT * FROM t1_rowid ORDER BY rowid
|
||||
} {1 1 {lower-left corner} {} 2 1 {upper-left corner} {} 3 1 {lower-right corner} {} 4 1 {upper-right corner} {} 5 1 center {} 6 1 {left edge} {} 7 1 {right edge} {} 8 1 {bottom edge} {} 9 1 {top edge} {} 10 1 {the whole thing} {} 11 1 {left half} {} 12 1 {right half} {} 13 1 {bottom half} {} 14 1 {top half} {}}
|
||||
|
||||
do_execsql_test rtreeH-102 {
|
||||
SELECT * FROM t1 WHERE rowid=5;
|
||||
} {5 40.0 60.0 40.0 60.0 center {}}
|
||||
do_execsql_test rtreeH-103 {
|
||||
SELECT * FROM t1 WHERE label='center';
|
||||
} {5 40.0 60.0 40.0 60.0 center {}}
|
||||
|
||||
do_rtree_integrity_test rtreeH-110 t1
|
||||
|
||||
do_execsql_test rtreeH-120 {
|
||||
SELECT label FROM t1 WHERE x1<=50 ORDER BY id
|
||||
} {{lower-left corner} {upper-left corner} {left edge} {left half}}
|
||||
do_execsql_test rtreeH-121 {
|
||||
SELECT label FROM t1 WHERE x1<=50 AND label NOT LIKE '%corner%' ORDER BY id
|
||||
} {{left edge} {left half}}
|
||||
|
||||
do_execsql_test rtreeH-200 {
|
||||
WITH RECURSIVE
|
||||
c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
|
||||
c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
|
||||
INSERT INTO t1(id, x0,x1,y0,y1,label)
|
||||
SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
|
||||
} {}
|
||||
|
||||
do_execsql_test rtreeH-210 {
|
||||
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
|
||||
ORDER BY id;
|
||||
} {box-48,48 box-49,48 box-48,49 box-49,49}
|
||||
|
||||
do_execsql_test rtreeH-300 {
|
||||
UPDATE t1 SET label='x'||label
|
||||
WHERE x0>=49 AND x1<=50 AND y0>=49 AND y1<=50;
|
||||
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
|
||||
ORDER BY id;
|
||||
} {box-48,48 box-49,48 box-48,49 xbox-49,49}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -1,18 +1,19 @@
|
||||
C Remove\sincorrect\sNEVER()\smacro\sadded\sby\sthe\sprevious\scheck-in.
|
||||
D 2018-05-18T14:19:35.018
|
||||
C Fix\sthe\sassert()s\sin\sthe\sbyte-code\sengine\sthat\sprove\sthat\scursors\nare\sunidirectional.
|
||||
D 2018-06-07T18:01:21.263
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f
|
||||
F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373
|
||||
F VERSION b7c9d1d11cb70ef8e90cfcf3c944aa58a9f801cc2ad487eebb0a110c16dfc2df
|
||||
F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am f8c274ee0022cb6d48ff103ab6c6b0733c41b3b02cb8566228dfd602f701e0c2
|
||||
F autoconf/Makefile.am 465fb475ee5a4b8a63d26c889cb36a4edbff0325b6859eb29a13cdf5c91b005c
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc 6a46d0659d6e4a25346102bcba40a7fb4b0b8b2dc4faabdf0187488c6dd580d6
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
@@ -32,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 80e2dcad8ab88aacc58b55eb0e395f79184b45fcfaa3f36fc20d2e71cfa0a7e4 x
|
||||
F configure 481df2c668b5c8cd5723dbcda88df8e6796a23884877109d1fe558667a0474bf x
|
||||
F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
|
||||
@@ -44,8 +45,8 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
|
||||
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 87e54effda905d991edfe4bcd28098460a568246129ab7263f71b25420ea727f
|
||||
F ext/expert/sqlite3expert.c 95fdee74be2912d962951d984f1123e55d3f44bd643da7a48ff6ea9426a47f69
|
||||
F ext/expert/expert1.test baa05800dc1c569faa7ce6232cead0fcedc07fea038b3a2489eaaf710831d546
|
||||
F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4
|
||||
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
@@ -274,7 +275,7 @@ F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c
|
||||
F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15
|
||||
F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483
|
||||
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
|
||||
F ext/misc/csv.c d1e324fac3f87f818d684a3d752d1ef76dbcd4fc0db6746ac4034c19d0bcda21
|
||||
F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
|
||||
F ext/misc/dbdump.c 69ef1be5b210538f77dfcc6fcb55b4b5f5e98b1e0bcfd67d818711e10761db4d
|
||||
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
|
||||
F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded
|
||||
@@ -355,24 +356,25 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
|
||||
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 11dc450eec4c86a9b1eee104e478f9556382622a6a7e8080a478567ea975ea69
|
||||
F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972
|
||||
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
|
||||
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
|
||||
F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482
|
||||
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
|
||||
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
|
||||
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
|
||||
F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2
|
||||
F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b
|
||||
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
|
||||
F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
|
||||
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
|
||||
F ext/rtree/rtreeC.test 55e40c4bd9735d9944280f0e664f39374e71bcd9cd3fe4e82786d20b48017fb5
|
||||
F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
|
||||
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
|
||||
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
|
||||
F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
|
||||
@@ -427,37 +429,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
|
||||
F src/alter.c 819b14b58e71565f8da505a9c1d5d9d904605f85cd64179cf9c7d1edcdad6c25
|
||||
F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
|
||||
F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
|
||||
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
|
||||
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 8270813c8f0ca91b2802e88ded3755d04ee962a923d431c13bcb6cf3e0c18f63
|
||||
F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598
|
||||
F src/btree.c ae7687faa330562d36cede3375fdc316bff068e9216322d0dfbb3749333e5d3d
|
||||
F src/btree.h ab639c4b9b210b8f4cd7a3a922af73df9a3f27c1d124267339fd73ef8619f488
|
||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||
F src/build.c 50ff3e0fa07646b4d797aae0f773efcdb7602f6a5e2f5da27856503f35200889
|
||||
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
|
||||
F src/build.c 5fc41458505331bfb0c175f40b9a13cb335f826bed3ae311aaae000c132d7b16
|
||||
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48
|
||||
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
|
||||
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
|
||||
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
|
||||
F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f
|
||||
F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013
|
||||
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
|
||||
F src/expr.c 16f90ae2af2a100bc430a89184afde54878d82f18267e8d00bc4f33e695a7c57
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
|
||||
F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
|
||||
F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa
|
||||
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e
|
||||
F src/insert.c 76b1dc902e4c3930d9a17a40cd8ee2e94b1fd8cce766672caef164a6d5d4df1d
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
|
||||
F src/main.c b56b2d62d5d11e3f5100b25fca34c13c62a0fe73941f6873454a7fa8a454170d
|
||||
F src/main.c a086ab7d6e4e3f07bd5789d16f977d425f9482e7b3baeeb2f17bde0e6bfb2bc1
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -477,35 +479,35 @@ F src/os.c 1cb0d1d1b3a4267966dee6e292d2b2cdf88e47c0c59cebff27ecafac052dd165
|
||||
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c 2b53b0b8ddc580db096252c721729e5f5f2f355b4fc056f8f3fb328aeb3c9e8a
|
||||
F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9
|
||||
F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
|
||||
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
|
||||
F src/parse.y 07784439d25f0bc64a656eece4caecc549b147d213f513cdbeb8430345ec2911
|
||||
F src/parse.y 0b81472496809693a139067fea1fe3f14a7be8aa26c8f18bb327034d1252a06a
|
||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c c0d13c0e82a9197aef5533d63300c5b0c8a216ae1fd14ada64e1f12f398d7e82
|
||||
F src/pragma.c 71c585f1d26e14b931fa4573f587933d6dfddecd9d9001b0f126f74f7306bf87
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa
|
||||
F src/printf.c 1d1b4a568a58d0f32a5ff26c6b98db8a6e1883467f343a6406263cacd2e60c21
|
||||
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
|
||||
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9
|
||||
F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71
|
||||
F src/shell.c.in e0f006980883e238555c5ab51bd2dad9fa477c31928419f6d35774288b94853b
|
||||
F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4
|
||||
F src/select.c 8d3176c5258cc83942815ebe75b4c1f8dcf62b5e0f4d37373a14ebf23c046f9f
|
||||
F src/shell.c.in 4d0ddf10c403710d241bf920163dcf032c21119aebb61e70840942c0eafecdf9
|
||||
F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
|
||||
F src/sqliteInt.h 5abdade4744cf3bd567afb65bb144bb3c61f6132f86813b995a5ca79c7b584e8
|
||||
F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
|
||||
F src/test1.c 51aa5f3030217ca45eb62e90944838794d4faaae7a8f60e0330ae01f30bc997b
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
||||
F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
|
||||
@@ -530,7 +532,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
|
||||
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
|
||||
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 5201422e2403e66a7a9c2b7d8df806acd8d2a0429822adb7e932f324e7b5b3c6
|
||||
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
|
||||
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
|
||||
@@ -558,34 +560,34 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97
|
||||
F src/treeview.c 2c5c4bc0a443401db5fd621542150452ddf5055d38edd4eef868bc2b6bfb0260
|
||||
F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
|
||||
F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b
|
||||
F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4
|
||||
F src/update.c 46dc24c6158446aaab45caee09b6d99327cb479268b83ffeb5b701823da3b67b
|
||||
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025
|
||||
F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55
|
||||
F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2
|
||||
F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
|
||||
F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
|
||||
F src/vdbeaux.c 3b0650dbebebb196010d8af830551e61ea7dcc0e414a2b747f897305b0bd0b8f
|
||||
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
|
||||
F src/vdbe.c d7a475cec51c83daf0d348301a1aec77f535832ea946632b5738ff9f087c0edb
|
||||
F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
|
||||
F src/vdbeInt.h d299d7a19853463dac418de0d97f2dd9cb4ddb495a45c93364e2daee109ba0ef
|
||||
F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
|
||||
F src/vdbeaux.c daecbbefaf0adfc428cddbfa5164c1d744496ba5dd19f840845ecac652913802
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d
|
||||
F src/vdbemem.c 803323406d8623a7619ea5d5f74016697eeaed19c02b98ce9c3013e77dbe1c38
|
||||
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
|
||||
F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
|
||||
F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
|
||||
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
|
||||
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
|
||||
F src/where.c 7dcb13bbcfd8c926546946556014c8f5aa0829eb8b65a6c18f8d187d265200a5
|
||||
F src/whereInt.h b09753e74bf92a8b17cf0e41ca94c44432c454544be6699b5311dcc57bf229c6
|
||||
F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
|
||||
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||
F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
|
||||
F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef
|
||||
@@ -625,7 +627,7 @@ F test/auth.test 3d6cd8f3978ba55b1202574e6ecd79c6e00914ca44b9bfd6c1fe6fb873fcac8
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
F test/autoinc.test 83aad64411583aac9ff0b629159ab4662029ab4e3f47090fce4efd132b304484
|
||||
F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22
|
||||
F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
|
||||
@@ -738,7 +740,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/csv01.test b99db7e57ee66fb3aa6e5d25af119003bee90bf679c5885711cbf7374f025b73
|
||||
F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58
|
||||
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
F test/cursorhint2.test 0078ae1ded4afcf5eb80d06e3a72b6e1c3f1a646aab26eeb583b0a9ec6f0d56e
|
||||
@@ -771,12 +773,12 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
|
||||
F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
|
||||
F test/e_fkey.test dcdc6ad26b1d4f07636208de4c1c22aae7c0597a685a6c10fe6da91f3191dd96
|
||||
F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da
|
||||
F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
|
||||
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
|
||||
F test/e_select.test 6fd45fd4a59ec82b6dda7468699dcc0ec1a72538577750b4f90357a62c1d2723
|
||||
F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
|
||||
@@ -965,6 +967,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08
|
||||
F test/in6.test 77c3e1d356d8aeb0864051f0677d3c0a032cf97b7f33a0ba8fa2b04a663f6b7b
|
||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -1050,7 +1053,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
|
||||
F test/malloc3.test 6e88bae6312854a4adb4ecc2a6a5ea8c59b4db778b724ba718e1c43fc8c3c136
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test f6eb6eca07a4c75f2897bf43a404689b6295bb95ab2e07d4b52eda743f925a27
|
||||
F test/malloc5.test 2e4ad7684a13389a44a840499cd47173a8d05f22f082d7d083eece433a7a64eb
|
||||
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
|
||||
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
|
||||
@@ -1087,7 +1090,7 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
|
||||
F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 567e223b6497da2226a0340befaf2d663c91ad57a48aede21a35a984a2882d41
|
||||
F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc
|
||||
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
|
||||
@@ -1128,7 +1131,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
||||
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
|
||||
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
|
||||
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
|
||||
F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
@@ -1171,7 +1174,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce146b79c x
|
||||
F test/resetdb.test 7fda92e443233208ec5e1825b176a9df63fb5bf962248e08b76eb4296c630cdf
|
||||
F test/resetdb.test 2107b34a8c437183f48eb833905df43818160a55f4ac69bbaf54f356fb2b27bd
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
|
||||
@@ -1211,7 +1214,7 @@ F test/select1.test 2e760bab8f3658b3b97debcf52860d0d2e20aa6cbe8b40e678ddb99871a1
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
@@ -1239,7 +1242,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 50154b0c4779df435b9e60ca60104b05f1cc217eab1aa383131359329e73d939
|
||||
F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
|
||||
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
@@ -1277,7 +1280,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c 20cc4028b0e88392b5a635c2ea5d5e777d569bf7258aead37f8be7a886c38344
|
||||
F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1583,7 +1586,7 @@ F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cf
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
||||
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
|
||||
F test/where.test f19ea3fa31c425b04af42c8b192a5b595ee84498df8d27dcd79ec043b25fbbfb
|
||||
F test/where.test 6bfcd29db193b814e5736832ffa899b4ff2969a106b718a79375063d5eb02b29
|
||||
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
|
||||
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
@@ -1659,7 +1662,7 @@ F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9
|
||||
F tool/mkkeywordhash.c 20f366ad3794e1db42e333a6f35fa41a024f2e3528579c9d58eb13eaa3ab4913
|
||||
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
|
||||
F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
|
||||
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
|
||||
@@ -1686,7 +1689,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
|
||||
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
|
||||
F tool/speed-check.sh 4ff9b095cf1a7643f0264e7fb7d23f0b12b7cce587a9de315877c378e90eeaf4
|
||||
F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
@@ -1728,7 +1731,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677
|
||||
R 95f9dad3dedc0c1d42618371aa8f363f
|
||||
P 439c8162272795b422a0e01b01b832fbc12b39914c9632a674162af8bdecff98
|
||||
R fe7d026f8be3134e2723fc39eeec5ed5
|
||||
U drh
|
||||
Z e422d7782a1b78611c0889726293f8af
|
||||
Z 8c642b57392b756fd19e94b953870085
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3
|
||||
4b0b4e14039469b656662312a5f80f086ede293e9ad04c7bc99a202b683a1e55
|
||||
+1
-1
@@ -142,7 +142,7 @@ static void renameParentFunc(
|
||||
}
|
||||
}
|
||||
|
||||
zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
|
||||
zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput);
|
||||
sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
|
||||
sqlite3DbFree(db, zOutput);
|
||||
}
|
||||
|
||||
+1
-1
@@ -150,6 +150,7 @@ void sqlite3AuthRead(
|
||||
int iDb; /* The index of the database the expression refers to */
|
||||
int iCol; /* Index of column in table */
|
||||
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
if( db->xAuth==0 ) return;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
|
||||
if( iDb<0 ){
|
||||
@@ -158,7 +159,6 @@ void sqlite3AuthRead(
|
||||
return;
|
||||
}
|
||||
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
if( pExpr->op==TK_TRIGGER ){
|
||||
pTab = pParse->pTriggerTab;
|
||||
}else{
|
||||
|
||||
+3
-3
@@ -382,7 +382,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** before this function exits.
|
||||
*/
|
||||
if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
|
||||
rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
|
||||
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
|
||||
bCloseTrans = 1;
|
||||
}
|
||||
|
||||
@@ -398,10 +398,10 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Lock the destination database, if it is not locked already. */
|
||||
if( SQLITE_OK==rc && p->bDestLocked==0
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
|
||||
(int*)&p->iDestSchema))
|
||||
){
|
||||
p->bDestLocked = 1;
|
||||
sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
|
||||
}
|
||||
|
||||
/* Do not allow backup if the destination database is in WAL mode
|
||||
|
||||
+19
-10
@@ -864,7 +864,11 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
|
||||
** back to where it ought to be if this routine returns true.
|
||||
*/
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
|
||||
return pCur->eState!=CURSOR_VALID;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pCur)
|
||||
|| pCur==sqlite3BtreeFakeValidCursor() );
|
||||
assert( offsetof(BtCursor, eState)==0 );
|
||||
assert( sizeof(pCur->eState)==1 );
|
||||
return CURSOR_VALID != *(u8*)pCur;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3296,7 +3300,7 @@ int sqlite3BtreeNewDb(Btree *p){
|
||||
** when A already has a read lock, we encourage A to give up and let B
|
||||
** proceed.
|
||||
*/
|
||||
int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
||||
int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
|
||||
BtShared *pBt = p->pBt;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
@@ -3424,12 +3428,17 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
||||
|
||||
|
||||
trans_begun:
|
||||
if( rc==SQLITE_OK && wrflag ){
|
||||
/* This call makes sure that the pager has the correct number of
|
||||
** open savepoints. If the second parameter is greater than 0 and
|
||||
** the sub-journal is not already open, then it will be opened here.
|
||||
*/
|
||||
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pSchemaVersion ){
|
||||
*pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
|
||||
}
|
||||
if( wrflag ){
|
||||
/* This call makes sure that the pager has the correct number of
|
||||
** open savepoints. If the second parameter is greater than 0 and
|
||||
** the sub-journal is not already open, then it will be opened here.
|
||||
*/
|
||||
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
|
||||
}
|
||||
}
|
||||
|
||||
btreeIntegrity(p);
|
||||
@@ -10080,11 +10089,11 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
||||
pBt->btsFlags &= ~BTS_NO_WAL;
|
||||
if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
|
||||
|
||||
rc = sqlite3BtreeBeginTrans(pBtree, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *aData = pBt->pPage1->aData;
|
||||
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
|
||||
rc = sqlite3BtreeBeginTrans(pBtree, 2);
|
||||
rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ int sqlite3BtreeGetOptimalReserve(Btree*);
|
||||
int sqlite3BtreeGetReserveNoMutex(Btree *p);
|
||||
int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
||||
int sqlite3BtreeGetAutoVacuum(Btree *);
|
||||
int sqlite3BtreeBeginTrans(Btree*,int);
|
||||
int sqlite3BtreeBeginTrans(Btree*,int,int*);
|
||||
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
|
||||
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
|
||||
int sqlite3BtreeCommit(Btree*);
|
||||
|
||||
+4
-2
@@ -2843,6 +2843,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3MultiWrite(pParse);
|
||||
|
||||
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
||||
@@ -2856,12 +2857,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
|
||||
if( IsUniqueIndex(pIndex) ){
|
||||
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
|
||||
sqlite3VdbeGoto(v, j2);
|
||||
int j2 = sqlite3VdbeGoto(v, 1);
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
|
||||
pIndex->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
}else{
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
|
||||
@@ -406,10 +406,12 @@ FuncDef *sqlite3FindFunction(
|
||||
if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
|
||||
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
|
||||
FuncDef *pOther;
|
||||
u8 *z;
|
||||
pBest->zName = (const char*)&pBest[1];
|
||||
pBest->nArg = (u16)nArg;
|
||||
pBest->funcFlags = enc;
|
||||
memcpy((char*)&pBest[1], zName, nName+1);
|
||||
for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z];
|
||||
pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);
|
||||
if( pOther==pBest ){
|
||||
sqlite3DbFree(db, pBest);
|
||||
|
||||
+1
-1
@@ -369,7 +369,7 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
|
||||
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+7
-4
@@ -553,13 +553,16 @@ void sqlite3DeleteFrom(
|
||||
if( IsVirtual(pTab) ){
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
sqlite3MayAbort(pParse);
|
||||
if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
if( eOnePass==ONEPASS_SINGLE ){
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iTabCur);
|
||||
if( sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
|
||||
+1
-1
@@ -3993,7 +3993,7 @@ expr_code_doover:
|
||||
case TK_COLLATE:
|
||||
case TK_UPLUS: {
|
||||
pExpr = pExpr->pLeft;
|
||||
goto expr_code_doover;
|
||||
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
|
||||
}
|
||||
|
||||
case TK_TRIGGER: {
|
||||
|
||||
@@ -331,6 +331,12 @@ static void fkLookupParent(
|
||||
int iCur = pParse->nTab - 1; /* Cursor number to use */
|
||||
int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
|
||||
|
||||
sqlite3VdbeVerifyAbortable(v,
|
||||
(!pFKey->isDeferred
|
||||
&& !(pParse->db->flags & SQLITE_DeferFKs)
|
||||
&& !pParse->pToplevel
|
||||
&& !pParse->isMultiWrite) ? OE_Abort : OE_Ignore);
|
||||
|
||||
/* If nIncr is less than zero, then check at runtime if there are any
|
||||
** outstanding constraints to resolve. If there are not, there is no need
|
||||
** to check if deleting this row resolves any outstanding violations.
|
||||
@@ -738,6 +744,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
||||
** constraints are violated.
|
||||
*/
|
||||
if( (db->flags & SQLITE_DeferFKs)==0 ){
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
|
||||
VdbeCoverage(v);
|
||||
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
|
||||
|
||||
+22
-1
@@ -226,11 +226,26 @@ static int autoIncBegin(
|
||||
Table *pTab /* The table we are writing to */
|
||||
){
|
||||
int memId = 0; /* Register holding maximum rowid */
|
||||
assert( pParse->db->aDb[iDb].pSchema!=0 );
|
||||
if( (pTab->tabFlags & TF_Autoincrement)!=0
|
||||
&& (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
|
||||
){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
AutoincInfo *pInfo;
|
||||
Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
|
||||
|
||||
/* Verify that the sqlite_sequence table exists and is an ordinary
|
||||
** rowid table with exactly two columns.
|
||||
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
|
||||
if( pSeqTab==0
|
||||
|| !HasRowid(pSeqTab)
|
||||
|| IsVirtual(pSeqTab)
|
||||
|| pSeqTab->nCol!=2
|
||||
){
|
||||
pParse->nErr++;
|
||||
pParse->rc = SQLITE_CORRUPT_SEQUENCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pInfo = pToplevel->pAinc;
|
||||
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
|
||||
@@ -1405,6 +1420,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
Expr *pExpr = pCheck->a[i].pExpr;
|
||||
if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
|
||||
allOk = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
|
||||
if( onError==OE_Ignore ){
|
||||
sqlite3VdbeGoto(v, ignoreDest);
|
||||
@@ -1514,6 +1530,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
/* Check to see if the new rowid already exists in the table. Skip
|
||||
** the following conflict logic if it does not. */
|
||||
VdbeNoopComment((v, "uniqueness check for ROWID"));
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
|
||||
VdbeCoverage(v);
|
||||
|
||||
@@ -1726,6 +1743,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
|
||||
/* Check to see if the new index entry will be unique */
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
|
||||
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
|
||||
|
||||
@@ -1812,10 +1830,12 @@ void sqlite3GenerateConstraintChecks(
|
||||
default: {
|
||||
Trigger *pTrigger = 0;
|
||||
assert( onError==OE_Replace );
|
||||
sqlite3MultiWrite(pParse);
|
||||
if( db->flags&SQLITE_RecTriggers ){
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
||||
}
|
||||
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
}
|
||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
regR, nPkField, 0, OE_Replace,
|
||||
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
|
||||
@@ -2335,6 +2355,7 @@ static int xferOptimization(
|
||||
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
||||
if( pDest->iPKey>=0 ){
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
|
||||
VdbeCoverage(v);
|
||||
sqlite3RowidConstraint(pParse, onError, pDest);
|
||||
|
||||
+37
-12
@@ -1808,11 +1808,13 @@ int sqlite3_create_function_v2(
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( xDestroy ){
|
||||
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
|
||||
pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor));
|
||||
if( !pArg ){
|
||||
sqlite3OomFault(db);
|
||||
xDestroy(p);
|
||||
goto out;
|
||||
}
|
||||
pArg->nRef = 0;
|
||||
pArg->xDestroy = xDestroy;
|
||||
pArg->pUserData = p;
|
||||
}
|
||||
@@ -1820,7 +1822,7 @@ int sqlite3_create_function_v2(
|
||||
if( pArg && pArg->nRef==0 ){
|
||||
assert( rc!=SQLITE_OK );
|
||||
xDestroy(p);
|
||||
sqlite3DbFree(db, pArg);
|
||||
sqlite3_free(pArg);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -1858,6 +1860,28 @@ int sqlite3_create_function16(
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
** wrong context. The sqlite3_overload_function() API might construct
|
||||
** SQL function that use this routine so that the functions will exist
|
||||
** for name resolution but are actually overloaded by the xFindFunction
|
||||
** method of virtual tables.
|
||||
*/
|
||||
static void sqlite3InvalidFunction(
|
||||
sqlite3_context *context, /* The function calling context */
|
||||
int NotUsed, /* Number of arguments to the function */
|
||||
sqlite3_value **NotUsed2 /* Value of each argument */
|
||||
){
|
||||
const char *zName = (const char*)sqlite3_user_data(context);
|
||||
char *zErr;
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
zErr = sqlite3_mprintf(
|
||||
"unable to use function %s in the requested context", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Declare that a function has been overloaded by a virtual table.
|
||||
**
|
||||
@@ -1875,7 +1899,8 @@ int sqlite3_overload_function(
|
||||
const char *zName,
|
||||
int nArg
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int rc;
|
||||
char *zCopy;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){
|
||||
@@ -1883,13 +1908,13 @@ int sqlite3_overload_function(
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){
|
||||
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
|
||||
0, sqlite3InvalidFunction, 0, 0, 0);
|
||||
}
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
if( rc ) return SQLITE_OK;
|
||||
zCopy = sqlite3_mprintf(zName);
|
||||
if( zCopy==0 ) return SQLITE_NOMEM;
|
||||
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
|
||||
zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
@@ -4090,7 +4115,7 @@ int sqlite3_snapshot_get(
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( 0==sqlite3BtreeIsInTrans(pBt) ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
|
||||
}
|
||||
@@ -4128,7 +4153,7 @@ int sqlite3_snapshot_open(
|
||||
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
|
||||
rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0);
|
||||
}
|
||||
}
|
||||
@@ -4160,7 +4185,7 @@ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
|
||||
sqlite3BtreeCommit(pBt);
|
||||
|
||||
+1
-1
@@ -3779,7 +3779,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
do{
|
||||
err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
|
||||
}while( err==EINTR );
|
||||
if( err ) return SQLITE_IOERR_WRITE;
|
||||
if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE;
|
||||
#else
|
||||
/* If the OS does not have posix_fallocate(), fake it. Write a
|
||||
** single byte to the last byte in each block that falls entirely
|
||||
|
||||
@@ -467,6 +467,7 @@ cmd ::= select(X). {
|
||||
}
|
||||
}
|
||||
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
select(A) ::= WITH wqlist(W) selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
@@ -487,6 +488,7 @@ select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
|
||||
}
|
||||
A = p;
|
||||
}
|
||||
%endif /* SQLITE_OMIT_CTE */
|
||||
select(A) ::= selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
|
||||
+5
-3
@@ -1564,6 +1564,11 @@ void sqlite3Pragma(
|
||||
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
|
||||
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
|
||||
if( !isQuick ){
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
}
|
||||
/* Verify that all NOT NULL columns really are NOT NULL */
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
char *zErr;
|
||||
@@ -1606,9 +1611,6 @@ void sqlite3Pragma(
|
||||
sqlite3ExprListDelete(db, pCheck);
|
||||
}
|
||||
if( !isQuick ){ /* Omit the remaining tests for quick_check */
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
|
||||
+2
-2
@@ -188,7 +188,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
** will be closed before this function returns. */
|
||||
sqlite3BtreeEnter(pDb->pBt);
|
||||
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
|
||||
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
|
||||
goto initone_error_out;
|
||||
@@ -433,7 +433,7 @@ static void schemaIsValid(Parse *pParse){
|
||||
** on the b-tree database, open one now. If a transaction is opened, it
|
||||
** will be closed immediately after reading the meta-value. */
|
||||
if( !sqlite3BtreeIsInReadTrans(pBt) ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
}
|
||||
|
||||
+1
-1
@@ -974,7 +974,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
** an SQLITE_NOMEM error.
|
||||
*/
|
||||
static sqlite3_str sqlite3OomStr = {
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
||||
};
|
||||
|
||||
/* Finalize a string created using sqlite3_str_new().
|
||||
|
||||
+24
-21
@@ -75,29 +75,31 @@ static void resolveAlias(
|
||||
assert( pOrig!=0 );
|
||||
db = pParse->db;
|
||||
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||
if( pDup==0 ) return;
|
||||
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
|
||||
if( pExpr->op==TK_COLLATE ){
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
||||
}
|
||||
ExprSetProperty(pDup, EP_Alias);
|
||||
if( pDup!=0 ){
|
||||
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
|
||||
if( pExpr->op==TK_COLLATE ){
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
||||
}
|
||||
ExprSetProperty(pDup, EP_Alias);
|
||||
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
** allowing it to be repopulated by the memcpy() on the following line.
|
||||
** The pExpr->u.zToken might point into memory that will be freed by the
|
||||
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
|
||||
** make a copy of the token before doing the sqlite3DbFree().
|
||||
*/
|
||||
ExprSetProperty(pExpr, EP_Static);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
memcpy(pExpr, pDup, sizeof(*pExpr));
|
||||
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
||||
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
pExpr->flags |= EP_MemToken;
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
** allowing it to be repopulated by the memcpy() on the following line.
|
||||
** The pExpr->u.zToken might point into memory that will be freed by the
|
||||
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
|
||||
** make a copy of the token before doing the sqlite3DbFree().
|
||||
*/
|
||||
ExprSetProperty(pExpr, EP_Static);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
memcpy(pExpr, pDup, sizeof(*pExpr));
|
||||
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
||||
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
pExpr->flags |= EP_MemToken;
|
||||
}
|
||||
sqlite3DbFree(db, pDup);
|
||||
}
|
||||
sqlite3DbFree(db, pDup);
|
||||
ExprSetProperty(pExpr, EP_Alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +351,7 @@ static int lookupName(
|
||||
testcase( iCol==(-1) );
|
||||
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
|
||||
eNewExprOp = TK_REGISTER;
|
||||
ExprSetProperty(pExpr, EP_Alias);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_UPSERT */
|
||||
{
|
||||
|
||||
+33
-6
@@ -817,7 +817,7 @@ static void selectExprDefer(
|
||||
if( pItem->u.x.iOrderByCol==0 ){
|
||||
Expr *pExpr = pItem->pExpr;
|
||||
Table *pTab = pExpr->pTab;
|
||||
if( pExpr->op==TK_COLUMN && pTab && !IsVirtual(pTab)
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
|
||||
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
|
||||
){
|
||||
int j;
|
||||
@@ -5100,11 +5100,17 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Update the accumulator memory cells for an aggregate based on
|
||||
** the current cursor position.
|
||||
**
|
||||
** If regAcc is non-zero and there are no min() or max() aggregates
|
||||
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
|
||||
** registers i register regAcc contains 0. The caller will take care
|
||||
** of setting and clearing regAcc.
|
||||
*/
|
||||
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
int regHit = 0;
|
||||
@@ -5168,6 +5174,9 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
** Another solution would be to change the OP_SCopy used to copy cached
|
||||
** values to an OP_Copy.
|
||||
*/
|
||||
if( regHit==0 && pAggInfo->nAccumulator ){
|
||||
regHit = regAcc;
|
||||
}
|
||||
if( regHit ){
|
||||
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
|
||||
}
|
||||
@@ -6021,8 +6030,6 @@ int sqlite3Select(
|
||||
pParse->nMem += pGroupBy->nExpr;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
|
||||
VdbeComment((v, "clear abort flag"));
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
|
||||
VdbeComment((v, "indicate accumulator empty"));
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
|
||||
|
||||
/* Begin a loop that will extract all source rows in GROUP BY order.
|
||||
@@ -6155,7 +6162,7 @@ int sqlite3Select(
|
||||
** the current row
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
updateAccumulator(pParse, &sAggInfo);
|
||||
updateAccumulator(pParse, iUseFlag, &sAggInfo);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
|
||||
VdbeComment((v, "indicate data in accumulator"));
|
||||
|
||||
@@ -6207,6 +6214,8 @@ int sqlite3Select(
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, addrReset);
|
||||
resetAccumulator(pParse, &sAggInfo);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
|
||||
VdbeComment((v, "indicate accumulator empty"));
|
||||
sqlite3VdbeAddOp1(v, OP_Return, regReset);
|
||||
|
||||
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
|
||||
@@ -6272,6 +6281,23 @@ int sqlite3Select(
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_BTREECOUNT */
|
||||
{
|
||||
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( sAggInfo.nAccumulator ){
|
||||
for(i=0; i<sAggInfo.nFunc; i++){
|
||||
if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
|
||||
}
|
||||
if( i==sAggInfo.nFunc ){
|
||||
regAcc = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
|
||||
}
|
||||
}
|
||||
|
||||
/* This case runs if the aggregate has no GROUP BY clause. The
|
||||
** processing is much simpler since there is only a single row
|
||||
** of output.
|
||||
@@ -6293,7 +6319,8 @@ int sqlite3Select(
|
||||
if( pWInfo==0 ){
|
||||
goto select_end;
|
||||
}
|
||||
updateAccumulator(pParse, &sAggInfo);
|
||||
updateAccumulator(pParse, regAcc, &sAggInfo);
|
||||
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
|
||||
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
|
||||
sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
|
||||
VdbeComment((v, "%s() by index",
|
||||
|
||||
+34
-15
@@ -2567,8 +2567,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
|
||||
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
|
||||
int iOp; /* Index of operation in p->aiIndent[] */
|
||||
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
|
||||
"NextIfOpen", "PrevIfOpen", 0 };
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
|
||||
"Rewind", 0 };
|
||||
const char *azGoto[] = { "Goto", 0 };
|
||||
@@ -2972,6 +2971,7 @@ static int shell_exec(
|
||||
/* Reprepare pStmt before reactiving trace modes */
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( pArg ) pArg->pStmt = pStmt;
|
||||
}
|
||||
restore_debug_trace_modes();
|
||||
}
|
||||
@@ -3656,6 +3656,17 @@ static void open_db(ShellState *p, int openFlags){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to close the databaes connection. Report errors.
|
||||
*/
|
||||
void close_db(sqlite3 *db){
|
||||
int rc = sqlite3_close(db);
|
||||
if( rc ){
|
||||
utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
|
||||
rc, sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_READLINE || HAVE_EDITLINE
|
||||
/*
|
||||
** Readline completion callbacks
|
||||
@@ -4236,7 +4247,7 @@ static void tryToClone(ShellState *p, const char *zNewDb){
|
||||
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
|
||||
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
|
||||
}
|
||||
sqlite3_close(newDb);
|
||||
close_db(newDb);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5273,7 +5284,8 @@ static int arExtractCommand(ArCommand *pAr){
|
||||
"SELECT "
|
||||
" ($dir || name),"
|
||||
" writefile(($dir || name), %s, mode, mtime) "
|
||||
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)";
|
||||
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
|
||||
" AND name NOT GLOB '*..[/\\]*'";
|
||||
|
||||
const char *azExtraArg[] = {
|
||||
"sqlar_uncompress(data, sz)",
|
||||
@@ -5553,7 +5565,7 @@ static int arDotCommand(
|
||||
}
|
||||
end_ar_command:
|
||||
if( cmd.db!=pState->db ){
|
||||
sqlite3_close(cmd.db);
|
||||
close_db(cmd.db);
|
||||
}
|
||||
sqlite3_free(cmd.zSrcTable);
|
||||
|
||||
@@ -5676,14 +5688,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
|
||||
if( rc!=SQLITE_OK ){
|
||||
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
|
||||
sqlite3_close(pDest);
|
||||
close_db(pDest);
|
||||
return 1;
|
||||
}
|
||||
open_db(p, 0);
|
||||
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
|
||||
if( pBackup==0 ){
|
||||
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
|
||||
sqlite3_close(pDest);
|
||||
close_db(pDest);
|
||||
return 1;
|
||||
}
|
||||
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
|
||||
@@ -5694,7 +5706,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
|
||||
rc = 1;
|
||||
}
|
||||
sqlite3_close(pDest);
|
||||
close_db(pDest);
|
||||
}else
|
||||
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
|
||||
@@ -6510,7 +6522,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int newFlag = 0; /* True to delete file before opening */
|
||||
/* Close the existing database */
|
||||
session_close_all(p);
|
||||
sqlite3_close(p->db);
|
||||
close_db(p->db);
|
||||
p->db = 0;
|
||||
p->zDbFilename = 0;
|
||||
sqlite3_free(p->zFreeOnClose);
|
||||
@@ -6690,14 +6702,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
rc = sqlite3_open(zSrcFile, &pSrc);
|
||||
if( rc!=SQLITE_OK ){
|
||||
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
|
||||
sqlite3_close(pSrc);
|
||||
close_db(pSrc);
|
||||
return 1;
|
||||
}
|
||||
open_db(p, 0);
|
||||
pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
|
||||
if( pBackup==0 ){
|
||||
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
sqlite3_close(pSrc);
|
||||
close_db(pSrc);
|
||||
return 1;
|
||||
}
|
||||
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
|
||||
@@ -6717,7 +6729,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
rc = 1;
|
||||
}
|
||||
sqlite3_close(pSrc);
|
||||
close_db(pSrc);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
|
||||
@@ -7401,7 +7413,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
initText(&s);
|
||||
open_db(p, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
if( rc ) return shellDatabaseError(p->db);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
return shellDatabaseError(p->db);
|
||||
}
|
||||
|
||||
if( nArg>2 && c=='i' ){
|
||||
/* It is an historical accident that the .indexes command shows an error
|
||||
@@ -7409,6 +7424,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
** command does not. */
|
||||
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
sqlite3_finalize(pStmt);
|
||||
goto meta_command_exit;
|
||||
}
|
||||
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
|
||||
@@ -8228,7 +8244,7 @@ static void usage(int showDetail){
|
||||
*/
|
||||
static void verify_uninitialized(void){
|
||||
if( sqlite3_config(-1)==SQLITE_MISUSE ){
|
||||
utf8_printf(stdout, "WARNING: attempt to configuration SQLite after"
|
||||
utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
|
||||
" initialization.\n");
|
||||
}
|
||||
}
|
||||
@@ -8754,7 +8770,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
set_table_name(&data, 0);
|
||||
if( data.db ){
|
||||
session_close_all(&data);
|
||||
sqlite3_close(data.db);
|
||||
close_db(data.db);
|
||||
}
|
||||
sqlite3_free(data.zFreeOnClose);
|
||||
find_home_dir(1);
|
||||
@@ -8765,5 +8781,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
for(i=0; i<argcToFree; i++) free(argvToFree[i]);
|
||||
free(argvToFree);
|
||||
#endif
|
||||
/* Clear the global data structure so that valgrind will detect memory
|
||||
** leaks */
|
||||
memset(&data, 0, sizeof(data));
|
||||
return rc;
|
||||
}
|
||||
|
||||
+10
-4
@@ -504,6 +504,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
@@ -511,6 +512,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
@@ -6292,6 +6294,10 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Scan Flags
|
||||
**
|
||||
** Virtual table implementations are allowed to set the
|
||||
** [sqlite3_index_info].idxFlags field to some combination of
|
||||
** these bits.
|
||||
*/
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
||||
|
||||
@@ -8533,11 +8539,11 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** method of a [virtual table], then it returns true if and only if the
|
||||
** column is being fetched as part of an UPDATE operation during which the
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a lighter-weight value to return that the corresponding [xUpdate] method
|
||||
** understands as a "no-change" value.
|
||||
** a return value that is less expensive to compute and that the corresponding
|
||||
** [xUpdate] method understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
** the column is not changed by the UPDATE statement, they the xColumn
|
||||
** the column is not changed by the UPDATE statement, then the xColumn
|
||||
** method can optionally return without setting a result, without calling
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
@@ -9032,7 +9038,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
||||
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
|
||||
** values of D and S.
|
||||
** The size of the database is written into *P even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
||||
** of the database exists.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
|
||||
+1
-1
@@ -4166,6 +4166,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
|
||||
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
|
||||
FuncDestructor *pDestructor
|
||||
);
|
||||
void sqlite3NoopDestructor(void*);
|
||||
void sqlite3OomFault(sqlite3*);
|
||||
void sqlite3OomClear(sqlite3*);
|
||||
int sqlite3ApiExit(sqlite3 *db, int);
|
||||
@@ -4268,7 +4269,6 @@ int sqlite3VtabCallConnect(Parse*, Table*);
|
||||
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ static int SQLITE_TCLAPI btree_begin_transaction(
|
||||
}
|
||||
pBt = sqlite3TestTextToPtr(argv[1]);
|
||||
sqlite3BtreeEnter(pBt);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 1);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
|
||||
sqlite3BtreeLeave(pBt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
|
||||
@@ -32,6 +32,8 @@ static struct MemFault {
|
||||
int nRepeat; /* Number of times to repeat the failure */
|
||||
int nBenign; /* Number of benign failures seen since last config */
|
||||
int nFail; /* Number of failures seen since last config */
|
||||
int nOkBefore; /* Successful allocations prior to the first fault */
|
||||
int nOkAfter; /* Successful allocations after a fault */
|
||||
u8 enable; /* True if enabled */
|
||||
int isInstalled; /* True if the fault simulation layer is installed */
|
||||
int isBenignMode; /* True if malloc failures are considered benign */
|
||||
@@ -47,18 +49,32 @@ static void sqlite3Fault(void){
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine exists as a place to set a breakpoint that will
|
||||
** fire the first time any malloc() fails on a single test case.
|
||||
** The sqlite3Fault() routine above runs on every malloc() failure.
|
||||
** This routine only runs on the first such failure.
|
||||
*/
|
||||
static void sqlite3FirstFault(void){
|
||||
static int cnt2 = 0;
|
||||
cnt2++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if a fault should be simulated. Return true to simulate
|
||||
** the fault. Return false if the fault should not be simulated.
|
||||
*/
|
||||
static int faultsimStep(void){
|
||||
if( likely(!memfault.enable) ){
|
||||
memfault.nOkAfter++;
|
||||
return 0;
|
||||
}
|
||||
if( memfault.iCountdown>0 ){
|
||||
memfault.iCountdown--;
|
||||
memfault.nOkBefore++;
|
||||
return 0;
|
||||
}
|
||||
if( memfault.nFail==0 ) sqlite3FirstFault();
|
||||
sqlite3Fault();
|
||||
memfault.nFail++;
|
||||
if( memfault.isBenignMode>0 ){
|
||||
@@ -133,6 +149,8 @@ static void faultsimConfig(int nDelay, int nRepeat){
|
||||
memfault.nRepeat = nRepeat;
|
||||
memfault.nBenign = 0;
|
||||
memfault.nFail = 0;
|
||||
memfault.nOkBefore = 0;
|
||||
memfault.nOkAfter = 0;
|
||||
memfault.enable = nDelay>=0;
|
||||
|
||||
/* Sometimes, when running multi-threaded tests, the isBenignMode
|
||||
|
||||
+9
-5
@@ -845,7 +845,7 @@ static void updateVirtualTable(
|
||||
int regRowid; /* Register for ephem table rowid */
|
||||
int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */
|
||||
int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */
|
||||
int bOnePass; /* True to use onepass strategy */
|
||||
int eOnePass; /* True to use onepass strategy */
|
||||
int addr; /* Address of OP_OpenEphemeral */
|
||||
|
||||
/* Allocate nArg registers in which to gather the arguments for VUpdate. Then
|
||||
@@ -890,12 +890,16 @@ static void updateVirtualTable(
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
|
||||
}
|
||||
|
||||
bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
|
||||
|
||||
if( bOnePass ){
|
||||
/* There is no ONEPASS_MULTI on virtual tables */
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
|
||||
if( eOnePass ){
|
||||
/* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
|
||||
** above. */
|
||||
sqlite3VdbeChangeToNoop(v, addr);
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
|
||||
}else{
|
||||
/* Create a record from the argument register contents and insert it into
|
||||
** the ephemeral table. */
|
||||
@@ -911,7 +915,7 @@ static void updateVirtualTable(
|
||||
}
|
||||
|
||||
|
||||
if( bOnePass==0 ){
|
||||
if( eOnePass==ONEPASS_OFF ){
|
||||
/* End the virtual table scan */
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
@@ -931,7 +935,7 @@ static void updateVirtualTable(
|
||||
|
||||
/* End of the ephemeral table scan. Or, if using the onepass strategy,
|
||||
** jump to here if the scan visited zero rows. */
|
||||
if( bOnePass==0 ){
|
||||
if( eOnePass==ONEPASS_OFF ){
|
||||
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
|
||||
|
||||
@@ -229,6 +229,7 @@ void sqlite3UpsertDoUpdate(
|
||||
VdbeComment((v, "%s.%s", pIdx->zName,
|
||||
pTab->aCol[pPk->aiColumn[i]].zName));
|
||||
}
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
|
||||
|
||||
+1
-1
@@ -224,7 +224,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
|
||||
*/
|
||||
rc = execSql(db, pzErrMsg, "BEGIN");
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
rc = sqlite3BtreeBeginTrans(pMain, 2);
|
||||
rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
/* Do not attempt to change the page size for a WAL database */
|
||||
|
||||
+171
-77
@@ -915,6 +915,9 @@ case OP_Yield: { /* in1, jump */
|
||||
*/
|
||||
case OP_HaltIfNull: { /* in3 */
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
if( (pIn3->flags & MEM_Null)==0 ) break;
|
||||
/* Fall through into OP_Halt */
|
||||
}
|
||||
@@ -954,6 +957,9 @@ case OP_Halt: {
|
||||
int pcx;
|
||||
|
||||
pcx = (int)(pOp - aOp);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
if( pOp->p1==SQLITE_OK && p->pFrame ){
|
||||
/* Halt the sub-program. Return control to the parent frame. */
|
||||
pFrame = p->pFrame;
|
||||
@@ -3196,8 +3202,7 @@ case OP_AutoCommit: {
|
||||
*/
|
||||
case OP_Transaction: {
|
||||
Btree *pBt;
|
||||
int iMeta;
|
||||
int iGen;
|
||||
int iMeta = 0;
|
||||
|
||||
assert( p->bIsReader );
|
||||
assert( p->readOnly==0 || pOp->p2==0 );
|
||||
@@ -3210,7 +3215,7 @@ case OP_Transaction: {
|
||||
pBt = db->aDb[pOp->p1].pBt;
|
||||
|
||||
if( pBt ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
|
||||
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
|
||||
testcase( rc==SQLITE_BUSY_SNAPSHOT );
|
||||
testcase( rc==SQLITE_BUSY_RECOVERY );
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -3243,19 +3248,17 @@ case OP_Transaction: {
|
||||
p->nStmtDefCons = db->nDeferredCons;
|
||||
p->nStmtDefImmCons = db->nDeferredImmCons;
|
||||
}
|
||||
|
||||
/* Gather the schema version number for checking:
|
||||
}
|
||||
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
|
||||
if( pOp->p5
|
||||
&& (iMeta!=pOp->p3
|
||||
|| db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
|
||||
){
|
||||
/*
|
||||
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
|
||||
** version is checked to ensure that the schema has not changed since the
|
||||
** SQL statement was prepared.
|
||||
*/
|
||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
||||
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
|
||||
}else{
|
||||
iGen = iMeta = 0;
|
||||
}
|
||||
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
|
||||
if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
|
||||
/* If the schema-cookie from the database file matches the cookie
|
||||
@@ -3324,6 +3327,8 @@ case OP_ReadCookie: { /* out2 */
|
||||
*/
|
||||
case OP_SetCookie: {
|
||||
Db *pDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
assert( pOp->p2<SQLITE_N_BTREE_META );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
@@ -3362,59 +3367,78 @@ case OP_SetCookie: {
|
||||
** values need not be contiguous but all P1 values should be small integers.
|
||||
** It is an error for P1 to be negative.
|
||||
**
|
||||
** If P5!=0 then use the content of register P2 as the root page, not
|
||||
** the value of P2 itself.
|
||||
**
|
||||
** There will be a read lock on the database whenever there is an
|
||||
** open cursor. If the database was unlocked prior to this instruction
|
||||
** then a read lock is acquired as part of this instruction. A read
|
||||
** lock allows other processes to read the database but prohibits
|
||||
** any other process from modifying the database. The read lock is
|
||||
** released when all cursors are closed. If this instruction attempts
|
||||
** to get a read lock but fails, the script terminates with an
|
||||
** SQLITE_BUSY error code.
|
||||
** Allowed P5 bits:
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** </ul>
|
||||
**
|
||||
** The P4 value may be either an integer (P4_INT32) or a pointer to
|
||||
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
|
||||
** structure, then said structure defines the content and collating
|
||||
** sequence of the index being opened. Otherwise, if P4 is an integer
|
||||
** value, it is set to the number of columns in the table.
|
||||
** object, then table being opened must be an [index b-tree] where the
|
||||
** KeyInfo object defines the content and collating
|
||||
** sequence of that index b-tree. Otherwise, if P4 is an integer
|
||||
** value, then the table being opened must be a [table b-tree] with a
|
||||
** number of columns no less than the value of P4.
|
||||
**
|
||||
** See also: OpenWrite, ReopenIdx
|
||||
*/
|
||||
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
|
||||
** Synopsis: root=P2 iDb=P3
|
||||
**
|
||||
** The ReopenIdx opcode works exactly like ReadOpen except that it first
|
||||
** checks to see if the cursor on P1 is already open with a root page
|
||||
** number of P2 and if it is this opcode becomes a no-op. In other words,
|
||||
** The ReopenIdx opcode works like OP_OpenRead except that it first
|
||||
** checks to see if the cursor on P1 is already open on the same
|
||||
** b-tree and if it is this opcode becomes a no-op. In other words,
|
||||
** if the cursor is already open, do not reopen it.
|
||||
**
|
||||
** The ReopenIdx opcode may only be used with P5==0 and with P4 being
|
||||
** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
|
||||
** every other ReopenIdx or OpenRead for the same cursor number.
|
||||
** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ
|
||||
** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must
|
||||
** be the same as every other ReopenIdx or OpenRead for the same cursor
|
||||
** number.
|
||||
**
|
||||
** See the OpenRead opcode documentation for additional information.
|
||||
** Allowed P5 bits:
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** </ul>
|
||||
**
|
||||
** See also: OP_OpenRead, OP_OpenWrite
|
||||
*/
|
||||
/* Opcode: OpenWrite P1 P2 P3 P4 P5
|
||||
** Synopsis: root=P2 iDb=P3
|
||||
**
|
||||
** Open a read/write cursor named P1 on the table or index whose root
|
||||
** page is P2. Or if P5!=0 use the content of register P2 to find the
|
||||
** root page.
|
||||
** page is P2 (or whose root page is held in register P2 if the
|
||||
** OPFLAG_P2ISREG bit is set in P5 - see below).
|
||||
**
|
||||
** The P4 value may be either an integer (P4_INT32) or a pointer to
|
||||
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
|
||||
** structure, then said structure defines the content and collating
|
||||
** sequence of the index being opened. Otherwise, if P4 is an integer
|
||||
** value, it is set to the number of columns in the table, or to the
|
||||
** largest index of any column of the table that is actually used.
|
||||
** object, then table being opened must be an [index b-tree] where the
|
||||
** KeyInfo object defines the content and collating
|
||||
** sequence of that index b-tree. Otherwise, if P4 is an integer
|
||||
** value, then the table being opened must be a [table b-tree] with a
|
||||
** number of columns no less than the value of P4.
|
||||
**
|
||||
** This instruction works just like OpenRead except that it opens the cursor
|
||||
** in read/write mode. For a given table, there can be one or more read-only
|
||||
** cursors or a single read/write cursor but not both.
|
||||
** Allowed P5 bits:
|
||||
** <ul>
|
||||
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
||||
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
||||
** of OP_SeekLE/OP_IdxGT)
|
||||
** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
|
||||
** and subsequently delete entries in an index btree. This is a
|
||||
** hint to the storage engine that the storage engine is allowed to
|
||||
** ignore. The hint is not used by the official SQLite b*tree storage
|
||||
** engine, but is used by COMDB2.
|
||||
** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2
|
||||
** as the root page, not the value of P2 itself.
|
||||
** </ul>
|
||||
**
|
||||
** See also OpenRead.
|
||||
** This instruction works like OpenRead except that it opens the cursor
|
||||
** in read/write mode.
|
||||
**
|
||||
** See also: OP_OpenRead, OP_ReopenIdx
|
||||
*/
|
||||
case OP_ReopenIdx: {
|
||||
int nField;
|
||||
@@ -3470,6 +3494,7 @@ case OP_OpenWrite:
|
||||
if( pOp->p5 & OPFLAG_P2ISREG ){
|
||||
assert( p2>0 );
|
||||
assert( p2<=(p->nMem+1 - p->nCursor) );
|
||||
assert( pOp->opcode==OP_OpenWrite );
|
||||
pIn2 = &aMem[p2];
|
||||
assert( memIsValid(pIn2) );
|
||||
assert( (pIn2->flags & MEM_Int)!=0 );
|
||||
@@ -3598,7 +3623,7 @@ case OP_OpenEphemeral: {
|
||||
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
|
||||
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
|
||||
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If a transient index is required, create it by calling
|
||||
@@ -4006,6 +4031,25 @@ seek_not_found:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SeekHit P1 P2 * * *
|
||||
** Synopsis: seekHit=P2
|
||||
**
|
||||
** Set the seekHit flag on cursor P1 to the value in P2.
|
||||
** The seekHit flag is used by the IfNoHope opcode.
|
||||
**
|
||||
** P1 must be a valid b-tree cursor. P2 must be a boolean value,
|
||||
** either 0 or 1.
|
||||
*/
|
||||
case OP_SeekHit: {
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pOp->p2==0 || pOp->p2==1 );
|
||||
pC->seekHit = pOp->p2 & 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Found P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
@@ -4040,7 +4084,34 @@ seek_not_found:
|
||||
** advanced in either direction. In other words, the Next and Prev
|
||||
** opcodes do not work after this operation.
|
||||
**
|
||||
** See also: Found, NotExists, NoConflict
|
||||
** See also: Found, NotExists, NoConflict, IfNoHope
|
||||
*/
|
||||
/* Opcode: IfNoHope P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
** Register P3 is the first of P4 registers that form an unpacked
|
||||
** record.
|
||||
**
|
||||
** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
|
||||
** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
|
||||
** check to see if there is any entry in P1 that matches the
|
||||
** prefix identified by P3 and P4. If no entry matches the prefix,
|
||||
** jump to P2. Otherwise fall through.
|
||||
**
|
||||
** This opcode behaves like OP_NotFound if the seekHit
|
||||
** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
|
||||
**
|
||||
** This opcode is used in IN clause processing for a multi-column key.
|
||||
** If an IN clause is attached to an element of the key other than the
|
||||
** left-most element, and if there are no matches on the most recent
|
||||
** seek over the whole key, then it might be that one of the key element
|
||||
** to the left is prohibiting a match, and hence there is "no hope" of
|
||||
** any match regardless of how many IN clause elements are checked.
|
||||
** In such a case, we abandon the IN clause search early, using this
|
||||
** opcode. The opcode name comes from the fact that the
|
||||
** jump is taken if there is "no hope" of achieving a match.
|
||||
**
|
||||
** See also: NotFound, SeekHit
|
||||
*/
|
||||
/* Opcode: NoConflict P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
@@ -4065,6 +4136,14 @@ seek_not_found:
|
||||
**
|
||||
** See also: NotFound, Found, NotExists
|
||||
*/
|
||||
case OP_IfNoHope: { /* jump, in3 */
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
if( pC->seekHit ) break;
|
||||
/* Fall through into OP_NotFound */
|
||||
}
|
||||
case OP_NoConflict: /* jump, in3 */
|
||||
case OP_NotFound: /* jump, in3 */
|
||||
case OP_Found: { /* jump, in3 */
|
||||
@@ -4213,7 +4292,7 @@ case OP_NotExists: /* jump, in3 */
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
#ifdef SQLITE_DEBUG
|
||||
pC->seekOp = 0;
|
||||
pC->seekOp = OP_SeekRowid;
|
||||
#endif
|
||||
assert( pC->isTable );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
@@ -4287,11 +4366,8 @@ case OP_NewRowid: { /* out2 */
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
if( !pC->isTable ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
assert( pC!=0 );
|
||||
assert( pC->isTable );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pC->uc.pCursor!=0 );
|
||||
{
|
||||
@@ -4460,6 +4536,7 @@ case OP_InsertInt: {
|
||||
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
|
||||
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
|
||||
REGISTER_TRACE(pOp->p2, pData);
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
|
||||
if( pOp->opcode==OP_Insert ){
|
||||
pKey = &aMem[pOp->p3];
|
||||
@@ -4574,6 +4651,7 @@ case OP_Delete: {
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pC->uc.pCursor!=0 );
|
||||
assert( pC->deferredMoveto==0 );
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
|
||||
@@ -4742,10 +4820,10 @@ case OP_SorterData: {
|
||||
** If the P1 cursor must be pointing to a valid row (not a NULL row)
|
||||
** of a real table, not a pseudo-table.
|
||||
**
|
||||
** If P3!=0 then this opcode is allowed to make an ephermeral pointer
|
||||
** If P3!=0 then this opcode is allowed to make an ephemeral pointer
|
||||
** into the database page. That means that the content of the output
|
||||
** register will be invalidated as soon as the cursor moves - including
|
||||
** moves caused by other cursors that "save" the the current cursors
|
||||
** moves caused by other cursors that "save" the current cursors
|
||||
** position in order that they can write to the same table. If P3==0
|
||||
** then a copy of the data is made into memory. P3!=0 is faster, but
|
||||
** P3==0 is safer.
|
||||
@@ -4868,6 +4946,9 @@ case OP_NullRow: {
|
||||
assert( pC->uc.pCursor!=0 );
|
||||
sqlite3BtreeClearCursor(pC->uc.pCursor);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5054,12 +5135,7 @@ case OP_Rewind: { /* jump */
|
||||
** If P5 is positive and the jump is taken, then event counter
|
||||
** number P5-1 in the prepared statement is incremented.
|
||||
**
|
||||
** See also: Prev, NextIfOpen
|
||||
*/
|
||||
/* Opcode: NextIfOpen P1 P2 P3 P4 P5
|
||||
**
|
||||
** This opcode works just like Next except that if cursor P1 is not
|
||||
** open it behaves a no-op.
|
||||
** See also: Prev
|
||||
*/
|
||||
/* Opcode: Prev P1 P2 P3 P4 P5
|
||||
**
|
||||
@@ -5087,11 +5163,6 @@ case OP_Rewind: { /* jump */
|
||||
** If P5 is positive and the jump is taken, then event counter
|
||||
** number P5-1 in the prepared statement is incremented.
|
||||
*/
|
||||
/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
|
||||
**
|
||||
** This opcode works just like Prev except that if cursor P1 is not
|
||||
** open it behaves a no-op.
|
||||
*/
|
||||
/* Opcode: SorterNext P1 P2 * * P5
|
||||
**
|
||||
** This opcode works just like OP_Next except that P1 must be a
|
||||
@@ -5106,10 +5177,6 @@ case OP_SorterNext: { /* jump */
|
||||
assert( isSorter(pC) );
|
||||
rc = sqlite3VdbeSorterNext(db, pC);
|
||||
goto next_tail;
|
||||
case OP_PrevIfOpen: /* jump */
|
||||
case OP_NextIfOpen: /* jump */
|
||||
if( p->apCsr[pOp->p1]==0 ) break;
|
||||
/* Fall through */
|
||||
case OP_Prev: /* jump */
|
||||
case OP_Next: /* jump */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
@@ -5120,17 +5187,17 @@ case OP_Next: /* jump */
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
|
||||
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||
assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
|
||||
|
||||
/* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
|
||||
/* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found.
|
||||
** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
|
||||
assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
|
||||
assert( pOp->opcode!=OP_Next
|
||||
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|
||||
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
|
||||
assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
|
||||
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|
||||
|| pC->seekOp==OP_NullRow);
|
||||
assert( pOp->opcode!=OP_Prev
|
||||
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|
||||
|| pC->seekOp==OP_Last );
|
||||
|| pC->seekOp==OP_Last
|
||||
|| pC->seekOp==OP_NullRow);
|
||||
|
||||
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
|
||||
next_tail:
|
||||
@@ -5192,6 +5259,7 @@ case OP_IdxInsert: { /* in2 */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
assert( pC!=0 );
|
||||
assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
@@ -5238,6 +5306,7 @@ case OP_IdxDelete: {
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
pCrsr = pC->uc.pCursor;
|
||||
assert( pCrsr!=0 );
|
||||
assert( pOp->p5==0 );
|
||||
@@ -5460,6 +5529,7 @@ case OP_Destroy: { /* out2 */
|
||||
int iMoved;
|
||||
int iDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
assert( p->readOnly==0 );
|
||||
assert( pOp->p1>1 );
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
@@ -5509,6 +5579,7 @@ case OP_Destroy: { /* out2 */
|
||||
case OP_Clear: {
|
||||
int nChange;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
nChange = 0;
|
||||
assert( p->readOnly==0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p2) );
|
||||
@@ -5558,13 +5629,14 @@ case OP_ResetSorter: {
|
||||
** Allocate a new b-tree in the main database file if P1==0 or in the
|
||||
** TEMP database file if P1==1 or in an attached database if
|
||||
** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
|
||||
** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table.
|
||||
** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
|
||||
** The root page number of the new b-tree is stored in register P2.
|
||||
*/
|
||||
case OP_CreateBtree: { /* out2 */
|
||||
int pgno;
|
||||
Db *pDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
pgno = 0;
|
||||
assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
|
||||
@@ -5584,6 +5656,7 @@ case OP_CreateBtree: { /* out2 */
|
||||
** Run the SQL statement or statements specified in the P4 string.
|
||||
*/
|
||||
case OP_SqlExec: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
db->nSqlExec++;
|
||||
rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
|
||||
db->nSqlExec--;
|
||||
@@ -5673,6 +5746,7 @@ case OP_LoadAnalysis: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTable: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -5686,6 +5760,7 @@ case OP_DropTable: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropIndex: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -5699,6 +5774,7 @@ case OP_DropIndex: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTrigger: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -6745,7 +6821,7 @@ case OP_VFilter: { /* jump */
|
||||
** If the VColumn opcode is being used to fetch the value of
|
||||
** an unchanging column during an UPDATE operation, then the P5
|
||||
** value is 1. Otherwise, P5 is 0. The P5 value is returned
|
||||
** by sqlite3_vtab_nochange() routine can can be used
|
||||
** by sqlite3_vtab_nochange() routine and can be used
|
||||
** by virtual table implementations to return special "no-change"
|
||||
** marks which can be more efficient, depending on the virtual table.
|
||||
*/
|
||||
@@ -6908,6 +6984,7 @@ case OP_VUpdate: {
|
||||
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
|
||||
);
|
||||
assert( p->readOnly==0 );
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
pVtab = pOp->p4.pVtab->pVtab;
|
||||
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
|
||||
rc = SQLITE_LOCKED;
|
||||
@@ -7225,6 +7302,22 @@ case OP_CursorHint: {
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Opcode: Abortable * * * * *
|
||||
**
|
||||
** Verify that an Abort can happen. Assert if an Abort at this point
|
||||
** might cause database corruption. This opcode only appears in debugging
|
||||
** builds.
|
||||
**
|
||||
** An Abort is safe if either there have been no writes, or if there is
|
||||
** an active statement journal.
|
||||
*/
|
||||
case OP_Abortable: {
|
||||
sqlite3VdbeAssertAbortable(p);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: Noop * * * * *
|
||||
**
|
||||
** Do nothing. This instruction is often useful as a jump
|
||||
@@ -7236,8 +7329,9 @@ case OP_CursorHint: {
|
||||
** This opcode records information from the optimizer. It is the
|
||||
** the same as a no-op. This opcodesnever appears in a real VM program.
|
||||
*/
|
||||
default: { /* This is really OP_Noop and OP_Explain */
|
||||
default: { /* This is really OP_Noop, OP_Explain */
|
||||
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,11 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
||||
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
|
||||
# define sqlite3VdbeVerifyNoResultRow(A)
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG)
|
||||
void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
|
||||
#else
|
||||
# define sqlite3VdbeVerifyAbortable(A,B)
|
||||
#endif
|
||||
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
void sqlite3VdbeExplain(Parse*,u8,const char*,...);
|
||||
|
||||
@@ -85,6 +85,7 @@ struct VdbeCursor {
|
||||
Bool isEphemeral:1; /* True for an ephemeral table */
|
||||
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
|
||||
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
|
||||
Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
|
||||
Btree *pBtx; /* Separate file holding temporary table */
|
||||
i64 seqCount; /* Sequence counter */
|
||||
int *aAltMap; /* Mapping from table to index column numbers */
|
||||
@@ -379,6 +380,7 @@ struct Vdbe {
|
||||
int nOp; /* Number of instructions in the program */
|
||||
#ifdef SQLITE_DEBUG
|
||||
int rcApp; /* errcode set by sqlite3_result_error_code() */
|
||||
u32 nWrite; /* Number of write operations that have occurred */
|
||||
#endif
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
@@ -514,6 +516,14 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
|
||||
void sqlite3VdbeAssertAbortable(Vdbe*);
|
||||
#else
|
||||
# define sqlite3VdbeIncrWriteCounter(V,C)
|
||||
# define sqlite3VdbeAssertAbortable(V)
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE)
|
||||
void sqlite3VdbeEnter(Vdbe*);
|
||||
#else
|
||||
|
||||
@@ -787,28 +787,6 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
||||
return *piTime;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
** wrong context. The sqlite3_overload_function() API might construct
|
||||
** SQL function that use this routine so that the functions will exist
|
||||
** for name resolution but are actually overloaded by the xFindFunction
|
||||
** method of virtual tables.
|
||||
*/
|
||||
void sqlite3InvalidFunction(
|
||||
sqlite3_context *context, /* The function calling context */
|
||||
int NotUsed, /* Number of arguments to the function */
|
||||
sqlite3_value **NotUsed2 /* Value of each argument */
|
||||
){
|
||||
const char *zName = context->pFunc->zName;
|
||||
char *zErr;
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
zErr = sqlite3_mprintf(
|
||||
"unable to use function %s in the requested context", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new aggregate context for p and return a pointer to
|
||||
** its pMem->z element.
|
||||
|
||||
+48
-9
@@ -603,6 +603,32 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
||||
}
|
||||
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Increment the nWrite counter in the VDBE if the cursor is not an
|
||||
** ephemeral cursor, or if the cursor argument is NULL.
|
||||
*/
|
||||
void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){
|
||||
if( pC==0
|
||||
|| (pC->eCurType!=CURTYPE_SORTER
|
||||
&& pC->eCurType!=CURTYPE_PSEUDO
|
||||
&& !pC->isEphemeral)
|
||||
){
|
||||
p->nWrite++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Assert if an Abort at this point in time might result in a corrupt
|
||||
** database.
|
||||
*/
|
||||
void sqlite3VdbeAssertAbortable(Vdbe *p){
|
||||
assert( p->nWrite==0 || p->usesStmtJournal );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine is called after all opcodes have been inserted. It loops
|
||||
** through all the opcodes and fixes up some details.
|
||||
@@ -663,7 +689,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
break;
|
||||
}
|
||||
case OP_Next:
|
||||
case OP_NextIfOpen:
|
||||
case OP_SorterNext: {
|
||||
pOp->p4.xAdvance = sqlite3BtreeNext;
|
||||
pOp->p4type = P4_ADVANCE;
|
||||
@@ -673,8 +698,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
assert( pOp->p2>=0 );
|
||||
break;
|
||||
}
|
||||
case OP_Prev:
|
||||
case OP_PrevIfOpen: {
|
||||
case OP_Prev: {
|
||||
pOp->p4.xAdvance = sqlite3BtreePrevious;
|
||||
pOp->p4type = P4_ADVANCE;
|
||||
/* The code generator never codes any of these opcodes as a jump
|
||||
@@ -762,6 +786,17 @@ void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Generate code (a single OP_Abortable opcode) that will
|
||||
** verify that the VDBE program can safely call Abort in the current
|
||||
** context.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG)
|
||||
void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){
|
||||
if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function returns a pointer to the array of opcodes associated with
|
||||
** the Vdbe passed as the first argument. It is the callers responsibility
|
||||
@@ -2995,6 +3030,9 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->nWrite = 0;
|
||||
#endif
|
||||
|
||||
/* Save profiling information from this VDBE run.
|
||||
*/
|
||||
@@ -4089,7 +4127,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
u32 idx1; /* Offset of first type in header */
|
||||
int rc = 0; /* Return value */
|
||||
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
|
||||
KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
|
||||
KeyInfo *pKeyInfo;
|
||||
const unsigned char *aKey1 = (const unsigned char *)pKey1;
|
||||
Mem mem1;
|
||||
|
||||
@@ -4184,7 +4222,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
if( (d1+mem1.n) > (unsigned)nKey1 ){
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else if( pKeyInfo->aColl[i] ){
|
||||
}else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
|
||||
mem1.enc = pKeyInfo->enc;
|
||||
mem1.db = pKeyInfo->db;
|
||||
mem1.flags = MEM_Str;
|
||||
@@ -4235,7 +4273,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
}
|
||||
|
||||
if( rc!=0 ){
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
if( pPKey2->pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc;
|
||||
}
|
||||
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
|
||||
@@ -4244,10 +4282,11 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
}
|
||||
|
||||
i++;
|
||||
if( i==pPKey2->nField ) break;
|
||||
pRhs++;
|
||||
d1 += sqlite3VdbeSerialTypeLen(serial_type);
|
||||
idx1 += sqlite3VarintLen(serial_type);
|
||||
}while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
|
||||
}while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 );
|
||||
|
||||
/* No memory allocation is ever used on mem1. Prove this using
|
||||
** the following assert(). If the assert() fails, it indicates a
|
||||
@@ -4259,7 +4298,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
** value. */
|
||||
assert( CORRUPT_DB
|
||||
|| vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
|
||||
|| pKeyInfo->db->mallocFailed
|
||||
|| pPKey2->pKeyInfo->db->mallocFailed
|
||||
);
|
||||
pPKey2->eqSeen = 1;
|
||||
return pPKey2->default_rc;
|
||||
@@ -4585,7 +4624,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
|
||||
*res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
|
||||
sqlite3VdbeMemRelease(&m);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+1
-1
@@ -800,7 +800,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
}
|
||||
|
||||
/* A no-op destructor */
|
||||
static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
|
||||
void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
|
||||
|
||||
/*
|
||||
** Set the value stored in *pMem should already be a NULL.
|
||||
|
||||
+13
-10
@@ -1049,9 +1049,6 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
void *pArg = 0;
|
||||
FuncDef *pNew;
|
||||
int rc = 0;
|
||||
char *zLowerName;
|
||||
unsigned char *z;
|
||||
|
||||
|
||||
/* Check to see the left operand is a column in a virtual table */
|
||||
if( NEVER(pExpr==0) ) return pDef;
|
||||
@@ -1066,16 +1063,22 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
if( pMod->xFindFunction==0 ) return pDef;
|
||||
|
||||
/* Call the xFindFunction method on the virtual table implementation
|
||||
** to see if the implementation wants to overload this function
|
||||
** to see if the implementation wants to overload this function.
|
||||
**
|
||||
** Though undocumented, we have historically always invoked xFindFunction
|
||||
** with an all lower-case function name. Continue in this tradition to
|
||||
** avoid any chance of an incompatibility.
|
||||
*/
|
||||
zLowerName = sqlite3DbStrDup(db, pDef->zName);
|
||||
if( zLowerName ){
|
||||
for(z=(unsigned char*)zLowerName; *z; z++){
|
||||
*z = sqlite3UpperToLower[*z];
|
||||
#ifdef SQLITE_DEBUG
|
||||
{
|
||||
int i;
|
||||
for(i=0; pDef->zName[i]; i++){
|
||||
unsigned char x = (unsigned char)pDef->zName[i];
|
||||
assert( x==sqlite3UpperToLower[x] );
|
||||
}
|
||||
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg);
|
||||
sqlite3DbFree(db, zLowerName);
|
||||
}
|
||||
#endif
|
||||
rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg);
|
||||
if( rc==0 ){
|
||||
return pDef;
|
||||
}
|
||||
|
||||
+9
-2
@@ -5083,10 +5083,17 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
|
||||
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
|
||||
if( pIn->eEndLoopOp!=OP_Noop ){
|
||||
if( pIn->nPrefix ){
|
||||
assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
|
||||
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2,
|
||||
pIn->iBase, pIn->nPrefix);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,8 @@ struct WhereLevel {
|
||||
struct InLoop {
|
||||
int iCur; /* The VDBE cursor used by this IN operator */
|
||||
int addrInTop; /* Top of the IN loop */
|
||||
int iBase; /* Base register of multi-key index record */
|
||||
int nPrefix; /* Number of prior entires in the key */
|
||||
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
|
||||
} *aInLoop; /* Information about each nested IN operator */
|
||||
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
|
||||
@@ -555,3 +557,4 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
||||
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
|
||||
#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 */
|
||||
|
||||
+15
-1
@@ -591,7 +591,14 @@ static int codeEqualityTerm(
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
||||
if( i==iEq ){
|
||||
pIn->iCur = iTab;
|
||||
pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
|
||||
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
||||
if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
||||
pIn->iBase = iReg - i;
|
||||
pIn->nPrefix = i;
|
||||
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
||||
}else{
|
||||
pIn->nPrefix = 0;
|
||||
}
|
||||
}else{
|
||||
pIn->eEndLoopOp = OP_Noop;
|
||||
}
|
||||
@@ -1658,6 +1665,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** above has already left the cursor sitting on the correct row,
|
||||
** so no further seeking is needed */
|
||||
}else{
|
||||
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
|
||||
sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
|
||||
}
|
||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||
assert( op!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
||||
@@ -1721,6 +1731,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
|
||||
}
|
||||
|
||||
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
|
||||
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
|
||||
}
|
||||
|
||||
/* Seek the table cursor, if required */
|
||||
if( omitTable ){
|
||||
/* pIdx is a covering index. No need to access the main table. */
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ do_test aggnested-2.0 {
|
||||
t1.*
|
||||
FROM t1;
|
||||
}
|
||||
} {A,B,B 3 33 333 3333}
|
||||
} {A,B,B 1 11 111 1111}
|
||||
db2 close
|
||||
|
||||
##################### Test cases for ticket [bfbf38e5e9956ac69f] ############
|
||||
|
||||
@@ -25,6 +25,11 @@ ifcapable {!autoinc} {
|
||||
return
|
||||
}
|
||||
|
||||
if {[permutation]=="inmemory_journal"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
|
||||
# The database is initially empty.
|
||||
@@ -684,4 +689,164 @@ do_execsql_test autoinc-11.1 {
|
||||
SELECT seq FROM sqlite_sequence WHERE name='t11';
|
||||
} {5}
|
||||
|
||||
# 2018-05-23 ticket d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c
|
||||
# Does not crash if the sqlite_sequence table schema is missing
|
||||
# or corrupt.
|
||||
#
|
||||
do_test autoinc-12.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql=replace(sql,'fake_','sqlite_'),
|
||||
name='sqlite_sequence',
|
||||
tbl_name='sqlite_sequence'
|
||||
WHERE name='fake_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test autoinc-12.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql=replace(sql,'sqlite_','x_'),
|
||||
name='x_sequence',
|
||||
tbl_name='x_sequence'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
ifcapable vtab {
|
||||
set err "database disk image is malformed"
|
||||
} else {
|
||||
set err {malformed database schema (sqlite_sequence) - near "VIRTUAL": syntax error}
|
||||
}
|
||||
do_test autoinc-12.3 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} [list 1 $err]
|
||||
do_test autoinc-12.4 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
|
||||
}
|
||||
set root1 [db one {SELECT rootpage FROM sqlite_master
|
||||
WHERE name='sqlite_sequence'}]
|
||||
set root2 [db one {SELECT rootpage FROM sqlite_master
|
||||
WHERE name='fake'}]
|
||||
db eval {
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET rootpage=$root2
|
||||
WHERE name='sqlite_sequence';
|
||||
UPDATE sqlite_master SET rootpage=$root1
|
||||
WHERE name='fake';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
breakpoint
|
||||
do_test autoinc-12.5 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(x)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test autoinc-12.6 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two'),('three'),('four');
|
||||
INSERT INTO t1(b) VALUES('five');
|
||||
PRAGMA integrity_check;
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {0 ok}
|
||||
do_test autoinc-12.7 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two'),('three'),('four');
|
||||
INSERT INTO t1(b) VALUES('five');
|
||||
PRAGMA integrity_check;
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {0 ok}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -148,4 +148,13 @@ do_catchsql_test 4.3 {
|
||||
USING csv(filename='FileDoesNotExist.csv');
|
||||
} {1 {cannot open 'FileDoesNotExist.csv' for reading}}
|
||||
|
||||
# 2018-06-02
|
||||
# Problem with single-column CSV support reported on the mailing list
|
||||
# by Trent W. Buck.
|
||||
#
|
||||
do_execsql_test 4.4 {
|
||||
CREATE VIRTUAL TABLE temp.trent USING csv(data='1');
|
||||
SELECT * FROM trent;
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
+31
-15
@@ -24,7 +24,24 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
proc eqp {sql {db db}} { uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db }
|
||||
proc eqp {sql {db db}} {
|
||||
uplevel [subst -nocommands {
|
||||
set eqpres [list]
|
||||
$db eval "$sql" {
|
||||
lappend eqpres [set detail]
|
||||
}
|
||||
set eqpres
|
||||
}]
|
||||
}
|
||||
|
||||
proc do_detail_test {tn sql res} {
|
||||
set normalres [list {*}$res]
|
||||
uplevel [subst -nocommands {
|
||||
do_test $tn {
|
||||
eqp { $sql }
|
||||
} {$normalres}
|
||||
}]
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
### SECTION 2: Enabling Foreign Key Support
|
||||
@@ -970,20 +987,20 @@ do_test e_fkey-25.1 {
|
||||
);
|
||||
}
|
||||
} {}
|
||||
do_execsql_test e_fkey-25.2 {
|
||||
do_detail_test e_fkey-25.2 {
|
||||
PRAGMA foreign_keys = OFF;
|
||||
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
|
||||
EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE artist}
|
||||
0 0 0 {SCAN TABLE track}
|
||||
{SCAN TABLE artist}
|
||||
{SCAN TABLE track}
|
||||
}
|
||||
do_execsql_test e_fkey-25.3 {
|
||||
do_detail_test e_fkey-25.3 {
|
||||
PRAGMA foreign_keys = ON;
|
||||
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE artist}
|
||||
0 0 0 {SCAN TABLE track}
|
||||
{SCAN TABLE artist}
|
||||
{SCAN TABLE track}
|
||||
}
|
||||
do_test e_fkey-25.4 {
|
||||
execsql {
|
||||
@@ -1097,21 +1114,20 @@ do_test e_fkey-27.1 {
|
||||
do_test e_fkey-27.2 {
|
||||
eqp { INSERT INTO artist VALUES(?, ?) }
|
||||
} {}
|
||||
do_execsql_test e_fkey-27.3 {
|
||||
do_detail_test e_fkey-27.3 {
|
||||
EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
|
||||
} {
|
||||
0 0 0 {SCAN TABLE artist}
|
||||
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
{SCAN TABLE artist}
|
||||
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
}
|
||||
do_execsql_test e_fkey-27.4 {
|
||||
do_detail_test e_fkey-27.4 {
|
||||
EXPLAIN QUERY PLAN DELETE FROM artist
|
||||
} {
|
||||
0 0 0 {SCAN TABLE artist}
|
||||
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
{SCAN TABLE artist}
|
||||
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
|
||||
}
|
||||
|
||||
|
||||
###########################################################################
|
||||
### SECTION 4.1: Composite Foreign Key Constraints
|
||||
###########################################################################
|
||||
|
||||
+13
-13
@@ -801,7 +801,7 @@ do_select_tests e_select-4.1 {
|
||||
4 "SELECT z2.* FROM z1,z2 LIMIT 1" {{} 21}
|
||||
5 "SELECT z2.*, z1.* FROM z1,z2 LIMIT 1" {{} 21 51.65 -59.58 belfries}
|
||||
|
||||
6 "SELECT count(*), * FROM z1" {6 63 born -26}
|
||||
6 "SELECT count(*), * FROM z1" {6 51.65 -59.58 belfries}
|
||||
7 "SELECT max(a), * FROM z1" {63 63 born -26}
|
||||
8 "SELECT *, min(a) FROM z1" {-5 {} 75 -5}
|
||||
|
||||
@@ -939,13 +939,13 @@ do_execsql_test e_select-4.6.0 {
|
||||
INSERT INTO a2 VALUES(10, 4);
|
||||
} {}
|
||||
do_select_tests e_select-4.6 {
|
||||
1 "SELECT one, two, count(*) FROM a1" {4 10 4}
|
||||
2 "SELECT one, two, count(*) FROM a1 WHERE one<3" {2 3 2}
|
||||
1 "SELECT one, two, count(*) FROM a1" {1 1 4}
|
||||
2 "SELECT one, two, count(*) FROM a1 WHERE one<3" {1 1 2}
|
||||
3 "SELECT one, two, count(*) FROM a1 WHERE one>3" {4 10 1}
|
||||
4 "SELECT *, count(*) FROM a1 JOIN a2" {4 10 10 4 16}
|
||||
5 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {3 6 2 3}
|
||||
6 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {3 6 2 3}
|
||||
7 "SELECT group_concat(three, ''), a1.* FROM a1 NATURAL JOIN a2" {12 3 6}
|
||||
4 "SELECT *, count(*) FROM a1 JOIN a2" {1 1 1 1 16}
|
||||
5 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {1 1 1 3}
|
||||
6 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {1 1 1 3}
|
||||
7 "SELECT group_concat(three, ''), a1.* FROM a1 NATURAL JOIN a2" {12 1 1}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-04486-07266 Or, if the dataset contains zero rows, then
|
||||
@@ -1128,7 +1128,7 @@ do_select_tests e_select-4.13 {
|
||||
2.1 "SELECT up FROM c1 GROUP BY up HAVING down>10" {y}
|
||||
2.2 "SELECT up FROM c1 GROUP BY up HAVING up='y'" {y}
|
||||
|
||||
2.3 "SELECT i, j FROM c2 GROUP BY i>4 HAVING i>6" {9 36}
|
||||
2.3 "SELECT i, j FROM c2 GROUP BY i>4 HAVING j>6" {5 10}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-23927-54081 Each expression in the result-set is then
|
||||
@@ -1154,12 +1154,12 @@ do_select_tests e_select-4.15 {
|
||||
# for the same row.
|
||||
#
|
||||
do_select_tests e_select-4.15 {
|
||||
1 "SELECT i, j FROM c2 GROUP BY i%2" {8 28 9 36}
|
||||
2 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j<30" {8 28}
|
||||
3 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {9 36}
|
||||
4 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {9 36}
|
||||
1 "SELECT i, j FROM c2 GROUP BY i%2" {2 1 1 0}
|
||||
2 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j<30" {2 1 1 0}
|
||||
3 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {}
|
||||
4 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {}
|
||||
5 "SELECT count(*), i, k FROM c2 NATURAL JOIN c3 GROUP BY substr(k, 1, 1)"
|
||||
{2 5 boron 2 2 helium 1 3 lithium}
|
||||
{2 4 beryllium 2 1 hydrogen 1 3 lithium}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-19334-12811 Each group of input dataset rows
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# 2018-06-07
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# A multi-key index that uses an IN operator on one of the keys other
|
||||
# than the left-most key is able to abort the IN-operator loop early
|
||||
# if key terms further to the left do not match.
|
||||
#
|
||||
# Call this the "multikey-IN-operator early-out optimization" or
|
||||
# just "IN-early-out" optimization for short.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix in6
|
||||
|
||||
do_test in6-1.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
|
||||
INSERT INTO t1(a,b,c,d)
|
||||
SELECT 100, 200+x/2, 300+x/5, x FROM c;
|
||||
CREATE INDEX t1abc ON t1(a,b,c);
|
||||
}
|
||||
set ::sqlite_search_count 0
|
||||
db eval {
|
||||
SELECT d FROM t1
|
||||
WHERE a=99
|
||||
AND b IN (200,205,201,204)
|
||||
AND c IN (304,302,309,308);
|
||||
}
|
||||
} {}
|
||||
do_test in6-1.2 {
|
||||
set ::sqlite_search_count
|
||||
} {0} ;# Without the IN-early-out optimization, this value would be 15
|
||||
|
||||
# The multikey-IN-operator early-out optimization does not apply
|
||||
# when the IN operator is on the left-most column of the index.
|
||||
#
|
||||
do_test in6-1.3 {
|
||||
db eval {
|
||||
EXPLAIN
|
||||
SELECT d FROM t1
|
||||
WHERE a IN (98,99,100,101)
|
||||
AND b=200 AND c=300;
|
||||
}
|
||||
} {~/(IfNoHope|SeekHit)/}
|
||||
|
||||
set sqlite_search_count 0
|
||||
do_execsql_test in6-1.4 {
|
||||
SELECT d FROM t1
|
||||
WHERE a=100
|
||||
AND b IN (200,201,202,204)
|
||||
AND c IN (300,302,301,305)
|
||||
ORDER BY +d;
|
||||
} {1 2 3 4 5 8 9}
|
||||
do_test in6-1.5 {
|
||||
set ::sqlite_search_count
|
||||
} {39}
|
||||
|
||||
do_execsql_test in6-2.1 {
|
||||
CREATE TABLE t2(e INT UNIQUE, f TEXT);
|
||||
SELECT d, f FROM t1 LEFT JOIN t2 ON (e=d)
|
||||
WHERE a=100
|
||||
AND b IN (200,201,202,204)
|
||||
AND c IN (300,302,301,305)
|
||||
ORDER BY +d;
|
||||
} {1 {} 2 {} 3 {} 4 {} 5 {} 8 {} 9 {}}
|
||||
|
||||
finish_test
|
||||
+5
-2
@@ -174,8 +174,11 @@ do_test malloc5-2.2 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
list $nRelease $data
|
||||
} [list $pgalloc [list 1 2 3 4 5 6]]
|
||||
value_in_range $::pgalloc $::mrange $nRelease
|
||||
} [value_in_range $::pgalloc $::mrange]
|
||||
do_test malloc5-2.2.1 {
|
||||
set data
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
do_test malloc5-3.1 {
|
||||
# Simple test to show that if two pagers are opened from within this
|
||||
|
||||
+19
-14
@@ -270,22 +270,27 @@ forcedelete test.db-journal
|
||||
sqlite3 db test.db
|
||||
|
||||
ifcapable explain {
|
||||
do_execsql_test misc7-14.1 {
|
||||
do_execsql_test misc7-14.0 {
|
||||
CREATE TABLE abc(a PRIMARY KEY, b, c);
|
||||
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE rowid = 1;
|
||||
}
|
||||
do_eqp_test misc7-14.1 {
|
||||
SELECT * FROM abc AS t2 WHERE rowid = 1;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
do_execsql_test misc7-14.2 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE a = 1;
|
||||
} {0 0 0
|
||||
{SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)}
|
||||
}
|
||||
do_execsql_test misc7-14.3 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a;
|
||||
} {0 0 0
|
||||
{SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1}
|
||||
}
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_eqp_test misc7-14.2 {
|
||||
SELECT * FROM abc AS t2 WHERE a = 1;
|
||||
} {
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
|
||||
}
|
||||
do_eqp_test misc7-14.3 {
|
||||
SELECT * FROM abc AS t2 ORDER BY a;
|
||||
} {
|
||||
QUERY PLAN
|
||||
`--SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1
|
||||
}
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
+2
-2
@@ -55,11 +55,11 @@ if {![clang_sanitize_address]} {
|
||||
do_test 1.1.1 {
|
||||
set ::log [list]
|
||||
list [catch {
|
||||
for {set i 0} {$i < 2000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
|
||||
for {set i 0} {$i < 20000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
|
||||
} msg] $msg
|
||||
} {1 {unable to open database file}}
|
||||
do_test 1.1.2 {
|
||||
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
|
||||
catch { for {set i 0} {$i < 20000} {incr i} { dbh_$i close } }
|
||||
} {1}
|
||||
do_re_test 1.1.3 {
|
||||
lindex $::log 0
|
||||
|
||||
@@ -15,13 +15,30 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix resetdb
|
||||
|
||||
do_not_use_codec
|
||||
|
||||
ifcapable !vtab||!compound {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# In the "inmemory_journal" permutation, each new connection executes
|
||||
# "PRAGMA journal_mode = memory". This fails with SQLITE_BUSY if attempted
|
||||
# on a wal mode database with existing connections. For this and a few
|
||||
# other reasons, this test is not run as part of "inmemory_journal".
|
||||
#
|
||||
# Permutation "journaltest" does not support wal mode.
|
||||
#
|
||||
if {[permutation]=="inmemory_journal"
|
||||
|| [permutation]=="journaltest"
|
||||
} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Create a sample database
|
||||
do_execsql_test 100 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA page_size=4096;
|
||||
CREATE TABLE t1(a,b);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
|
||||
@@ -82,6 +99,7 @@ db2 close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 300 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA page_size=8192;
|
||||
PRAGMA journal_mode=WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
@@ -118,6 +136,8 @@ do_test 330 {
|
||||
} db2
|
||||
} {1 {file is not a database}}
|
||||
|
||||
db2 cache flush ;# Required by permutation "prepare".
|
||||
|
||||
# Reset the database yet again. Verify that the page size and
|
||||
# journal mode are preserved.
|
||||
#
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ do_test select5-5.5 {
|
||||
execsql {
|
||||
SELECT a, b FROM t2 GROUP BY a;
|
||||
}
|
||||
} {1 4 6 4}
|
||||
} {1 2 6 4}
|
||||
|
||||
# Test rendering of columns for the GROUP BY clause.
|
||||
#
|
||||
|
||||
@@ -637,6 +637,19 @@ do_test shell1-3.23b.4 {
|
||||
catchcmd "test.db" ".stats OFF BAD"
|
||||
} {1 {Usage: .stats ?on|off?}}
|
||||
|
||||
# Ticket 7be932dfa60a8a6b3b26bcf7623ec46e0a403ddb 2018-06-07
|
||||
# Adverse interaction between .stats and .eqp
|
||||
#
|
||||
do_test shell1-3.23b.5 {
|
||||
catchcmd "test.db" [string map {"\n " "\n"} {
|
||||
CREATE TEMP TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1),(2);
|
||||
.stats on
|
||||
.eqp full
|
||||
SELECT * FROM t1;
|
||||
}]
|
||||
} {/1\n2\n/}
|
||||
|
||||
# .tables ?TABLE? List names of tables
|
||||
# If TABLE specified, only list tables matching
|
||||
# LIKE pattern TABLE.
|
||||
|
||||
+53
-6
@@ -1247,10 +1247,11 @@ void testset_rtree(int p1, int p2){
|
||||
unsigned mxCoord;
|
||||
unsigned x0, x1, y0, y1, z0, z1;
|
||||
unsigned iStep;
|
||||
unsigned mxRowid;
|
||||
int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*500 );
|
||||
|
||||
mxCoord = 15000;
|
||||
n = g.szTest*500;
|
||||
mxRowid = n = g.szTest*500;
|
||||
speedtest1_begin_test(100, "%d INSERTs into an r-tree", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)");
|
||||
@@ -1277,7 +1278,7 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
|
||||
speedtest1_end_test();
|
||||
|
||||
n = g.szTest*100;
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n);
|
||||
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2");
|
||||
iStep = mxCoord/n;
|
||||
@@ -1290,7 +1291,7 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_end_test();
|
||||
|
||||
if( g.bVerify ){
|
||||
n = g.szTest*100;
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries");
|
||||
speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2");
|
||||
iStep = mxCoord/n;
|
||||
@@ -1306,7 +1307,7 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_end_test();
|
||||
}
|
||||
|
||||
n = g.szTest*100;
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n);
|
||||
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2");
|
||||
iStep = mxCoord/n;
|
||||
@@ -1319,7 +1320,7 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_end_test();
|
||||
|
||||
if( g.bVerify ){
|
||||
n = g.szTest*100;
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries");
|
||||
speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2");
|
||||
iStep = mxCoord/n;
|
||||
@@ -1336,7 +1337,7 @@ void testset_rtree(int p1, int p2){
|
||||
}
|
||||
|
||||
|
||||
n = g.szTest*100;
|
||||
n = g.szTest*200;
|
||||
speedtest1_begin_test(125, "%d custom geometry callback queries", n);
|
||||
sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0);
|
||||
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)");
|
||||
@@ -1373,6 +1374,52 @@ void testset_rtree(int p1, int p2){
|
||||
speedtest1_run();
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
n = g.szTest*50;
|
||||
speedtest1_begin_test(150, "%d UPDATEs using rowid", n);
|
||||
speedtest1_prepare("UPDATE rt1 SET x0=x0+100, x1=x1+100 WHERE id=?1");
|
||||
for(i=1; i<=n; i++){
|
||||
sqlite3_bind_int(g.pStmt, 1, (i*251)%mxRowid + 1);
|
||||
speedtest1_run();
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
n = g.szTest*5;
|
||||
speedtest1_begin_test(155, "%d UPDATEs using one-dimensional overlap", n);
|
||||
speedtest1_prepare("UPDATE rt1 SET x0=x0-100, x1=x1-100"
|
||||
" WHERE y1>=?1 AND y0<=?1+5");
|
||||
iStep = mxCoord/n;
|
||||
for(i=0; i<n; i++){
|
||||
sqlite3_bind_int(g.pStmt, 1, i*iStep);
|
||||
speedtest1_run();
|
||||
aCheck[i] = atoi(g.zResult);
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
n = g.szTest*50;
|
||||
speedtest1_begin_test(160, "%d DELETEs using rowid", n);
|
||||
speedtest1_prepare("DELETE FROM rt1 WHERE id=?1");
|
||||
for(i=1; i<=n; i++){
|
||||
sqlite3_bind_int(g.pStmt, 1, (i*257)%mxRowid + 1);
|
||||
speedtest1_run();
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
|
||||
n = g.szTest*5;
|
||||
speedtest1_begin_test(165, "%d DELETEs using one-dimensional overlap", n);
|
||||
speedtest1_prepare("DELETE FROM rt1 WHERE y1>=?1 AND y0<=?1+5");
|
||||
iStep = mxCoord/n;
|
||||
for(i=0; i<n; i++){
|
||||
sqlite3_bind_int(g.pStmt, 1, i*iStep);
|
||||
speedtest1_run();
|
||||
aCheck[i] = atoi(g.zResult);
|
||||
}
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(170, "Restore deleted entries using INSERT OR IGNORE");
|
||||
speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM t1");
|
||||
speedtest1_end_test();
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_RTREE */
|
||||
|
||||
|
||||
+2
-2
@@ -490,12 +490,12 @@ ifcapable subquery {
|
||||
count {
|
||||
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
|
||||
}
|
||||
} {2 1 9 5}
|
||||
} {2 1 9 4}
|
||||
do_test where-5.15 {
|
||||
count {
|
||||
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1;
|
||||
}
|
||||
} {2 1 9 3 1 16 9}
|
||||
} {2 1 9 3 1 16 8}
|
||||
do_test where-5.100 {
|
||||
db eval {
|
||||
SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969)
|
||||
|
||||
+2
-1
@@ -75,6 +75,7 @@ while {![eof $in]} {
|
||||
if {[regexp {^case OP_} $line]} {
|
||||
set line [split $line]
|
||||
set name [string trim [lindex $line 1] :]
|
||||
if {$name=="OP_Abortable"} continue; # put OP_Abortable last
|
||||
set op($name) -1
|
||||
set jump($name) 0
|
||||
set in1($name) 0
|
||||
@@ -113,7 +114,7 @@ while {![eof $in]} {
|
||||
#
|
||||
puts "/* Automatically generated. Do not edit */"
|
||||
puts "/* See the tool/mkopcodeh.tcl script for details */"
|
||||
foreach name {OP_Noop OP_Explain} {
|
||||
foreach name {OP_Noop OP_Explain OP_Abortable} {
|
||||
set jump($name) 0
|
||||
set in1($name) 0
|
||||
set in2($name) 0
|
||||
|
||||
+5
-1
@@ -41,8 +41,12 @@ doExplain=0
|
||||
doCachegrind=1
|
||||
doVdbeProfile=0
|
||||
doWal=1
|
||||
doDiff=1
|
||||
while test "$1" != ""; do
|
||||
case $1 in
|
||||
--nodiff)
|
||||
doDiff=0
|
||||
;;
|
||||
--reprepare)
|
||||
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
|
||||
;;
|
||||
@@ -179,6 +183,6 @@ if test $doVdbeProfile -eq 1; then
|
||||
tclsh ../sqlite/tool/vdbe_profile.tcl >vdbeprofile-$NAME.txt
|
||||
open vdbeprofile-$NAME.txt
|
||||
fi
|
||||
if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1; then
|
||||
if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1 -a $doDiff -ne 0; then
|
||||
fossil test-diff --tk -c 20 cout-$BASELINE.txt cout-$NAME.txt
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user