Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 00583291bd | |||
| eb7df46e32 | |||
| 1fb7a60ca0 | |||
| 69a4b383a2 | |||
| 5ba5f5b5d2 | |||
| 789df14b11 | |||
| e893e2e4ee | |||
| 4344dbd3ab | |||
| 0f86c9d8fa | |||
| 416a801600 | |||
| 8cdafc384e | |||
| fc232d6f65 | |||
| 5d3112872d | |||
| 8e02a180b9 | |||
| 6a8b94e266 | |||
| 3e62ddbf13 | |||
| 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 | |||
| 8d1751b6fa | |||
| 6c319e1238 | |||
| be4ccb2838 | |||
| d0f9cdcc63 | |||
| 1f22f62582 | |||
| 26fb126622 | |||
| 7578456c25 | |||
| 1e76c22b4a | |||
| e297196524 | |||
| f80bba9d8d | |||
| dd7460f0fd | |||
| a44005af4f | |||
| 492ad131bd | |||
| a090ab90d6 | |||
| a3926f4bbf | |||
| fc97c1c8cb | |||
| 69ed38a822 |
@@ -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)
|
||||
@@ -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 ){
|
||||
|
||||
+1
-1
@@ -2118,7 +2118,7 @@ static int jsonEachColumn(
|
||||
}
|
||||
if( p->eType==JSON_ARRAY ){
|
||||
jsonPrintf(30, &x, "[%d]", p->iRowid);
|
||||
}else{
|
||||
}else if( p->eType==JSON_OBJECT ){
|
||||
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
|
||||
}
|
||||
}
|
||||
|
||||
+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{
|
||||
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
|
||||
char *zTmp;
|
||||
int ii;
|
||||
for(ii=4; zSql && ii<argc; ii++){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( zSql ){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s);", zTmp);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
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,5 +1,5 @@
|
||||
C In\sthe\sCLI,\sallow\scomment\slines\sthat\sbegin\swith\s'#',\sbut\sonly\sin\sa\scontext\nwhere\sa\sdot-command\sis\sallowed.\s\sIn\sother\swords,\s'#'\sat\sthe\sbeginning\sof\sa\nline\sin\sthe\smiddle\sof\san\sSQL\sstatement\sis\sjust\spart\sof\sthe\sSQL.
|
||||
D 2018-05-12T23:56:22.493
|
||||
C Version\s3.24.0
|
||||
D 2018-06-04T19:24:41.225
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
||||
@@ -12,7 +12,8 @@ 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
|
||||
@@ -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,13 +275,13 @@ 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
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984
|
||||
F ext/misc/json1.c 02f5f0d9c131df79f4ee168d2b426f0f0d273b7771fc0bb5293c4e7692d9a2ee
|
||||
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
|
||||
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
@@ -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 bc61010e978b5b8ae6dbb90274a2fbb5db5ff5e2880b5c6e8abd48eea77264db
|
||||
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
|
||||
@@ -430,34 +432,34 @@ F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
|
||||
F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
|
||||
F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
|
||||
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
|
||||
F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 8270813c8f0ca91b2802e88ded3755d04ee962a923d431c13bcb6cf3e0c18f63
|
||||
F src/btree.c 44405d03a05496e13b40b3a208bcf941c42c815da90d6ff4b04267a6985e5eb7
|
||||
F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598
|
||||
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/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 0402e234155e0aad75fe6cd204864f492495be8605a50b4b3d4d72895cced3ce
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -477,28 +479,28 @@ 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.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa
|
||||
F src/printf.c 74ca0348796b490cdc56c85a8fb1abaa423c15c869712f54bf49fca65aa1dda1
|
||||
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 df40a09c4098d050bf5a008caa9ca8f25eed8ff9a8468d39b1f4d8a778cd324a
|
||||
F src/sqlite.h.in ef7e6fae65cb40ba004abf090ea491751295c11e64b1446322813d3b473b9400
|
||||
F src/select.c 3291892add3a8f01dc3754e40ef9e30ad22c78e3404a388ae58f0390a1fb29eb
|
||||
F src/shell.c.in c29cb307d6275131e6f9874e0fa73f87acf40a22c4a82faba2059a93b4d294d1
|
||||
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
|
||||
@@ -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,26 +560,26 @@ 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 f1cb5ae6e42c54d4991e2951e5293c1e18bad6847056e9b17622fbf6b17964a9
|
||||
F src/vdbe.c 71e5a72d89eabf7f88ef0ad4a429d3c3ee5d10de76af3818c47b275a6b3a9097
|
||||
F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
|
||||
F src/vdbeInt.h 42d3e65ea0c664f6d9bc9a53de645c0baf8566ff0188409ff3b8d2abc327bc17
|
||||
F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
|
||||
F src/vdbeaux.c b00d35805a2b326d1371ab7ce8f3a95c8af35b1431367ffe482fc2c735d69fb1
|
||||
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 d89b1aa56a75a572cd60ad27ec0fe5958d5f98b0f4391a89c72811287be7c439
|
||||
F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
|
||||
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
|
||||
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
|
||||
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
|
||||
@@ -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,7 +773,7 @@ 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
|
||||
@@ -1021,7 +1023,7 @@ F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d54530
|
||||
F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
|
||||
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test 24e97954e3bd6404f3715888c7f8f835e36e19c7ae6513b5d9ab2d381498962d
|
||||
F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
@@ -1050,7 +1052,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 +1089,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 +1130,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 +1173,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
|
||||
@@ -1239,7 +1241,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 e2f7d375ae80eb16590af23d6c40cd0140b6d1f92642c1b71eb94630a144ee08
|
||||
F test/shell1.test 50154b0c4779df435b9e60ca60104b05f1cc217eab1aa383131359329e73d939
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
|
||||
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
@@ -1277,7 +1279,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
|
||||
@@ -1605,7 +1607,7 @@ F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286c
|
||||
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test 1dee70c9cc147330156d75e23de88f771e624998b03ae316cb64e1d249f129d8
|
||||
F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
|
||||
F test/wherelimit2.test be78ba3aa1831c6358fd7d5b9809bfd520f0c2a7d63a295e8f182e140ff137c3
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
|
||||
@@ -1659,7 +1661,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 +1688,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 +1730,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 13e7300a37e379eac564594d78d3f039fd25737493b3b627ef02fab57a6c98e1
|
||||
R 6b32792e712eff37702825b507b2e9b6
|
||||
P 1ecb3aa13de5c8dc611b814ff34010de0bd90aae73d88aa37a59c4627be4cc2d
|
||||
R 2db4b8b40a57a71d528932145db72c5a
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.24.0 *
|
||||
U drh
|
||||
Z d7c29ce2018cfc34028d7ed7f7fd8bc3
|
||||
Z 1c60c6ad1e28023fcabbb88fe23d7708
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4ee136d6d2e029dad8371faf659d3a0bc0ac6ae76940db81d333848545bc990f
|
||||
c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca
|
||||
+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{
|
||||
|
||||
+5
-1
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+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);
|
||||
|
||||
+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);
|
||||
|
||||
+34
-9
@@ -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
|
||||
|
||||
+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 ){
|
||||
|
||||
+13
-1
@@ -967,11 +967,21 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
return p->zText;
|
||||
}
|
||||
|
||||
/*
|
||||
** This singleton is an sqlite3_str object that is returned if
|
||||
** sqlite3_malloc() fails to provide space for a real one. This
|
||||
** sqlite3_str object accepts no new text and always returns
|
||||
** an SQLITE_NOMEM error.
|
||||
*/
|
||||
static sqlite3_str sqlite3OomStr = {
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
||||
};
|
||||
|
||||
/* Finalize a string created using sqlite3_str_new().
|
||||
*/
|
||||
char *sqlite3_str_finish(sqlite3_str *p){
|
||||
char *z;
|
||||
if( p ){
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
z = sqlite3StrAccumFinish(p);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
@@ -1040,6 +1050,8 @@ sqlite3_str *sqlite3_str_new(sqlite3 *db){
|
||||
if( p ){
|
||||
sqlite3StrAccumInit(p, 0, 0, 0,
|
||||
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
|
||||
}else{
|
||||
p = &sqlite3OomStr;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
+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 */
|
||||
{
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+99
-45
@@ -3323,6 +3323,7 @@ static char zHelp[] =
|
||||
".auth ON|OFF Show authorizer callbacks\n"
|
||||
#endif
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
" Add \"--append\" to open using appendvfs.\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".cd DIRECTORY Change the working directory to DIRECTORY\n"
|
||||
@@ -3540,14 +3541,17 @@ static int session_filter(void *pCtx, const char *zTab){
|
||||
** Otherwise, assume an ordinary database regardless of the filename if
|
||||
** the type cannot be determined from content.
|
||||
*/
|
||||
static int deduceDatabaseType(const char *zName, int dfltZip){
|
||||
int deduceDatabaseType(const char *zName, int dfltZip){
|
||||
FILE *f = fopen(zName, "rb");
|
||||
size_t n;
|
||||
int rc = SHELL_OPEN_UNSPEC;
|
||||
char zBuf[100];
|
||||
if( f==0 ){
|
||||
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ) return SHELL_OPEN_ZIPFILE;
|
||||
return SHELL_OPEN_NORMAL;
|
||||
if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
|
||||
return SHELL_OPEN_ZIPFILE;
|
||||
}else{
|
||||
return SHELL_OPEN_NORMAL;
|
||||
}
|
||||
}
|
||||
fseek(f, -25, SEEK_END);
|
||||
n = fread(zBuf, 25, 1, f);
|
||||
@@ -3560,24 +3564,38 @@ static int deduceDatabaseType(const char *zName, int dfltZip){
|
||||
&& zBuf[3]==0x06 ){
|
||||
rc = SHELL_OPEN_ZIPFILE;
|
||||
}else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
|
||||
return SHELL_OPEN_ZIPFILE;
|
||||
rc = SHELL_OPEN_ZIPFILE;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Flags for open_db().
|
||||
**
|
||||
** The default behavior of open_db() is to exit(1) if the database fails to
|
||||
** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
|
||||
** but still returns without calling exit.
|
||||
**
|
||||
** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
|
||||
** ZIP archive if the file does not exist or is empty and its name matches
|
||||
** the *.zip pattern.
|
||||
*/
|
||||
#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
|
||||
#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
|
||||
|
||||
/*
|
||||
** Make sure the database is open. If it is not, then open it. If
|
||||
** the database fails to open, print an error message and exit.
|
||||
*/
|
||||
static void open_db(ShellState *p, int keepAlive){
|
||||
static void open_db(ShellState *p, int openFlags){
|
||||
if( p->db==0 ){
|
||||
if( p->openMode==SHELL_OPEN_UNSPEC ){
|
||||
if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
|
||||
p->openMode = SHELL_OPEN_NORMAL;
|
||||
}else if( access(p->zDbFilename,0)==0 ){
|
||||
p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0);
|
||||
}else{
|
||||
p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
|
||||
(openFlags & OPEN_DB_ZIPFILE)!=0);
|
||||
}
|
||||
}
|
||||
switch( p->openMode ){
|
||||
@@ -3604,7 +3622,7 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
|
||||
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
|
||||
p->zDbFilename, sqlite3_errmsg(p->db));
|
||||
if( keepAlive ) return;
|
||||
if( openFlags & OPEN_DB_KEEPALIVE ) return;
|
||||
exit(1);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
@@ -3638,6 +3656,17 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** 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
|
||||
@@ -4218,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4873,6 +4902,7 @@ struct ArCommand {
|
||||
u8 bZip; /* True if the archive is a ZIP */
|
||||
u8 bDryRun; /* True if --dry-run */
|
||||
u8 bAppend; /* True if --append */
|
||||
u8 fromCmdLine; /* Run from -A instead of .archive */
|
||||
int nArg; /* Number of command arguments */
|
||||
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
|
||||
const char *zFile; /* --file argument, or NULL */
|
||||
@@ -4919,13 +4949,18 @@ static int arUsage(FILE *f){
|
||||
** Print an error message for the .ar command to stderr and return
|
||||
** SQLITE_ERROR.
|
||||
*/
|
||||
static int arErrorMsg(const char *zFmt, ...){
|
||||
static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
char *z;
|
||||
va_start(ap, zFmt);
|
||||
z = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
raw_printf(stderr, "Error: %s (try \".ar --help\")\n", z);
|
||||
utf8_printf(stderr, "Error: %s\n", z);
|
||||
if( pAr->fromCmdLine ){
|
||||
utf8_printf(stderr, "Use \"-A\" for more help\n");
|
||||
}else{
|
||||
utf8_printf(stderr, "Use \".archive --help\" for more help\n");
|
||||
}
|
||||
sqlite3_free(z);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
@@ -4956,7 +4991,7 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
case AR_CMD_UPDATE:
|
||||
case AR_CMD_HELP:
|
||||
if( pAr->eCmd ){
|
||||
return arErrorMsg("multiple command options");
|
||||
return arErrorMsg(pAr, "multiple command options");
|
||||
}
|
||||
pAr->eCmd = eSwitch;
|
||||
break;
|
||||
@@ -5016,8 +5051,6 @@ static int arParseCommand(
|
||||
return arUsage(stderr);
|
||||
}else{
|
||||
char *z = azArg[1];
|
||||
memset(pAr, 0, sizeof(ArCommand));
|
||||
|
||||
if( z[0]!='-' ){
|
||||
/* Traditional style [tar] invocation */
|
||||
int i;
|
||||
@@ -5029,11 +5062,11 @@ static int arParseCommand(
|
||||
if( z[i]==pOpt->cShort ) break;
|
||||
}
|
||||
if( pOpt==pEnd ){
|
||||
return arErrorMsg("unrecognized option: %c", z[i]);
|
||||
return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
|
||||
}
|
||||
if( pOpt->bArg ){
|
||||
if( iArg>=nArg ){
|
||||
return arErrorMsg("option requires an argument: %c",z[i]);
|
||||
return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
|
||||
}
|
||||
zArg = azArg[iArg++];
|
||||
}
|
||||
@@ -5067,7 +5100,7 @@ static int arParseCommand(
|
||||
if( z[i]==pOpt->cShort ) break;
|
||||
}
|
||||
if( pOpt==pEnd ){
|
||||
return arErrorMsg("unrecognized option: %c\n", z[i]);
|
||||
return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
|
||||
}
|
||||
if( pOpt->bArg ){
|
||||
if( i<(n-1) ){
|
||||
@@ -5075,7 +5108,7 @@ static int arParseCommand(
|
||||
i = n;
|
||||
}else{
|
||||
if( iArg>=(nArg-1) ){
|
||||
return arErrorMsg("option requires an argument: %c\n",z[i]);
|
||||
return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
|
||||
}
|
||||
zArg = azArg[++iArg];
|
||||
}
|
||||
@@ -5097,7 +5130,7 @@ static int arParseCommand(
|
||||
const char *zLong = pOpt->zLong;
|
||||
if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
|
||||
if( pMatch ){
|
||||
return arErrorMsg("ambiguous option: %s",z);
|
||||
return arErrorMsg(pAr, "ambiguous option: %s",z);
|
||||
}else{
|
||||
pMatch = pOpt;
|
||||
}
|
||||
@@ -5105,11 +5138,11 @@ static int arParseCommand(
|
||||
}
|
||||
|
||||
if( pMatch==0 ){
|
||||
return arErrorMsg("unrecognized option: %s", z);
|
||||
return arErrorMsg(pAr, "unrecognized option: %s", z);
|
||||
}
|
||||
if( pMatch->bArg ){
|
||||
if( iArg>=(nArg-1) ){
|
||||
return arErrorMsg("option requires an argument: %s", z);
|
||||
return arErrorMsg(pAr, "option requires an argument: %s", z);
|
||||
}
|
||||
zArg = azArg[++iArg];
|
||||
}
|
||||
@@ -5238,6 +5271,7 @@ static int arListCommand(ArCommand *pAr){
|
||||
}
|
||||
}
|
||||
shellFinalize(&rc, pSql);
|
||||
sqlite3_free(zWhere);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5440,12 +5474,14 @@ end_ar_transaction:
|
||||
*/
|
||||
static int arDotCommand(
|
||||
ShellState *pState, /* Current shell tool state */
|
||||
int fromCmdLine, /* True if -A command-line option, not .ar cmd */
|
||||
char **azArg, /* Array of arguments passed to dot command */
|
||||
int nArg /* Number of entries in azArg[] */
|
||||
){
|
||||
ArCommand cmd;
|
||||
int rc;
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.fromCmdLine = fromCmdLine;
|
||||
rc = arParseCommand(azArg, nArg, &cmd);
|
||||
if( rc==SQLITE_OK ){
|
||||
int eDbType = SHELL_OPEN_UNSPEC;
|
||||
@@ -5492,7 +5528,7 @@ static int arDotCommand(
|
||||
shellPutsFunc, 0, 0);
|
||||
|
||||
}
|
||||
if( cmd.zSrcTable==0 && cmd.bZip==0 ){
|
||||
if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
|
||||
if( cmd.eCmd!=AR_CMD_CREATE
|
||||
&& sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
|
||||
){
|
||||
@@ -5528,7 +5564,7 @@ static int arDotCommand(
|
||||
}
|
||||
end_ar_command:
|
||||
if( cmd.db!=pState->db ){
|
||||
sqlite3_close(cmd.db);
|
||||
close_db(cmd.db);
|
||||
}
|
||||
sqlite3_free(cmd.zSrcTable);
|
||||
|
||||
@@ -5608,7 +5644,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
||||
if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
|
||||
open_db(p, 0);
|
||||
rc = arDotCommand(p, azArg, nArg);
|
||||
rc = arDotCommand(p, 0, azArg, nArg);
|
||||
}else
|
||||
#endif
|
||||
|
||||
@@ -5620,11 +5656,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3 *pDest;
|
||||
sqlite3_backup *pBackup;
|
||||
int j;
|
||||
const char *zVfs = 0;
|
||||
for(j=1; j<nArg; j++){
|
||||
const char *z = azArg[j];
|
||||
if( z[0]=='-' ){
|
||||
while( z[0]=='-' ) z++;
|
||||
/* No options to process at this time */
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z, "-append")==0 ){
|
||||
zVfs = "apndvfs";
|
||||
}else
|
||||
{
|
||||
utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
|
||||
return 1;
|
||||
@@ -5635,7 +5674,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
zDb = zDestFile;
|
||||
zDestFile = azArg[j];
|
||||
}else{
|
||||
raw_printf(stderr, "too many arguments to .backup\n");
|
||||
raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -5644,17 +5683,18 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
return 1;
|
||||
}
|
||||
if( zDb==0 ) zDb = "main";
|
||||
rc = sqlite3_open(zDestFile, &pDest);
|
||||
rc = sqlite3_open_v2(zDestFile, &pDest,
|
||||
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 ){}
|
||||
@@ -5665,7 +5705,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 ){
|
||||
@@ -6481,7 +6521,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);
|
||||
@@ -6511,7 +6551,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( zNewFilename ){
|
||||
if( newFlag ) shellDeleteFile(zNewFilename);
|
||||
p->zDbFilename = zNewFilename;
|
||||
open_db(p, 1);
|
||||
open_db(p, OPEN_DB_KEEPALIVE);
|
||||
if( p->db==0 ){
|
||||
utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
|
||||
sqlite3_free(zNewFilename);
|
||||
@@ -6661,14 +6701,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
|
||||
@@ -6688,7 +6728,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 ){
|
||||
@@ -7372,7 +7412,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
|
||||
@@ -7380,6 +7423,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++){
|
||||
@@ -8199,7 +8243,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");
|
||||
}
|
||||
}
|
||||
@@ -8280,6 +8324,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
int nCmd = 0;
|
||||
char **azCmd = 0;
|
||||
const char *zVfs = 0; /* Value of -vfs command-line option */
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
char **argvToFree = 0;
|
||||
int argcToFree = 0;
|
||||
#endif
|
||||
|
||||
setBinaryMode(stdin, 0);
|
||||
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
|
||||
@@ -8303,7 +8351,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
*/
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
sqlite3_initialize();
|
||||
argv = malloc(sizeof(argv[0])*argc);
|
||||
argvToFree = malloc(sizeof(argv[0])*argc*2);
|
||||
argcToFree = argc;
|
||||
argv = argvToFree + argc;
|
||||
if( argv==0 ) shell_out_of_memory();
|
||||
for(i=0; i<argc; i++){
|
||||
char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
|
||||
@@ -8313,6 +8363,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
argv[i] = malloc( n+1 );
|
||||
if( argv[i]==0 ) shell_out_of_memory();
|
||||
memcpy(argv[i], z, n+1);
|
||||
argvToFree[i] = argv[i];
|
||||
sqlite3_free(z);
|
||||
}
|
||||
sqlite3_shutdown();
|
||||
@@ -8634,12 +8685,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
" with \"%s\"\n", z);
|
||||
return 1;
|
||||
}
|
||||
open_db(&data, 0);
|
||||
open_db(&data, OPEN_DB_ZIPFILE);
|
||||
if( z[2] ){
|
||||
argv[i] = &z[2];
|
||||
arDotCommand(&data, argv+(i-1), argc-(i-1));
|
||||
arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
|
||||
}else{
|
||||
arDotCommand(&data, argv+i, argc-i);
|
||||
arDotCommand(&data, 1, argv+i, argc-i);
|
||||
}
|
||||
readStdin = 0;
|
||||
break;
|
||||
@@ -8718,7 +8769,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);
|
||||
@@ -8726,8 +8777,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
data.doXdgOpen = 0;
|
||||
clearTempFile(&data);
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
for(i=0; i<argc; i++) free(argv[i]);
|
||||
free(argv);
|
||||
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;
|
||||
}
|
||||
|
||||
+21
-7
@@ -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 */
|
||||
|
||||
@@ -7155,12 +7161,20 @@ typedef struct sqlite3_str sqlite3_str;
|
||||
** CONSTRUCTOR: sqlite3_str
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface allocates and initializes
|
||||
** a new [sqlite3_str]
|
||||
** object. ^The [sqlite3_str_new()] interface returns NULL on an out-of-memory
|
||||
** condition. To avoid memory leaks, the object returned by
|
||||
** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
|
||||
** [sqlite3_str_new()] must be freed by a subsequent call to
|
||||
** [sqlite3_str_finish(X)].
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
|
||||
** valid [sqlite3_str] object, though in the event of an out-of-memory
|
||||
** error the returned object might be a special singleton that will
|
||||
** silently reject new text, always return SQLITE_NOMEM from
|
||||
** [sqlite3_str_errcode()], always return 0 for
|
||||
** [sqlite3_str_length()], and always return NULL from
|
||||
** [sqlite3_str_finish(X)]. It is always safe to use the value
|
||||
** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
|
||||
** to any of the other [sqlite3_str] methods.
|
||||
**
|
||||
** The D parameter to [sqlite3_str_new(D)] may be NULL. If the
|
||||
** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum
|
||||
** length of the string contained in the [sqlite3_str] object will be
|
||||
@@ -8525,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
|
||||
@@ -9024,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 *);
|
||||
|
||||
@@ -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,
|
||||
|
||||
+43
-9
@@ -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;
|
||||
@@ -3324,6 +3330,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) );
|
||||
@@ -4287,11 +4295,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 +4465,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 +4580,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 +4749,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.
|
||||
@@ -5192,6 +5199,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 +5246,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 +5469,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 +5519,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 +5569,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 +5596,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 +5686,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 +5700,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 +5714,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 +6761,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 +6924,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 +7242,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 +7269,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*,...);
|
||||
|
||||
@@ -379,6 +379,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 +515,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.
|
||||
|
||||
+42
-5
@@ -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.
|
||||
@@ -762,6 +788,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 +3032,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.
|
||||
*/
|
||||
@@ -3917,13 +3957,10 @@ static int sqlite3IntFloatCompare(i64 i, double r){
|
||||
i64 y;
|
||||
double s;
|
||||
if( r<-9223372036854775808.0 ) return +1;
|
||||
if( r>9223372036854775807.0 ) return -1;
|
||||
if( r>=9223372036854775808.0 ) return -1;
|
||||
y = (i64)r;
|
||||
if( i<y ) return -1;
|
||||
if( i>y ){
|
||||
if( y==SMALLEST_INT64 && r>0.0 ) return -1;
|
||||
return +1;
|
||||
}
|
||||
if( i>y ) return +1;
|
||||
s = (double)i;
|
||||
if( s<r ) return -1;
|
||||
if( s>r ) return +1;
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+10
-5
@@ -2862,14 +2862,16 @@ static int whereLoopAddBtree(
|
||||
/* TUNING: One-time cost for computing the automatic index is
|
||||
** estimated to be X*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed and where X is 7 (LogEst=28) for normal
|
||||
** tables or 1.375 (LogEst=4) for views and subqueries. The value
|
||||
** tables or 0.5 (LogEst=-10) for views and subqueries. The value
|
||||
** of X is smaller for views and subqueries so that the query planner
|
||||
** will be more aggressive about generating automatic indexes for
|
||||
** those objects, since there is no opportunity to add schema
|
||||
** indexes on subqueries and views. */
|
||||
pNew->rSetup = rLogSize + rSize + 4;
|
||||
pNew->rSetup = rLogSize + rSize;
|
||||
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
|
||||
pNew->rSetup += 24;
|
||||
pNew->rSetup += 28;
|
||||
}else{
|
||||
pNew->rSetup -= 10;
|
||||
}
|
||||
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
|
||||
if( pNew->rSetup<0 ) pNew->rSetup = 0;
|
||||
@@ -4005,12 +4007,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){
|
||||
if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){
|
||||
/* Do not use an automatic index if the this loop is expected
|
||||
** to run less than 2 times. */
|
||||
** to run less than 1.25 times. It is tempting to also exclude
|
||||
** automatic index usage on an outer loop, but sometimes an automatic
|
||||
** index is useful in the outer loop of a correlated subquery. */
|
||||
assert( 10==sqlite3LogEst(2) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
|
||||
@@ -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
|
||||
###########################################################################
|
||||
|
||||
@@ -784,5 +784,35 @@ do_execsql_test json-13.110 {
|
||||
WHERE Z.value==t2.id);
|
||||
} {3 {{"value":3}} 1 {{"items":[3,5]}} 5 {{"value":5}} 1 {{"items":[3,5]}}}
|
||||
|
||||
# 2018-05-16
|
||||
# Incorrect fullkey output from json_each()
|
||||
# when the input JSON is not an array or object.
|
||||
#
|
||||
do_execsql_test json-14.100 {
|
||||
SELECT fullkey FROM json_each('123');
|
||||
} {$}
|
||||
do_execsql_test json-14.110 {
|
||||
SELECT fullkey FROM json_each('123.56');
|
||||
} {$}
|
||||
do_execsql_test json-14.120 {
|
||||
SELECT fullkey FROM json_each('"hello"');
|
||||
} {$}
|
||||
do_execsql_test json-14.130 {
|
||||
SELECT fullkey FROM json_each('null');
|
||||
} {$}
|
||||
do_execsql_test json-14.140 {
|
||||
SELECT fullkey FROM json_tree('123');
|
||||
} {$}
|
||||
do_execsql_test json-14.150 {
|
||||
SELECT fullkey FROM json_tree('123.56');
|
||||
} {$}
|
||||
do_execsql_test json-14.160 {
|
||||
SELECT fullkey FROM json_tree('"hello"');
|
||||
} {$}
|
||||
do_execsql_test json-14.170 {
|
||||
SELECT fullkey FROM json_tree('null');
|
||||
} {$}
|
||||
|
||||
|
||||
|
||||
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
@@ -256,7 +256,7 @@ do_test shell1-3.1.3 {
|
||||
do_test shell1-3.1.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".backup FOO BAR BAD"
|
||||
} {1 {too many arguments to .backup}}
|
||||
} {1 {Usage: .backup ?DB? ?--append? FILENAME}}
|
||||
|
||||
# .bail ON|OFF Stop after hitting an error. Default OFF
|
||||
do_test shell1-3.2.1 {
|
||||
|
||||
+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 */
|
||||
|
||||
|
||||
+11
-6
@@ -51,15 +51,19 @@ ifcapable {update_delete_limit} {
|
||||
catchsql {UPDATE t1 SET y=1 WHERE x=1 ORDER BY x}
|
||||
} {1 {ORDER BY without LIMIT on UPDATE}}
|
||||
|
||||
execsql { DROP TABLE t1 }
|
||||
|
||||
# no AS on table sources
|
||||
#
|
||||
# UPDATE: As of version 3.24, AS clauses are allowed as part of
|
||||
# UPDATE or DELETE statements.
|
||||
do_test wherelimit-0.4 {
|
||||
catchsql {DELETE FROM t1 AS a WHERE x=1}
|
||||
} {1 {near "AS": syntax error}}
|
||||
do_test wherelimit-0.5 {
|
||||
catchsql {DELETE FROM t1 AS a WHERE a.x=1}
|
||||
} {0 {}}
|
||||
do_test wherelimit-0.5.1 {
|
||||
catchsql {UPDATE t1 AS a SET y=1 WHERE x=1}
|
||||
} {1 {near "AS": syntax error}}
|
||||
} {0 {}}
|
||||
do_test wherelimit-0.5.2 {
|
||||
catchsql {UPDATE t1 AS a SET y=1 WHERE t1.x=1}
|
||||
} {1 {no such column: t1.x}}
|
||||
|
||||
# OFFSET w/o LIMIT
|
||||
do_test wherelimit-0.6 {
|
||||
@@ -69,6 +73,7 @@ ifcapable {update_delete_limit} {
|
||||
catchsql {UPDATE t1 SET y=1 WHERE x=1 OFFSET 2}
|
||||
} {1 {near "OFFSET": syntax error}}
|
||||
|
||||
execsql { DROP TABLE t1 }
|
||||
|
||||
# check deletes w/o where clauses but with limit/offsets
|
||||
create_test_data 5
|
||||
|
||||
+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