From e2971965246f138ac887a7a4d17dd7239f0cdde8 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 May 2018 17:57:30 +0000 Subject: [PATCH 01/13] Initial implementation of the ability to have auxiliary columns in an rtree virtual table that store arbitrary content. It mostly works, but there are some minor issues in OOM corner cases. FossilOrigin-Name: 0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719 --- ext/rtree/rtree.c | 269 +++++++++++++++++++++++++++++++++------------- manifest | 15 +-- manifest.uuid | 2 +- 3 files changed, 202 insertions(+), 84 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 0211261821..b5a27ac956 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -122,12 +122,14 @@ 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 */ + 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 +156,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 +235,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 +243,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 */ @@ -930,6 +937,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 +1027,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; iiaNode[ii]); sqlite3_free(pCsr); @@ -1560,6 +1570,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; @@ -1590,11 +1604,10 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ int rc = SQLITE_OK; RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - if( rc ) return rc; - if( p==0 ) return SQLITE_OK; + if( p==0 || pNode==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 +1618,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; } @@ -3015,7 +3048,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; @@ -3041,8 +3074,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 +3085,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; iicell.aCoord[ii+1].f ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; @@ -3065,9 +3099,9 @@ static int rtreeUpdate( }else #endif { - for(ii=0; iicell.aCoord[ii+1].i ){ rc = rtreeConstraintError(pRtree, ii+1); goto constraint; @@ -3077,10 +3111,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 +3133,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 +3167,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; jjnAux; jj++){ + sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); + } + sqlite3_step(pUp); + rc = sqlite3_reset(pUp); + } } constraint: @@ -3289,18 +3333,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 +3352,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; iinAux; 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 +3392,17 @@ static int rtreeSqlInit( rc = rtreeQueryStat1(db, pRtree); for(i=0; inAux==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 +3411,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; iinAux; 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 +3539,21 @@ 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 */ + "AUX: 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]); + if( argc>=256 ){ + *pzErr = sqlite3_mprintf("%s", aErrMsg[3]); return SQLITE_ERROR; } @@ -3476,53 +3571,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; iinAux++; + sqlite3_str_appendf(pSql, ",%s", argv[ii]+4); + }else if( pRtree->nAux>0 ){ + break; }else{ - sqlite3_str *pSql = sqlite3_str_new(db); - char *zSql; - int ii; - if( pSql==0 ){ - zSql = 0; - }else{ - sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]); - for(ii=4; iinDim2++; + 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( iinDim = 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; } diff --git a/manifest b/manifest index 90956c0afc..840b771c9e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite3_str_new()\sinterface\sso\sthat\sit\salways\sreturns\sa\svalid\nand\snon-NULL\spointer\seven\sin\san\sOOM\scondition. -D 2018-05-16T15:35:03.770 +C Initial\simplementation\sof\sthe\sability\sto\shave\sauxiliary\scolumns\sin\san\srtree\nvirtual\stable\sthat\sstore\sarbitrary\scontent.\s\sIt\smostly\sworks,\sbut\sthere\sare\nsome\sminor\sissues\sin\sOOM\scorner\scases. +D 2018-05-16T17:57:30.645 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 11dc450eec4c86a9b1eee104e478f9556382622a6a7e8080a478567ea975ea69 +F ext/rtree/rtree.c 74c1157c32d44f0810c56436ff5e2922389a7d9ac81f1ad4fcd85976c3854018 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -1728,7 +1728,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 b45b18850c59f22a163ee482f529f578a8798f96d0e26b5a061d336d480a1540 -R c3a19bb61082b137e0cb5588248c4f0e +P ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a +R 091cfdce4344d2ad2548902254b1bbe7 +T *branch * aux-data-in-rtree +T *sym-aux-data-in-rtree * +T -sym-trunk * U drh -Z 26153b062cb510be04ec5eecb2714fde +Z 6d7dec46bb0abfe5fe6f07ef3233cda3 diff --git a/manifest.uuid b/manifest.uuid index c2200e96a6..eea070869b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a \ No newline at end of file +0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719 \ No newline at end of file From 1e76c22b4a1d2fe1930e199dfbd2d12e0d03f7a3 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 May 2018 18:18:24 +0000 Subject: [PATCH 02/13] Fix the OOM issue mentioned in the previous check-in. FossilOrigin-Name: c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a --- ext/rtree/rtree.c | 3 ++- manifest | 15 ++++++--------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index b5a27ac956..c43c304ff1 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1604,7 +1604,8 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ int rc = SQLITE_OK; RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); - if( p==0 || pNode==0 ) return SQLITE_OK; + if( rc ) return rc; + if( p==0 ) return SQLITE_OK; if( i==0 ){ sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); }else if( i<=pRtree->nDim2 ){ diff --git a/manifest b/manifest index 840b771c9e..fbcbd84a28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\simplementation\sof\sthe\sability\sto\shave\sauxiliary\scolumns\sin\san\srtree\nvirtual\stable\sthat\sstore\sarbitrary\scontent.\s\sIt\smostly\sworks,\sbut\sthere\sare\nsome\sminor\sissues\sin\sOOM\scorner\scases. -D 2018-05-16T17:57:30.645 +C Fix\sthe\sOOM\sissue\smentioned\sin\sthe\sprevious\scheck-in. +D 2018-05-16T18:18:24.545 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,7 +355,7 @@ 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 74c1157c32d44f0810c56436ff5e2922389a7d9ac81f1ad4fcd85976c3854018 +F ext/rtree/rtree.c 8176ca2bef95655f259b7320ae779e504b9d86edb181fc267cde94f9db3742b1 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -1728,10 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a -R 091cfdce4344d2ad2548902254b1bbe7 -T *branch * aux-data-in-rtree -T *sym-aux-data-in-rtree * -T -sym-trunk * +P 0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719 +R 1a66dc3ed24af9af189a9d927f133deb U drh -Z 6d7dec46bb0abfe5fe6f07ef3233cda3 +Z 426a969e38bb74296bdc875c7051db68 diff --git a/manifest.uuid b/manifest.uuid index eea070869b..2a0e277de3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719 \ No newline at end of file +c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a \ No newline at end of file From 7578456c253d7f7dc332e7226fc091715a7ef629 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 May 2018 19:07:07 +0000 Subject: [PATCH 03/13] Do not allow auxiliary columns in the rtree to interfere with query planning. Begin adding test cases. FossilOrigin-Name: 9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c --- ext/rtree/rtree.c | 20 ++++++----- ext/rtree/rtree3.test | 2 +- ext/rtree/rtreeC.test | 4 +-- ext/rtree/rtreeH.test | 80 +++++++++++++++++++++++++++++++++++++++++++ manifest | 17 ++++----- manifest.uuid | 2 +- 6 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 ext/rtree/rtreeH.test diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index c43c304ff1..104feb789b 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -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 @@ -1890,7 +1891,10 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ 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; @@ -3584,9 +3588,9 @@ static int rtreeInit( pSql = sqlite3_str_new(db); sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]); for(ii=4; iinAux++; - sqlite3_str_appendf(pSql, ",%s", argv[ii]+4); + sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); }else if( pRtree->nAux>0 ){ break; }else{ @@ -3867,7 +3871,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. @@ -3882,8 +3886,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 ); diff --git a/ext/rtree/rtree3.test b/ext/rtree/rtree3.test index 1d863c6cc2..e37d18ee84 100644 --- a/ext/rtree/rtree3.test +++ b/ext/rtree/rtree3.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 diff --git a/ext/rtree/rtreeC.test b/ext/rtree/rtreeC.test index f983b220f4..19a1f7fe6c 100644 --- a/ext/rtree/rtreeC.test +++ b/ext/rtree/rtreeC.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 diff --git a/ext/rtree/rtreeH.test b/ext/rtree/rtreeH.test new file mode 100644 index 0000000000..bff765d530 --- /dev/null +++ b/ext/rtree/rtreeH.test @@ -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 diff --git a/manifest b/manifest index fbcbd84a28..6cb645124e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sOOM\sissue\smentioned\sin\sthe\sprevious\scheck-in. -D 2018-05-16T18:18:24.545 +C Do\snot\sallow\sauxiliary\scolumns\sin\sthe\srtree\sto\sinterfere\swith\squery\splanning.\nBegin\sadding\stest\scases. +D 2018-05-16T19:07:07.322 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,11 +355,11 @@ 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 8176ca2bef95655f259b7320ae779e504b9d86edb181fc267cde94f9db3742b1 +F ext/rtree/rtree.c 762823491d82fccfe51628d4ed4e3c2444c839416e4c9e4fb5ff7267538a8759 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972 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 @@ -368,11 +368,12 @@ F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1ce 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 @@ -1728,7 +1729,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719 -R 1a66dc3ed24af9af189a9d927f133deb +P c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a +R f1ba39e4f92eb847a2aa6e82a35e3a11 U drh -Z 426a969e38bb74296bdc875c7051db68 +Z 5b179b6d81cfc68160024bb335ccee53 diff --git a/manifest.uuid b/manifest.uuid index 2a0e277de3..328ec449f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a \ No newline at end of file +9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c \ No newline at end of file From 26fb12662294ba73a19969a2f72a73788a0ff183 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 16 May 2018 19:56:20 +0000 Subject: [PATCH 04/13] Fix an issue with rtreecheck() and auxiliary data columns. FossilOrigin-Name: 46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60 --- ext/rtree/rtree.c | 13 ++++++++++++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 104feb789b..5d76a8d801 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -4071,6 +4071,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)); @@ -4086,11 +4087,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) ){ diff --git a/manifest b/manifest index 6cb645124e..76e14de3ae 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sauxiliary\scolumns\sin\sthe\srtree\sto\sinterfere\swith\squery\splanning.\nBegin\sadding\stest\scases. -D 2018-05-16T19:07:07.322 +C Fix\san\sissue\swith\srtreecheck()\sand\sauxiliary\sdata\scolumns. +D 2018-05-16T19:56:20.915 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,7 +355,7 @@ 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 762823491d82fccfe51628d4ed4e3c2444c839416e4c9e4fb5ff7267538a8759 +F ext/rtree/rtree.c 90c35907cedf73c7b2a69497f88a17da266616ee6f7bced787f8cc49002d4372 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -1729,7 +1729,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a -R f1ba39e4f92eb847a2aa6e82a35e3a11 +P 9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c +R 7a064c4cbbc33c8c1ab943f10eb67b1c U drh -Z 5b179b6d81cfc68160024bb335ccee53 +Z 2eb6f867a66e47a61ca5b21b3b9da89e diff --git a/manifest.uuid b/manifest.uuid index 328ec449f9..1fa5732712 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c \ No newline at end of file +46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60 \ No newline at end of file From 1f22f625826eddef8104a9837b2c3be41bdbb0b7 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 May 2018 13:29:14 +0000 Subject: [PATCH 05/13] Fix memory errors associated with argv in the CLI when it is compiled on Windows. FossilOrigin-Name: 4474d69b5c21b4e6f0d1376fbceca0f18c715ff673aea63053a02bfbe041d03b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 13 ++++++++++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 90956c0afc..c4b5932c03 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite3_str_new()\sinterface\sso\sthat\sit\salways\sreturns\sa\svalid\nand\snon-NULL\spointer\seven\sin\san\sOOM\scondition. -D 2018-05-16T15:35:03.770 +C Fix\smemory\serrors\sassociated\swith\sargv\sin\sthe\sCLI\swhen\sit\sis\ncompiled\son\sWindows. +D 2018-05-17T13:29:14.965 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in 53affa90711f280342f7238f9c9aa9dcaed321ec6218a18043cf92154ef8a704 +F src/shell.c.in e4086ed1af95dc9430e628e4dc9fadae91111d5f241fca11b68b8105896c5f2c F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b45b18850c59f22a163ee482f529f578a8798f96d0e26b5a061d336d480a1540 -R c3a19bb61082b137e0cb5588248c4f0e +P ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a +R 8f0e11b03bcaa4f31e83d13ec47c0763 U drh -Z 26153b062cb510be04ec5eecb2714fde +Z 09fcdd5831882bd1e0d99424cf0a518a diff --git a/manifest.uuid b/manifest.uuid index c2200e96a6..3253138b2b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a \ No newline at end of file +4474d69b5c21b4e6f0d1376fbceca0f18c715ff673aea63053a02bfbe041d03b \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c50c92ec64..c48659c9f5 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8285,6 +8285,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 */ @@ -8308,7 +8312,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 Date: Thu, 17 May 2018 14:09:06 +0000 Subject: [PATCH 06/13] Improved error and help messages for the ".archive" command and "-A" option to the CLI. If a memory leak in --list processing. FossilOrigin-Name: 02541ac6f919a8a8b18ef0525c4ee24fdbc5c1883171fb1a492434cd0f006f7c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 39 +++++++++++++++++++++++---------------- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index c4b5932c03..64995aa5ff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smemory\serrors\sassociated\swith\sargv\sin\sthe\sCLI\swhen\sit\sis\ncompiled\son\sWindows. -D 2018-05-17T13:29:14.965 +C Improved\serror\sand\shelp\smessages\sfor\sthe\s".archive"\scommand\sand\s"-A"\soption\nto\sthe\sCLI.\sIf\sa\smemory\sleak\sin\s--list\sprocessing. +D 2018-05-17T14:09:06.396 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in e4086ed1af95dc9430e628e4dc9fadae91111d5f241fca11b68b8105896c5f2c +F src/shell.c.in d9154a6b52ce772717894e4045a336eb7ceeab87dee1976273f4621c809c72ea F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ed5b09680fd6659ebbe5ace3c1c56f3962bbd75cfdf65c7565651900cf87917a -R 8f0e11b03bcaa4f31e83d13ec47c0763 +P 4474d69b5c21b4e6f0d1376fbceca0f18c715ff673aea63053a02bfbe041d03b +R 835a789214eecbe14ece19d570e27697 U drh -Z 09fcdd5831882bd1e0d99424cf0a518a +Z 40bf372b75111f9f6f7fc064ea2d367d diff --git a/manifest.uuid b/manifest.uuid index 3253138b2b..27b690eaeb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4474d69b5c21b4e6f0d1376fbceca0f18c715ff673aea63053a02bfbe041d03b \ No newline at end of file +02541ac6f919a8a8b18ef0525c4ee24fdbc5c1883171fb1a492434cd0f006f7c \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c48659c9f5..c517778bdc 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4874,6 +4874,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 */ @@ -4920,13 +4921,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; } @@ -4957,7 +4963,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; @@ -5017,8 +5023,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; @@ -5030,11 +5034,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++]; } @@ -5068,7 +5072,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) ){ @@ -5076,7 +5080,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]; } @@ -5098,7 +5102,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; } @@ -5106,11 +5110,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]; } @@ -5239,6 +5243,7 @@ static int arListCommand(ArCommand *pAr){ } } shellFinalize(&rc, pSql); + sqlite3_free(zWhere); return rc; } @@ -5441,12 +5446,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; @@ -5493,7 +5500,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) ){ @@ -5609,7 +5616,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 @@ -8649,9 +8656,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ open_db(&data, 0); 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; From be4ccb283848667b92224e6e6be2ad9e7d9521db Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 17 May 2018 20:04:24 +0000 Subject: [PATCH 07/13] In the CLI with the -A command, if the file does not previously exist and its name looks like a ZIP archive name, then create it as a ZIP archive. FossilOrigin-Name: 33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 33 +++++++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 64995aa5ff..0e98844ccb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\serror\sand\shelp\smessages\sfor\sthe\s".archive"\scommand\sand\s"-A"\soption\nto\sthe\sCLI.\sIf\sa\smemory\sleak\sin\s--list\sprocessing. -D 2018-05-17T14:09:06.396 +C In\sthe\sCLI\swith\sthe\s-A\scommand,\sif\sthe\sfile\sdoes\snot\spreviously\sexist\sand\nits\sname\slooks\slike\sa\sZIP\sarchive\sname,\sthen\screate\sit\sas\sa\sZIP\sarchive. +D 2018-05-17T20:04:24.639 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in d9154a6b52ce772717894e4045a336eb7ceeab87dee1976273f4621c809c72ea +F src/shell.c.in e0f006980883e238555c5ab51bd2dad9fa477c31928419f6d35774288b94853b F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4474d69b5c21b4e6f0d1376fbceca0f18c715ff673aea63053a02bfbe041d03b -R 835a789214eecbe14ece19d570e27697 +P 02541ac6f919a8a8b18ef0525c4ee24fdbc5c1883171fb1a492434cd0f006f7c +R 5813b43636e3c1dfad760cb10ce61cfe U drh -Z 40bf372b75111f9f6f7fc064ea2d367d +Z acb1b3ae3afe9e045167e0aeea3fdccf diff --git a/manifest.uuid b/manifest.uuid index 27b690eaeb..90d0b49d16 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02541ac6f919a8a8b18ef0525c4ee24fdbc5c1883171fb1a492434cd0f006f7c \ No newline at end of file +33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index c517778bdc..946b5eff47 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3547,8 +3547,11 @@ int deduceDatabaseType(const char *zName, int dfltZip){ 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); @@ -3568,17 +3571,31 @@ int deduceDatabaseType(const char *zName, int dfltZip){ 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 ){ @@ -3605,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 @@ -6523,7 +6540,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); @@ -8653,7 +8670,7 @@ 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, 1, argv+(i-1), argc-(i-1)); From 6c319e123811cc091911750cc9c0019798fb2dce Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 13:39:00 +0000 Subject: [PATCH 08/13] Improvements to the sqlite3IntFloatCompare() routine for systems that lack the long double type. FossilOrigin-Name: ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 9 +++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 0e98844ccb..3556865476 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sCLI\swith\sthe\s-A\scommand,\sif\sthe\sfile\sdoes\snot\spreviously\sexist\sand\nits\sname\slooks\slike\sa\sZIP\sarchive\sname,\sthen\screate\sit\sas\sa\sZIP\sarchive. -D 2018-05-17T20:04:24.639 +C Improvements\sto\sthe\ssqlite3IntFloatCompare()\sroutine\sfor\ssystems\sthat\nlack\sthe\slong\sdouble\stype. +D 2018-05-18T13:39:00.453 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -567,7 +567,7 @@ 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/vdbeaux.c 8442dd6b7aec70e034cee8221ca8fd906706c475072390e3cb8d9b498b31f4c5 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 02541ac6f919a8a8b18ef0525c4ee24fdbc5c1883171fb1a492434cd0f006f7c -R 5813b43636e3c1dfad760cb10ce61cfe +P 33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 +R 172d94da653421dfa4a13bdf39921f71 U drh -Z acb1b3ae3afe9e045167e0aeea3fdccf +Z c89655e68cdf9c04b590b1bb59f1f9b2 diff --git a/manifest.uuid b/manifest.uuid index 90d0b49d16..b6047ecbff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 \ No newline at end of file +ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 210712a8aa..76b46acbb8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3917,16 +3917,13 @@ 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( iy ){ - if( y==SMALLEST_INT64 && r>0.0 ) return -1; - return +1; - } + if( i>y ) return +1; s = (double)i; if( sr ) return +1; + if( NEVER(s>r) ) return +1; return 0; } } From 8d1751b6fa52c6fb6205c5403592c8dbb2e9ad97 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 14:19:35 +0000 Subject: [PATCH 09/13] Remove incorrect NEVER() macro added by the previous check-in. FossilOrigin-Name: 3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3556865476..6ce6e677e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\ssqlite3IntFloatCompare()\sroutine\sfor\ssystems\sthat\nlack\sthe\slong\sdouble\stype. -D 2018-05-18T13:39:00.453 +C Remove\sincorrect\sNEVER()\smacro\sadded\sby\sthe\sprevious\scheck-in. +D 2018-05-18T14:19:35.018 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -567,7 +567,7 @@ F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 -F src/vdbeaux.c 8442dd6b7aec70e034cee8221ca8fd906706c475072390e3cb8d9b498b31f4c5 +F src/vdbeaux.c 3b0650dbebebb196010d8af830551e61ea7dcc0e414a2b747f897305b0bd0b8f F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f @@ -1728,7 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 -R 172d94da653421dfa4a13bdf39921f71 +P ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677 +R 95f9dad3dedc0c1d42618371aa8f363f U drh -Z c89655e68cdf9c04b590b1bb59f1f9b2 +Z e422d7782a1b78611c0889726293f8af diff --git a/manifest.uuid b/manifest.uuid index b6047ecbff..fd4db6cc22 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677 \ No newline at end of file +3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 76b46acbb8..4b07647519 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3923,7 +3923,7 @@ static int sqlite3IntFloatCompare(i64 i, double r){ if( i>y ) return +1; s = (double)i; if( sr) ) return +1; + if( s>r ) return +1; return 0; } } From 252f39619aec89bac9148e9534c41d2bf61532d7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 15:21:43 +0000 Subject: [PATCH 10/13] Improved error messages. Limit the number of auxiliary columns to 100. FossilOrigin-Name: 059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef --- ext/rtree/rtree.c | 8 ++++++-- ext/rtree/rtree1.test | 32 ++++++++++++++++++++++++++++++++ manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 5d76a8d801..e569c94ace 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -95,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. @@ -3554,10 +3557,11 @@ static int rtreeInit( "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 */ - "AUX: columns must be last" /* 4 */ + "Auxiliary rtree columns must be last" /* 4 */ }; - if( argc>=256 ){ + 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; } diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index ac6e8d9d96..ed154cd3a3 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -609,5 +609,37 @@ 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}} + + + + + expand_all_sql db finish_test diff --git a/manifest b/manifest index 76e14de3ae..becef90153 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sissue\swith\srtreecheck()\sand\sauxiliary\sdata\scolumns. -D 2018-05-16T19:56:20.915 +C Improved\serror\smessages.\s\sLimit\sthe\snumber\sof\sauxiliary\scolumns\sto\s100. +D 2018-05-18T15:21:43.725 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,9 +355,9 @@ 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 90c35907cedf73c7b2a69497f88a17da266616ee6f7bced787f8cc49002d4372 +F ext/rtree/rtree.c b590972cdca5595fcd494697328971d7b142b9345ed8145fab2ca5e93286a3a0 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 -F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972 +F ext/rtree/rtree1.test 0300c431a6b78a59ca001af22f2e9ae4f54ccb7139cae1b70d654e4403f4d233 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499 F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b @@ -1729,7 +1729,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c -R 7a064c4cbbc33c8c1ab943f10eb67b1c +P 46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60 +R b5f8deb455b8613a5ff615c4f1065cf5 U drh -Z 2eb6f867a66e47a61ca5b21b3b9da89e +Z 905a75dcd2e1b90246040880bfb14954 diff --git a/manifest.uuid b/manifest.uuid index 1fa5732712..d66723f675 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60 \ No newline at end of file +059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef \ No newline at end of file From 136c9903bffb993326fbc5dd71f3067f787f98ca Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 16:46:09 +0000 Subject: [PATCH 11/13] Fix a prepare-statement leak. FossilOrigin-Name: 95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1 --- ext/rtree/rtree.c | 1 + ext/rtree/rtree1.test | 12 +++++++++--- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index e569c94ace..b39e5801b2 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1727,6 +1727,7 @@ static int rtreeFilter( /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ freeCursorConstraints(pCsr); sqlite3_free(pCsr->aPoint); + sqlite3_finalize(pCsr->pReadAux); memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = (sqlite3_vtab*)pRtree; diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index ed154cd3a3..a8ebf20625 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -637,9 +637,15 @@ do_test 16.120 { 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 diff --git a/manifest b/manifest index becef90153..f963313acd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\serror\smessages.\s\sLimit\sthe\snumber\sof\sauxiliary\scolumns\sto\s100. -D 2018-05-18T15:21:43.725 +C Fix\sa\sprepare-statement\sleak. +D 2018-05-18T16:46:09.315 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,9 +355,9 @@ 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 b590972cdca5595fcd494697328971d7b142b9345ed8145fab2ca5e93286a3a0 +F ext/rtree/rtree.c 22f70cfd945a35f22c825dd33a387f8e4a760e836dbdb5b53c8604c013baa70b F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 -F ext/rtree/rtree1.test 0300c431a6b78a59ca001af22f2e9ae4f54ccb7139cae1b70d654e4403f4d233 +F ext/rtree/rtree1.test 587889855b26fb8637417921b0709ca843cb6d36db94a882371fd8b7dcc3aa0b F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499 F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b @@ -1729,7 +1729,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60 -R b5f8deb455b8613a5ff615c4f1065cf5 +P 059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef +R 94d7d699dafad8b4359ea156ee884062 U drh -Z 905a75dcd2e1b90246040880bfb14954 +Z c84439bc3f7cc8054f4dee343e2e07a0 diff --git a/manifest.uuid b/manifest.uuid index d66723f675..a1b0e94190 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef \ No newline at end of file +95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1 \ No newline at end of file From a02fd67b99f33960a4c2e977f8c3f9c43d84f993 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 16:53:07 +0000 Subject: [PATCH 12/13] Avoid unnecessary sqlite3_finalize() operations. FossilOrigin-Name: 16f71032a3a2919cb226b25b5256a370adb5c55fa506d4774b7f83dc8868e793 --- ext/rtree/rtree.c | 4 +++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index b39e5801b2..c4c536f8ce 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1721,15 +1721,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); - sqlite3_finalize(pCsr->pReadAux); + pStmt = pCsr->pReadAux; memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = (sqlite3_vtab*)pRtree; + pCsr->pReadAux = pStmt; pCsr->iStrategy = idxNum; if( idxNum==1 ){ diff --git a/manifest b/manifest index f963313acd..bf8c2873b8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sprepare-statement\sleak. -D 2018-05-18T16:46:09.315 +C Avoid\sunnecessary\ssqlite3_finalize()\soperations. +D 2018-05-18T16:53:07.242 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,7 +355,7 @@ 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 22f70cfd945a35f22c825dd33a387f8e4a760e836dbdb5b53c8604c013baa70b +F ext/rtree/rtree.c 148ae743198ca9fe1dfdf2fed74e5c3b0e69330e5b71ddc0d9df9993324dcedc F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 587889855b26fb8637417921b0709ca843cb6d36db94a882371fd8b7dcc3aa0b F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -1729,7 +1729,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef -R 94d7d699dafad8b4359ea156ee884062 +P 95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1 +R 2d7f80f5a8cb7985e7256646130cf7be U drh -Z c84439bc3f7cc8054f4dee343e2e07a0 +Z 143ebe5c5507b367bd6154b3294d97b7 diff --git a/manifest.uuid b/manifest.uuid index a1b0e94190..643e5a1325 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1 \ No newline at end of file +16f71032a3a2919cb226b25b5256a370adb5c55fa506d4774b7f83dc8868e793 \ No newline at end of file From 9e80403bfcd0eef10f1ef9c075073a15898816b1 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 May 2018 17:11:50 +0000 Subject: [PATCH 13/13] In the CLI, detect and report errors on sqlite3_close(). Clear global variables prior to exit to so that valgrind can better detect resource leaks. FossilOrigin-Name: e3b2e0a078b82ac6cd3c3312e8ac0983c1375e1052f1e324476d2f8d1b227c30 --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/shell.c.in | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 17ab14e328..8659a25d5b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sinteger/float\scomparisons\son\sarchitectures\sthat\slack\sa\n"long\sdouble"\stype. -D 2018-05-18T14:24:23.139 +C In\sthe\sCLI,\sdetect\sand\sreport\serrors\son\ssqlite3_close().\s\sClear\sglobal\nvariables\sprior\sto\sexit\sto\sso\sthat\svalgrind\scan\sbetter\sdetect\sresource\nleaks. +D 2018-05-18T17:11:50.887 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -494,7 +494,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 -F src/shell.c.in e0f006980883e238555c5ab51bd2dad9fa477c31928419f6d35774288b94853b +F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -1728,8 +1728,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 33dc8fad7f2b467f259eb78eb7342a760f01d54d95da7fe4cace10e558788a58 3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3 -R 95f9dad3dedc0c1d42618371aa8f363f -T +closed 3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3 +P 5139ea62a8a6c6dc6558c337de39bcbadd26f6515742263387be03c862c78cf0 +R b8765ab2a09ad6fd3afc8344422cf1a3 U drh -Z 5a624356c837c7a872fedd9425b35399 +Z d089a713f2ba352bce4662bcdd3c7d90 diff --git a/manifest.uuid b/manifest.uuid index 21e2e660dc..0b799613c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5139ea62a8a6c6dc6558c337de39bcbadd26f6515742263387be03c862c78cf0 \ No newline at end of file +e3b2e0a078b82ac6cd3c3312e8ac0983c1375e1052f1e324476d2f8d1b227c30 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 946b5eff47..e7cc36f477 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3656,6 +3656,17 @@ static void open_db(ShellState *p, int openFlags){ } } +/* +** Attempt to close the databaes connection. Report errors. +*/ +void close_db(sqlite3 *db){ + int rc = sqlite3_close(db); + if( rc ){ + utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", + rc, sqlite3_errmsg(db)); + } +} + #if HAVE_READLINE || HAVE_EDITLINE /* ** Readline completion callbacks @@ -4236,7 +4247,7 @@ static void tryToClone(ShellState *p, const char *zNewDb){ sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); } - sqlite3_close(newDb); + close_db(newDb); } /* @@ -5553,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); @@ -5676,14 +5687,14 @@ static int do_meta_command(char *zLine, ShellState *p){ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs); if( rc!=SQLITE_OK ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); - sqlite3_close(pDest); + close_db(pDest); return 1; } open_db(p, 0); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); if( pBackup==0 ){ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); - sqlite3_close(pDest); + close_db(pDest); return 1; } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} @@ -5694,7 +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 ){ @@ -6510,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); @@ -6690,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 @@ -6717,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 ){ @@ -7401,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 @@ -7409,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++){ @@ -8754,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); @@ -8765,5 +8780,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ for(i=0; i