From 784156f84c7a64d0546ec600a0e7ce0612b48565 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 12 Feb 2014 14:43:52 +0000 Subject: [PATCH 01/66] Make sure "rowid" columns are correctly resolved in joins between normal tables and WITHOUT ROWID tables. Fix for ticket [c34d0557f740c45070]. FossilOrigin-Name: 5d01426ddfb2d47c57f93f71378594e637424be0 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/resolve.c | 4 ++-- test/without_rowid1.test | 16 +++++++++++++++- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 19a6fafab1..e5839e439d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.8.4 -D 2014-02-11T16:24:34.448 +C Make\ssure\s"rowid"\scolumns\sare\scorrectly\sresolved\sin\sjoins\sbetween\snormal\ntables\sand\sWITHOUT\sROWID\stables.\s\sFix\sfor\sticket\s[c34d0557f740c45070]. +D 2014-02-12T14:43:52.953 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece -F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 +F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 50961f0d0ab8f2d45ff29ec5f91d8db221330ca7 F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 @@ -1096,7 +1096,7 @@ F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068 F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 -F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8 +F test/without_rowid1.test e00a0a9dc9f0be651f011d61e8a32b7add5afb30 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a @@ -1153,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P f5ad1e1bf2828c5da70c1ff944d8212036142e6f -R 07c665af95e97929880dcb47f3f495f9 +P 0a8bcbbd4e11a60923736b2be9b1ce83ea2263fb +R ece7306a4645e7a68a79bfe14ec94970 U drh -Z 585a1fb26982d5587e4e3f114773e866 +Z 89db972fa80a38407f6b56a44d53bf78 diff --git a/manifest.uuid b/manifest.uuid index a4c42c8f7f..564e92ae29 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a8bcbbd4e11a60923736b2be9b1ce83ea2263fb \ No newline at end of file +5d01426ddfb2d47c57f93f71378594e637424be0 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index b0adb86295..07e0e919a5 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -380,8 +380,8 @@ static int lookupName( /* ** Perhaps the name is a reference to the ROWID */ - assert( pTab!=0 || cntTab==0 ); - if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) && HasRowid(pTab) ){ + if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol) + && HasRowid(pMatch->pTab) ){ cnt = 1; pExpr->iColumn = -1; /* IMP: R-44911-55124 */ pExpr->affinity = SQLITE_AFF_INTEGER; diff --git a/test/without_rowid1.test b/test/without_rowid1.test index 1a53d26e66..bdd03c57bb 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -198,6 +198,20 @@ do_execsql_test 3.1.5 { INSERT INTO t3 SELECT * FROM t4; SELECT * FROM t3; } {i ii iii} + +############################################################################ +# Ticket [c34d0557f740c450709d6e33df72d4f3f651a3cc] +# Name resolution issue with WITHOUT ROWID +# +do_execsql_test 4.1 { + CREATE TABLE t41(a PRIMARY KEY) WITHOUT ROWID; + INSERT INTO t41 VALUES('abc'); + CREATE TABLE t42(x); + INSERT INTO t42 VALUES('xyz'); + SELECT t42.rowid FROM t41, t42; +} {1} +do_execsql_test 4.2 { + SELECT t42.rowid FROM t42, t41; +} {1} finish_test - From e0670b6220ce4c0819c30faefc100e9228456fc9 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 12 Feb 2014 21:31:12 +0000 Subject: [PATCH 02/66] Remove the "rowid cache" that sought to remember the largest rowid for a table and thereby speed up OP_NewRowid. That cache was ineffective. Removing it results in a performance increase of 0.4%, less memory usage, and a slightly smaller library size. FossilOrigin-Name: 56bc5ce8958c8e6250531b4052b905d7ac993db3 --- manifest | 18 +++++------ manifest.uuid | 2 +- src/btree.c | 45 ++++++-------------------- src/btree.h | 2 -- src/btreeInt.h | 1 - src/vdbe.c | 85 +++++++++++++++++++++++--------------------------- 6 files changed, 59 insertions(+), 94 deletions(-) diff --git a/manifest b/manifest index e5839e439d..fd4cbee264 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\s"rowid"\scolumns\sare\scorrectly\sresolved\sin\sjoins\sbetween\snormal\ntables\sand\sWITHOUT\sROWID\stables.\s\sFix\sfor\sticket\s[c34d0557f740c45070]. -D 2014-02-12T14:43:52.953 +C Remove\sthe\s"rowid\scache"\sthat\ssought\sto\sremember\sthe\slargest\srowid\sfor\sa\ntable\sand\sthereby\sspeed\sup\sOP_NewRowid.\s\sThat\scache\swas\sineffective.\nRemoving\sit\sresults\sin\sa\sperformance\sincrease\sof\s0.4%,\sless\smemory\susage,\nand\sa\sslightly\ssmaller\slibrary\ssize. +D 2014-02-12T21:31:12.616 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -166,9 +166,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 7b2c3cd16deedff7f4904f2e871e7b77328b9872 -F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9 -F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 +F src/btree.c 97020a77cb53fb9d8e7f172d489b8f92af1d1b82 +F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f +F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 13b9d82181d95af7b00ec8a8e1304bac096432d4 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -280,7 +280,7 @@ F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c e5c87476d717aebef5dafceab11417ebf2730554 +F src/vdbe.c 3f0872b12ec3fc24ee540f8bb09de181ddad6d8d F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -1153,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 0a8bcbbd4e11a60923736b2be9b1ce83ea2263fb -R ece7306a4645e7a68a79bfe14ec94970 +P 5d01426ddfb2d47c57f93f71378594e637424be0 +R 0f58210f2a6ea71dc58155d3b9fc47e4 U drh -Z 89db972fa80a38407f6b56a44d53bf78 +Z 0cd8ad70eddd970bc8638e6270cc29ff diff --git a/manifest.uuid b/manifest.uuid index 564e92ae29..b2a9658b53 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d01426ddfb2d47c57f93f71378594e637424be0 \ No newline at end of file +56bc5ce8958c8e6250531b4052b905d7ac993db3 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index cf135b1e14..2aac72d55c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3632,7 +3632,6 @@ static int btreeCursor( } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; - pCur->cachedRowid = 0; return SQLITE_OK; } int sqlite3BtreeCursor( @@ -3673,36 +3672,6 @@ void sqlite3BtreeCursorZero(BtCursor *p){ memset(p, 0, offsetof(BtCursor, iPage)); } -/* -** Set the cached rowid value of every cursor in the same database file -** as pCur and having the same root page number as pCur. The value is -** set to iRowid. -** -** Only positive rowid values are considered valid for this cache. -** The cache is initialized to zero, indicating an invalid cache. -** A btree will work fine with zero or negative rowids. We just cannot -** cache zero or negative rowids, which means tables that use zero or -** negative rowids might run a little slower. But in practice, zero -** or negative rowids are very uncommon so this should not be a problem. -*/ -void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){ - BtCursor *p; - for(p=pCur->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid; - } - assert( pCur->cachedRowid==iRowid ); -} - -/* -** Return the cached rowid for the given cursor. A negative or zero -** return value indicates that the rowid cache is invalid and should be -** ignored. If the rowid cache has never before been set, then a -** zero is returned. -*/ -sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){ - return pCur->cachedRowid; -} - /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. @@ -6986,11 +6955,17 @@ int sqlite3BtreeInsert( rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); if( rc ) return rc; - /* If this is an insert into a table b-tree, invalidate any incrblob - ** cursors open on the row being replaced (assuming this is a replace - ** operation - if it is not, the following is a no-op). */ if( pCur->pKeyInfo==0 ){ + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, nKey, 0); + + /* If the cursor is currently on the last row and we are appending a + ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto() + ** call */ + if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){ + loc = -1; + } } if( !loc ){ @@ -7060,8 +7035,8 @@ int sqlite3BtreeInsert( ** row without seeking the cursor. This can be a big performance boost. */ pCur->info.nSize = 0; - pCur->validNKey = 0; if( rc==SQLITE_OK && pPage->nOverflow ){ + pCur->validNKey = 0; rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() diff --git a/src/btree.h b/src/btree.h index 3eb5906955..eda7bef70a 100644 --- a/src/btree.h +++ b/src/btree.h @@ -182,8 +182,6 @@ const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt); const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt); int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); -void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); -sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); diff --git a/src/btreeInt.h b/src/btreeInt.h index 3ebdeb663e..87b4181f82 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -500,7 +500,6 @@ struct BtCursor { Pgno *aOverflow; /* Cache of overflow page locations */ #endif Pgno pgnoRoot; /* The root page of this tree */ - sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor's last known position */ diff --git a/src/vdbe.c b/src/vdbe.c index aa34ad091a..00cff1e21e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3834,59 +3834,54 @@ case OP_NewRowid: { /* out2-prerelease */ #endif if( !pC->useRandomRowid ){ - v = sqlite3BtreeGetCachedRowid(pC->pCursor); - if( v==0 ){ - rc = sqlite3BtreeLast(pC->pCursor, &res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( res ){ - v = 1; /* IMP: R-61914-48074 */ + rc = sqlite3BtreeLast(pC->pCursor, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res ){ + v = 1; /* IMP: R-61914-48074 */ + }else{ + assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); + rc = sqlite3BtreeKeySize(pC->pCursor, &v); + assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + if( v>=MAX_ROWID ){ + pC->useRandomRowid = 1; }else{ - assert( sqlite3BtreeCursorIsValid(pC->pCursor) ); - rc = sqlite3BtreeKeySize(pC->pCursor, &v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ - if( v>=MAX_ROWID ){ - pC->useRandomRowid = 1; - }else{ - v++; /* IMP: R-29538-34987 */ - } + v++; /* IMP: R-29538-34987 */ } } + } #ifndef SQLITE_OMIT_AUTOINCREMENT - if( pOp->p3 ){ + if( pOp->p3 ){ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3>0 ); + if( p->pFrame ){ + for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3>0 ); - if( p->pFrame ){ - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=pFrame->nMem ); - pMem = &pFrame->aMem[pOp->p3]; - }else{ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=(p->nMem-p->nCursor) ); - pMem = &aMem[pOp->p3]; - memAboutToChange(p, pMem); - } - assert( memIsValid(pMem) ); - - REGISTER_TRACE(pOp->p3, pMem); - sqlite3VdbeMemIntegerify(pMem); - assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ - goto abort_due_to_error; - } - if( vu.i+1 ){ - v = pMem->u.i + 1; - } - pMem->u.i = v; + assert( pOp->p3<=pFrame->nMem ); + pMem = &pFrame->aMem[pOp->p3]; + }else{ + /* Assert that P3 is a valid memory cell. */ + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pMem = &aMem[pOp->p3]; + memAboutToChange(p, pMem); } -#endif + assert( memIsValid(pMem) ); - sqlite3BtreeSetCachedRowid(pC->pCursor, vp3, pMem); + sqlite3VdbeMemIntegerify(pMem); + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + rc = SQLITE_FULL; /* IMP: R-12275-61338 */ + goto abort_due_to_error; + } + if( vu.i+1 ){ + v = pMem->u.i + 1; + } + pMem->u.i = v; } +#endif if( pC->useRandomRowid ){ /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the ** largest possible integer (9223372036854775807) then the database @@ -4020,7 +4015,6 @@ case OP_InsertInt: { }else{ nZero = 0; } - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pData->z, pData->n, nZero, (pOp->p5 & OPFLAG_APPEND)!=0, seekResult @@ -4082,7 +4076,6 @@ case OP_Delete: { rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - sqlite3BtreeSetCachedRowid(pC->pCursor, 0); rc = sqlite3BtreeDelete(pC->pCursor); pC->cacheStatus = CACHE_STALE; From fe48599294e5e09b036f8c06fddb14e6d8c55fb6 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 12 Feb 2014 23:52:16 +0000 Subject: [PATCH 03/66] Minor simplifications to the "zeroPage()" routine in btree.c. FossilOrigin-Name: cc8f10bcb206c9def69b06f26decf025b8d9119d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fd4cbee264..e344356edb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\s"rowid\scache"\sthat\ssought\sto\sremember\sthe\slargest\srowid\sfor\sa\ntable\sand\sthereby\sspeed\sup\sOP_NewRowid.\s\sThat\scache\swas\sineffective.\nRemoving\sit\sresults\sin\sa\sperformance\sincrease\sof\s0.4%,\sless\smemory\susage,\nand\sa\sslightly\ssmaller\slibrary\ssize. -D 2014-02-12T21:31:12.616 +C Minor\ssimplifications\sto\sthe\s"zeroPage()"\sroutine\sin\sbtree.c. +D 2014-02-12T23:52:16.136 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -166,7 +166,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 97020a77cb53fb9d8e7f172d489b8f92af1d1b82 +F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200 F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 13b9d82181d95af7b00ec8a8e1304bac096432d4 @@ -1153,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 5d01426ddfb2d47c57f93f71378594e637424be0 -R 0f58210f2a6ea71dc58155d3b9fc47e4 +P 56bc5ce8958c8e6250531b4052b905d7ac993db3 +R 08bd4c102c2d08f0774c76e162878c69 U drh -Z 0cd8ad70eddd970bc8638e6270cc29ff +Z ed630d5c913dd5b0515f56c704c7877e diff --git a/manifest.uuid b/manifest.uuid index b2a9658b53..2af58e32b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56bc5ce8958c8e6250531b4052b905d7ac993db3 \ No newline at end of file +cc8f10bcb206c9def69b06f26decf025b8d9119d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 2aac72d55c..4fd8e27bf4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1542,13 +1542,12 @@ static void zeroPage(MemPage *pPage, int flags){ memset(&data[hdr], 0, pBt->usableSize - hdr); } data[hdr] = (char)flags; - first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); + first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8); memset(&data[hdr+1], 0, 4); data[hdr+7] = 0; put2byte(&data[hdr+5], pBt->usableSize); pPage->nFree = (u16)(pBt->usableSize - first); decodeFlags(pPage, flags); - pPage->hdrOffset = hdr; pPage->cellOffset = first; pPage->aDataEnd = &data[pBt->usableSize]; pPage->aCellIdx = &data[first]; From 962f9669b6cb5f476deced48107b5b3a7525508d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 13 Feb 2014 13:42:43 +0000 Subject: [PATCH 04/66] Update the tclconfig files to the latest from http://core.tcl.tk/tclconfig. FossilOrigin-Name: b81ba7a4bc7e840fce25fc6801957a64f877ff60 --- autoconf/tea/tclconfig/install-sh | 569 +++++++++++++++++++++++++----- autoconf/tea/tclconfig/tcl.m4 | 458 ++++++++++++++++-------- manifest | 14 +- manifest.uuid | 2 +- 4 files changed, 810 insertions(+), 233 deletions(-) diff --git a/autoconf/tea/tclconfig/install-sh b/autoconf/tea/tclconfig/install-sh index 0ff4b6a08e..7c34c3f926 100644 --- a/autoconf/tea/tclconfig/install-sh +++ b/autoconf/tea/tclconfig/install-sh @@ -1,119 +1,528 @@ #!/bin/sh - -# # install - install a program, script, or datafile -# This comes from X11R5; it is not part of GNU. + +scriptversion=2011-04-20.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. # -# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. -# +nl=' +' +IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi +# Put in absolute file names if you don't have them in your path; +# or use environment vars. -# put in absolute paths if you don't have them in your path; or use env. vars. +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' -instcmd="$mvprog" -chmodcmd="" -chowncmd="" -chgrpcmd="" -stripcmd="" +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" +stripcmd= -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; +src= +dst= +dir_arg= +dst_arg= - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; +copy_on_change=false +no_target_directory= - -o) chowncmd="$chownprog $2" - shift - shift - continue;; +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. - -s) stripcmd="$stripprog" - shift - continue;; +Options: + --help display this help and exit. + --version display version info and exit. - *) if [ x"$src" = x ] - then - src=$1 - else - dst=$1 - fi - shift - continue;; - esac + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -S $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -S) stripcmd="$stripprog $2" + shift;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift done -if [ x"$src" = x ] -then - echo "install: no input file specified" +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 exit 1 -fi + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` -if [ x"$dst" = x ] -then - echo "install: no destination specified" - exit 1 -fi + test -d "$dstdir" + dstdir_status=$? + fi + fi + obsolete_mkdir_used=false -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; -if [ -d $dst ] -then - dst="$dst"/`basename $src` -fi + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac -# Make a temp file name in the proper directory. + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi -dstdir=`dirname $dst` -dsttmp=$dstdir/#inst.$$# + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 -# Move or copy the file name to the temp name + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac -$doit $instcmd $src $dsttmp + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else -# and set any options; do chmod last to preserve setuid bits + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. -if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi -if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi -if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi -if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac -# Now rename the file to the real destination. + eval "$initialize_posix_glob" -$doit $rmcmd $dst -$doit $mvcmd $dsttmp $dst + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + prefixes= -exit 0 + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/autoconf/tea/tclconfig/tcl.m4 b/autoconf/tea/tclconfig/tcl.m4 index f910bc2a1f..66214e78a2 100644 --- a/autoconf/tea/tclconfig/tcl.m4 +++ b/autoconf/tea/tclconfig/tcl.m4 @@ -8,8 +8,6 @@ # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. -# -# RCS: @(#) $Id: tcl.m4,v 1.145 2010/08/17 00:33:40 hobbs Exp $ AC_PREREQ(2.57) @@ -140,6 +138,8 @@ AC_DEFUN([TEA_PATH_TCLCONFIG], [ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/lib/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" @@ -170,7 +170,7 @@ AC_DEFUN([TEA_PATH_TCLCONFIG], [ if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" - AC_MSG_ERROR([Can't find Tcl configuration definitions]) + AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" @@ -323,7 +323,7 @@ AC_DEFUN([TEA_PATH_TKCONFIG], [ if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" - AC_MSG_ERROR([Can't find Tk configuration definitions]) + AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" @@ -344,11 +344,10 @@ AC_DEFUN([TEA_PATH_TKCONFIG], [ # # Results: # -# Subst the following vars: +# Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE -# #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TCLCONFIG], [ @@ -417,32 +416,26 @@ AC_DEFUN([TEA_LOAD_TCLCONFIG], [ AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) - case "`uname -s`" in - *CYGWIN_*) - AC_MSG_CHECKING([for cygwin variant]) - case ${TCL_EXTRA_CFLAGS} in - *-mwin32*|*-mno-cygwin*) - TEA_PLATFORM="windows" - CFLAGS="$CFLAGS -mwin32" - AC_MSG_RESULT([win32]) - ;; - *) - TEA_PLATFORM="unix" - AC_MSG_RESULT([unix]) - ;; - esac - EXEEXT=".exe" - ;; - *) - ;; - esac + AC_MSG_CHECKING([platform]) + hold_cc=$CC; CC="$TCL_CC" + AC_TRY_COMPILE(,[ + #ifdef _WIN32 + #error win32 + #endif + ], TEA_PLATFORM="unix", + TEA_PLATFORM="windows" + ) + CC=$hold_cc + AC_MSG_RESULT($TEA_PLATFORM) + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], + [Building extension source?]) # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then - # The BUILD_$pkg is to define the correct extern storage class - # handling when making this package - AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}) - CLEANFILES="$CLEANFILES *.lib *.dll *.pdb" + EXEEXT=".exe" + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: @@ -566,11 +559,11 @@ AC_DEFUN([TEA_LOAD_TKCONFIG], [ # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # -# Arguments +# Arguments: # none # -# Results -# Subst's the following values: +# Results: +# Substitutes the following vars: # TCLSH_PROG #------------------------------------------------------------------------ @@ -616,11 +609,11 @@ AC_DEFUN([TEA_PROG_TCLSH], [ # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # -# Arguments +# Arguments: # none # -# Results -# Subst's the following values: +# Results: +# Substitutes the following vars: # WISH_PROG #------------------------------------------------------------------------ @@ -731,7 +724,6 @@ AC_DEFUN([TEA_ENABLE_SHARED], [ # TCL_THREADS # _REENTRANT # _THREAD_SAFE -# #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_THREADS], [ @@ -855,12 +847,11 @@ AC_DEFUN([TEA_ENABLE_THREADS], [ # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true -# Sets to $(CFLAGS_OPTIMIZE) if false +# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false # DBGX Formerly used as debug library extension; # always blank now. -# #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ @@ -873,7 +864,7 @@ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ [tcl_ok=$enableval], [tcl_ok=no]) DBGX="" if test "$tcl_ok" = "no"; then - CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE}" + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" AC_MSG_RESULT([no]) else @@ -920,7 +911,6 @@ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ # # Defines the following vars: # HAVE_LANGINFO Triggers use of nl_langinfo if defined. -# #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_LANGINFO], [ @@ -961,7 +951,6 @@ AC_DEFUN([TEA_ENABLE_LANGINFO], [ # Defines the following var: # # system - System/platform/version identification code. -# #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_SYSTEM], [ @@ -1030,21 +1019,20 @@ AC_DEFUN([TEA_CONFIG_SYSTEM], [ # extensions. An empty string means we don't know how # to use shared libraries on this platform. # LIB_SUFFIX - Specifies everything that comes after the "libfoo" -# in a static or shared library name, using the $VERSION variable +# in a static or shared library name, using the $PACKAGE_VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. -# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs -# to have a version after the .so, and ${VERSION}.a +# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${PACKAGE_VERSION}.a # on AIX, since a shared library needs to have # a .a extension whereas shared objects for loadable # extensions have a .so extension. Defaults to -# ${VERSION}${SHLIB_SUFFIX}. +# ${PACKAGE_VERSION}${SHLIB_SUFFIX}. # CFLAGS_DEBUG - # Flags used when running the compiler in debug mode # CFLAGS_OPTIMIZE - # Flags used when running the compiler in optimize mode # CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) -# #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_CFLAGS], [ @@ -1086,6 +1074,7 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [ AC_DEFINE(MODULE_SCOPE, [extern __attribute__((__visibility__("hidden")))], [Compiler support for module scope symbols]) + AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ]) # Step 0.d: Disable -rpath support? @@ -1134,15 +1123,14 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [ ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g - CFLAGS_OPTIMIZE=-O AS_IF([test "$GCC" = yes], [ - # TEA specific: CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" - ], [CFLAGS_WARNING=""]) -dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed. -dnl AC_CHECK_TOOL(AR, ar) - AC_CHECK_PROG(AR, ar, ar) + ], [ + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + ]) + AC_CHECK_TOOL(AR, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"]) @@ -1171,7 +1159,7 @@ dnl AC_CHECK_TOOL(AR, ar) PATH64="${MSSDK}/Bin/Win64" ;; esac - if test ! -d "${PATH64}" ; then + if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) AC_MSG_WARN([Ensure latest Platform SDK is installed]) do64bit="no" @@ -1288,7 +1276,7 @@ dnl AC_CHECK_TOOL(AR, ar) else RC="rc" lflags="-nologo" - LINKBIN="link" + LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi @@ -1296,13 +1284,43 @@ dnl AC_CHECK_TOOL(AR, ar) if test "$GCC" = "yes"; then # mingw gcc mode - RC="windres" + AC_CHECK_TOOL(RC, windres) CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" - SHLIB_LD="$CC -shared" + SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + + AC_CACHE_CHECK(for cross-compile version of gcc, + ac_cv_cross, + AC_TRY_COMPILE([ + #ifdef _WIN32 + #error cross-compiler + #endif + ], [], + ac_cv_cross=yes, + ac_cv_cross=no) + ) + if test "$ac_cv_cross" = "yes"; then + case "$do64bit" in + amd64|x64|yes) + CC="x86_64-w64-mingw32-gcc" + LD="x86_64-w64-mingw32-ld" + AR="x86_64-w64-mingw32-ar" + RANLIB="x86_64-w64-mingw32-ranlib" + RC="x86_64-w64-mingw32-windres" + ;; + *) + CC="i686-w64-mingw32-gcc" + LD="i686-w64-mingw32-ld" + AR="i686-w64-mingw32-ar" + RANLIB="i686-w64-mingw32-ranlib" + RC="i686-w64-mingw32-windres" + ;; + esac + fi + else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg @@ -1409,7 +1427,8 @@ dnl AC_CHECK_TOOL(AR, ar) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" - EXE_SUFFIX=".exe" + EXEEXT=".exe" + do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; @@ -1438,7 +1457,7 @@ dnl AC_CHECK_TOOL(AR, ar) ]) AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ - LDFLAGS="$LDFLAGS -E" + LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' LD_LIBRARY_PATH_VAR="SHLIB_PATH" @@ -1520,7 +1539,7 @@ dnl AC_CHECK_TOOL(AR, ar) ]) ]) ;; - Linux*) + Linux*|GNU*|NetBSD-Debian) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" @@ -1553,17 +1572,6 @@ dnl AC_CHECK_TOOL(AR, ar) # files in compat/*.c is being linked in. AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) - - ;; - GNU*) - SHLIB_CFLAGS="-fPIC" - SHLIB_SUFFIX=".so" - - SHLIB_LD='${CC} -shared' - LDFLAGS="$LDFLAGS -Wl,--export-dynamic" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) ;; Lynx*) SHLIB_CFLAGS="-fPIC" @@ -1576,35 +1584,44 @@ dnl AC_CHECK_TOOL(AR, ar) LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ;; OpenBSD-*) - SHLIB_CFLAGS="-fPIC" - SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' - SHLIB_SUFFIX=".so" - AS_IF([test $doRpath = yes], [ - CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) - LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' - AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ - AC_EGREP_CPP(yes, [ -#ifdef __ELF__ - yes -#endif - ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) - AS_IF([test $tcl_cv_ld_elf = yes], [ - LDFLAGS=-Wl,-export-dynamic - ], [LDFLAGS=""]) + arch=`arch -s` + case "$arch" in + vax) + SHLIB_SUFFIX="" + SHARED_LIB_SUFFIX="" + LDFLAGS="" + ;; + *) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + ;; + esac + case "$arch" in + vax) + CFLAGS_OPTIMIZE="-O1" + ;; + *) + CFLAGS_OPTIMIZE="-O2" + ;; + esac AS_IF([test "${TCL_THREADS}" = "1"], [ - # OpenBSD builds and links with -pthread, never -lpthread. + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" - SHLIB_CFLAGS="$SHLIB_CFLAGS -pthread" ]) # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; - NetBSD-*|FreeBSD-[[3-4]].*) - # FreeBSD 3.* and greater have ELF. - # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' SHLIB_SUFFIX=".so" @@ -1618,32 +1635,24 @@ dnl AC_CHECK_TOOL(AR, ar) CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) - case $system in - FreeBSD-3.*) - # FreeBSD-3 doesn't handle version numbers with dots. - UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' - SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' - TCL_LIB_VERSIONS_OK=nodots - ;; - esac ;; FreeBSD-*) # This configuration from FreeBSD Ports. SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -shared" - TCL_SHLIB_LD_EXTRAS="-soname \$[@]" + TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]" SHLIB_SUFFIX=".so" LDFLAGS="" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' - LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) # Version numbers are dot-stripped by system policy. - TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' TCL_LIB_VERSIONS_OK=nodots @@ -1705,7 +1714,7 @@ dnl AC_CHECK_TOOL(AR, ar) AS_IF([test $tcl_cv_ld_single_module = yes], [ SHLIB_LD="${SHLIB_LD} -Wl,-single_module" ]) - # TEA specific: link shlib with current and compatiblity version flags + # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" @@ -1941,6 +1950,24 @@ dnl AC_CHECK_TOOL(AR, ar) LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ]) ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_Bexport = yes], [ + LDFLAGS="$LDFLAGS -Wl,-Bexport" + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; esac AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ @@ -1965,7 +1992,7 @@ dnl # preprocessing tests use only CPPFLAGS. case $system in AIX-*) ;; BSD/OS*) ;; - CYGWIN_*) ;; + CYGWIN_*|MINGW32_*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; @@ -1977,15 +2004,109 @@ dnl # preprocessing tests use only CPPFLAGS. AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [extern], [No Compiler support for module scope symbols]) - AC_DEFINE(NO_VIZ) ]) AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ - # TEA specific: use PACKAGE_VERSION instead of VERSION - SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ - # TEA specific: use PACKAGE_VERSION instead of VERSION - UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) + + if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then + AC_CACHE_CHECK(for SEH support in compiler, + tcl_cv_seh, + AC_TRY_RUN([ +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + + int main(int argc, char** argv) { + int a, b = 0; + __try { + a = 666 / b; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; + } + ], + tcl_cv_seh=yes, + tcl_cv_seh=no, + tcl_cv_seh=no) + ) + if test "$tcl_cv_seh" = "no" ; then + AC_DEFINE(HAVE_NO_SEH, 1, + [Defined when mingw does not support SEH]) + fi + + # + # Check to see if the excpt.h include file provided contains the + # definition for EXCEPTION_DISPOSITION; if not, which is the case + # with Cygwin's version as of 2002-04-10, define it to be int, + # sufficient for getting the current code to work. + # + AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, + tcl_cv_eh_disposition, + AC_TRY_COMPILE([ +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN + ],[ + EXCEPTION_DISPOSITION x; + ], + tcl_cv_eh_disposition=yes, + tcl_cv_eh_disposition=no) + ) + if test "$tcl_cv_eh_disposition" = "no" ; then + AC_DEFINE(EXCEPTION_DISPOSITION, int, + [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) + fi + + # Check to see if winnt.h defines CHAR, SHORT, and LONG + # even if VOID has already been #defined. The win32api + # used by mingw and cygwin is known to do this. + + AC_CACHE_CHECK(for winnt.h that ignores VOID define, + tcl_cv_winnt_ignore_void, + AC_TRY_COMPILE([ +#define VOID void +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + ], [ + CHAR c; + SHORT s; + LONG l; + ], + tcl_cv_winnt_ignore_void=yes, + tcl_cv_winnt_ignore_void=no) + ) + if test "$tcl_cv_winnt_ignore_void" = "yes" ; then + AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, + [Defined when cygwin/mingw ignores VOID define in winnt.h]) + fi + fi + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + AC_CACHE_CHECK(for cast to union support, + tcl_cv_cast_to_union, + AC_TRY_COMPILE([], + [ + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + ], + tcl_cv_cast_to_union=yes, + tcl_cv_cast_to_union=no) + ) + if test "$tcl_cv_cast_to_union" = "yes"; then + AC_DEFINE(HAVE_CAST_TO_UNION, 1, + [Defined when compiler supports casting to union type.]) + fi AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) @@ -2024,7 +2145,6 @@ dnl # preprocessing tests use only CPPFLAGS. # USE_TERMIOS # USE_TERMIO # USE_SGTTY -# #-------------------------------------------------------------------- AC_DEFUN([TEA_SERIAL_PORT], [ @@ -2236,7 +2356,6 @@ closedir(d); # XINCLUDES # XLIBSW # PKG_LIBS (appends to) -# #-------------------------------------------------------------------- AC_DEFUN([TEA_PATH_X], [ @@ -2250,9 +2369,9 @@ AC_DEFUN([TEA_PATH_UNIX_X], [ not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then - AC_TRY_CPP([#include ], , not_really_there="yes") + AC_TRY_CPP([#include ], , not_really_there="yes") else - if test ! -r $x_includes/X11/Intrinsic.h; then + if test ! -r $x_includes/X11/Xlib.h; then not_really_there="yes" fi fi @@ -2260,11 +2379,11 @@ AC_DEFUN([TEA_PATH_UNIX_X], [ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then AC_MSG_CHECKING([for X11 header files]) found_xincludes="no" - AC_TRY_CPP([#include ], found_xincludes="yes", found_xincludes="no") + AC_TRY_CPP([#include ], found_xincludes="yes", found_xincludes="no") if test "$found_xincludes" = "no"; then dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" for i in $dirs ; do - if test -r $i/X11/Intrinsic.h; then + if test -r $i/X11/Xlib.h; then AC_MSG_RESULT([$i]) XINCLUDES=" -I$i" found_xincludes="yes" @@ -2332,7 +2451,6 @@ AC_DEFUN([TEA_PATH_UNIX_X], [ # HAVE_SYS_FILIO_H # USE_FIONBIO # O_NONBLOCK -# #-------------------------------------------------------------------- AC_DEFUN([TEA_BLOCKING_STYLE], [ @@ -2367,7 +2485,6 @@ AC_DEFUN([TEA_BLOCKING_STYLE], [ # HAVE_TM_GMTOFF # HAVE_TM_TZADJ # HAVE_TIMEZONE_VAR -# #-------------------------------------------------------------------- AC_DEFUN([TEA_TIME_HANDLER], [ @@ -2436,7 +2553,6 @@ AC_DEFUN([TEA_TIME_HANDLER], [ # # Might defines some of the following vars: # strtod (=fixstrtod) -# #-------------------------------------------------------------------- AC_DEFUN([TEA_BUGGY_STRTOD], [ @@ -2487,7 +2603,7 @@ AC_DEFUN([TEA_BUGGY_STRTOD], [ # # Results: # -# Subst's the following var: +# Substitutes the following vars: # TCL_LIBS # MATH_LIBS # @@ -2496,7 +2612,6 @@ AC_DEFUN([TEA_BUGGY_STRTOD], [ # # Might define the following vars: # HAVE_NET_ERRNO_H -# #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ @@ -2574,7 +2689,6 @@ AC_DEFUN([TEA_TCL_LINK_LIBS], [ # _ISOC99_SOURCE # _LARGEFILE64_SOURCE # _LARGEFILE_SOURCE64 -# #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_EARLY_FLAG],[ @@ -2622,7 +2736,6 @@ AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ # HAVE_STRUCT_DIRENT64 # HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T -# #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ @@ -2654,7 +2767,7 @@ AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ # Now check for auxiliary declarations AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_TRY_COMPILE([#include -#include ],[struct dirent64 p;], +#include ],[struct dirent64 p;], tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in ?]) @@ -2739,6 +2852,13 @@ TEA version not specified.]) else AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) fi + + # If the user did not set CFLAGS, set it now to keep macros + # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) @@ -2752,8 +2872,17 @@ TEA version not specified.]) ;; *) CYGPATH=echo - EXEEXT="" - TEA_PLATFORM="unix" + # Maybe we are cross-compiling.... + case ${host_alias} in + *mingw32*) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *) + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac ;; esac @@ -2766,6 +2895,8 @@ TEA version not specified.]) exec_prefix=$prefix fi + AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) + AC_SUBST(EXEEXT) AC_SUBST(CYGPATH) @@ -3001,6 +3132,22 @@ AC_DEFUN([TEA_ADD_CFLAGS], [ AC_SUBST(PKG_CFLAGS) ]) +#------------------------------------------------------------------------ +# TEA_ADD_CLEANFILES -- +# +# Specify one or more CLEANFILES. +# +# Arguments: +# one or more file names to clean target +# +# Results: +# +# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CLEANFILES], [ + CLEANFILES="$CLEANFILES $@" +]) + #------------------------------------------------------------------------ # TEA_PREFIX -- # @@ -3055,16 +3202,17 @@ AC_DEFUN([TEA_SETUP_COMPILER_CC], [ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. - # If the user did not set CFLAGS, set it now to keep - # the AC_PROG_CC macro from adding "-g -O2". - if test "${CFLAGS+set}" != "set" ; then - CFLAGS="" - fi - AC_PROG_CC AC_PROG_CPP - AC_PROG_INSTALL + INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c" + AC_SUBST(INSTALL) + INSTALL_DATA="\${INSTALL} -m 644" + AC_SUBST(INSTALL_DATA) + INSTALL_PROGRAM="\${INSTALL}" + AC_SUBST(INSTALL_PROGRAM) + INSTALL_SCRIPT="\${INSTALL}" + AC_SUBST(INSTALL_SCRIPT) #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. @@ -3076,7 +3224,7 @@ AC_DEFUN([TEA_SETUP_COMPILER_CC], [ # Find ranlib #-------------------------------------------------------------------- - AC_PROG_RANLIB + AC_CHECK_TOOL(RANLIB, ranlib) #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) @@ -3155,13 +3303,26 @@ AC_DEFUN([TEA_SETUP_COMPILER], [ # MAKE_SHARED_LIB Makefile rule for building a shared library # MAKE_STATIC_LIB Makefile rule for building a static library # MAKE_STUB_LIB Makefile rule for building a stub library +# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL +# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE #------------------------------------------------------------------------ AC_DEFUN([TEA_MAKE_LIB], [ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)" - MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)" + AC_EGREP_CPP([manifest needed], [ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + ], [ + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + TEA_ADD_CLEANFILES([*.manifest]) + ]) + MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" @@ -3184,13 +3345,19 @@ AC_DEFUN([TEA_MAKE_LIB], [ if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. - SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test "$GCC" = "yes"; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" + fi eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_LIB_FILE=lib${PKG_LIB_FILE} + fi fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" @@ -3228,6 +3395,8 @@ AC_DEFUN([TEA_MAKE_LIB], [ AC_SUBST(MAKE_STATIC_LIB) AC_SUBST(MAKE_STUB_LIB) AC_SUBST(RANLIB_STUB) + AC_SUBST(VC_MANIFEST_EMBED_DLL) + AC_SUBST(VC_MANIFEST_EMBED_EXE) ]) #------------------------------------------------------------------------ @@ -3316,7 +3485,7 @@ AC_DEFUN([TEA_LIB_SPEC], [ # # Results: # -# Substs the following vars: +# Substitutes the following vars: # TCL_TOP_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ @@ -3394,7 +3563,7 @@ AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ # Adds a --with-tclinclude switch to configure. # Result is cached. # -# Substs the following vars: +# Substitutes the following vars: # TCL_INCLUDES #------------------------------------------------------------------------ @@ -3484,7 +3653,7 @@ AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ # # Results: # -# Substs the following vars: +# Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ @@ -3573,7 +3742,7 @@ AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ # Adds a --with-tkinclude switch to configure. # Result is cached. # -# Substs the following vars: +# Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ @@ -3791,11 +3960,10 @@ AC_DEFUN([TEA_PATH_CONFIG], [ # # Results: # -# Subst the following vars: +# Substitutes the following vars: # $1_SRC_DIR # $1_LIB_FILE # $1_LIB_SPEC -# #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG], [ @@ -3822,6 +3990,8 @@ AC_DEFUN([TEA_LOAD_CONFIG], [ $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} + $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} + $1_LIBRARY_PATH=${$1_LIBRARY_PATH} fi AC_SUBST($1_VERSION) @@ -3854,7 +4024,6 @@ AC_DEFUN([TEA_LOAD_CONFIG], [ # # Results: # Adds to LIBS the appropriate extension library -# #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ AC_MSG_CHECKING([For $1 library for LIBS]) @@ -3886,11 +4055,10 @@ AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ # $1 # # Results: -# Subst the following vars: -# +# Substitutes the following vars: #------------------------------------------------------------------------ -AC_DEFUN(TEA_EXPORT_CONFIG, [ +AC_DEFUN([TEA_EXPORT_CONFIG], [ #-------------------------------------------------------------------- # These are for $1Config.sh #-------------------------------------------------------------------- diff --git a/manifest b/manifest index e344356edb..821fec76d7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplifications\sto\sthe\s"zeroPage()"\sroutine\sin\sbtree.c. -D 2014-02-12T23:52:16.136 +C Update\sthe\stclconfig\sfiles\sto\sthe\slatest\sfrom\shttp://core.tcl.tk/tclconfig. +D 2014-02-13T13:42:43.442 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -30,8 +30,8 @@ F autoconf/tea/configure.in e0466b881b53f31f5a4a69e7a91ad130902fb359 F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523 F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d -F autoconf/tea/tclconfig/install-sh b087e5c4b92820c60bffb74acc1d9c2d40d80b8f -F autoconf/tea/tclconfig/tcl.m4 a68179d7cc45524fa59db428a36610e20bdba808 +F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00 +F autoconf/tea/tclconfig/tcl.m4 f035b86539a5ab30689e997a11ae9e7fd2e65570 F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928 F autoconf/tea/win/nmakehlp.c 2070e086f39866b353a482d3a14dedaf26196506 F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 @@ -1153,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 56bc5ce8958c8e6250531b4052b905d7ac993db3 -R 08bd4c102c2d08f0774c76e162878c69 +P cc8f10bcb206c9def69b06f26decf025b8d9119d +R 5827f3fddcd143de0504e7bdcdecb65f U drh -Z ed630d5c913dd5b0515f56c704c7877e +Z 978280b213079b27efd56c6d39f0432f diff --git a/manifest.uuid b/manifest.uuid index 2af58e32b8..12ee7ec0ac 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cc8f10bcb206c9def69b06f26decf025b8d9119d \ No newline at end of file +b81ba7a4bc7e840fce25fc6801957a64f877ff60 \ No newline at end of file From e5b6ea797ea935d0ae245d8ac29613e9ab7972ea Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 13 Feb 2014 18:46:59 +0000 Subject: [PATCH 05/66] Avoid passing a flags argument with the internal WAL_SYNC_TRANSACTIONS bit set when calling sqlite3OsSync(). FossilOrigin-Name: e3b79e920c298a39613631d689d1a2f182d00496 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 821fec76d7..574e8a65cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\stclconfig\sfiles\sto\sthe\slatest\sfrom\shttp://core.tcl.tk/tclconfig. -D 2014-02-13T13:42:43.442 +C Avoid\spassing\sa\sflags\sargument\swith\sthe\sinternal\sWAL_SYNC_TRANSACTIONS\sbit\sset\swhen\scalling\ssqlite3OsSync(). +D 2014-02-13T18:46:59.101 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd -F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 +F src/wal.c d89e386ead8ecfc823b6162b09e1ada0623df37a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 F src/where.c b0436385f40e86f0f4cc60355cd018bde2c89d4b @@ -1153,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P cc8f10bcb206c9def69b06f26decf025b8d9119d -R 5827f3fddcd143de0504e7bdcdecb65f -U drh -Z 978280b213079b27efd56c6d39f0432f +P b81ba7a4bc7e840fce25fc6801957a64f877ff60 +R a59cd87bb88fdc66ea1a7d77759b0c27 +U dan +Z 4fedb8574b1ff1640e605452066ee2b1 diff --git a/manifest.uuid b/manifest.uuid index 12ee7ec0ac..8a95093ecf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b81ba7a4bc7e840fce25fc6801957a64f877ff60 \ No newline at end of file +e3b79e920c298a39613631d689d1a2f182d00496 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index f413920648..c2c3d369c1 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2677,7 +2677,7 @@ static int walWriteToLog( iAmt -= iFirstAmt; pContent = (void*)(iFirstAmt + (char*)pContent); assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); - rc = sqlite3OsSync(p->pFd, p->syncFlags); + rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); if( iAmt==0 || rc ) return rc; } rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); From 56e3767eb4776be108d0441c010c84787c38026a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 13 Feb 2014 19:10:24 +0000 Subject: [PATCH 06/66] Change README to README.md and expand it. Remove unrelated and obsolete files. FossilOrigin-Name: 18d4e258c45c32984b23d97b896a761eeef2dbdf --- README | 39 ---------- README.md | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++ manifest | 17 ++--- manifest.uuid | 2 +- mkdll.sh | 49 ------------- mkextu.sh | 13 ---- mkextw.sh | 22 ------ 7 files changed, 200 insertions(+), 134 deletions(-) delete mode 100644 README create mode 100644 README.md delete mode 100644 mkdll.sh delete mode 100644 mkextu.sh delete mode 100644 mkextw.sh diff --git a/README b/README deleted file mode 100644 index 0d65e518f9..0000000000 --- a/README +++ /dev/null @@ -1,39 +0,0 @@ -This directory contains source code to - - SQLite: An Embeddable SQL Database Engine - -To compile the project, first create a directory in which to place -the build products. It is recommended, but not required, that the -build directory be separate from the source directory. Cd into the -build directory and then from the build directory run the configure -script found at the root of the source tree. Then run "make". - -For example: - - tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" - mkdir bld ;# Build will occur in a sibling directory - cd bld ;# Change to the build directory - ../sqlite/configure ;# Run the configure script - make ;# Run the makefile. - make install ;# (Optional) Install the build products - -The configure script uses autoconf 2.61 and libtool. If the configure -script does not work out for you, there is a generic makefile named -"Makefile.linux-gcc" in the top directory of the source tree that you -can copy and edit to suit your needs. Comments on the generic makefile -show what changes are needed. - -The linux binaries on the website are created using the generic makefile, -not the configure script. The windows binaries on the website are created -using MinGW32 configured as a cross-compiler running under Linux. For -details, see the ./publish.sh script at the top-level of the source tree. -The developers do not use teh configure script. - -SQLite does not require TCL to run, but a TCL installation is required -by the makefiles. SQLite contains a lot of generated code and TCL is -used to do much of that code generation. The makefile also requires -AWK. - -Contacts: - - http://www.sqlite.org/ diff --git a/README.md b/README.md new file mode 100644 index 0000000000..d8042cee45 --- /dev/null +++ b/README.md @@ -0,0 +1,192 @@ +

SQLite Source Repository

+ +This repository contains the complete source code for the SQLite database +engine. Some test scripts are also include. However, many other test scripts +and most of the documentation are managed separately. + +## Compiling + +First create a directory in which to place +the build products. It is recommended, but not required, that the +build directory be separate from the source directory. Cd into the +build directory and then from the build directory run the configure +script found at the root of the source tree. Then run "make". + +For example: + + tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" + mkdir bld ;# Build will occur in a sibling directory + cd bld ;# Change to the build directory + ../sqlite/configure ;# Run the configure script + make ;# Run the makefile. + make sqlite3.c ;# Build the "amalgamation" source file + make test ;# Run some tests (requires TCL) + +See the makefile for additional targets. + +The configure script uses autoconf 2.61 and libtool. If the configure +script does not work out for you, there is a generic makefile named +"Makefile.linux-gcc" in the top directory of the source tree that you +can copy and edit to suit your needs. Comments on the generic makefile +show what changes are needed. + +SQLite does not require TCL to run, but a TCL installation is required +by the makefiles. SQLite contains a lot of generated code and TCL is +used to do much of that code generation. The makefile also requires +AWK. + +## Source Code Tour + +Most of the core source files are in the **src/** subdirectory. But +src/ also contains files used to build the "testfixture" test harness; +those file all begin with "test". And src/ contains the "shell.c" file +which is the main program for the "sqlite3.exe" command-line shell and +the "tclsqlite.c" file which implements the bindings to SQLite from the +TCL programming language. (Historical note: SQLite began as a TCL +extension and only later escaped to the wild as an independent library.) + +Test scripts and programs are found in the **test/** subdirectory. +There are other test suites for SQLite (see +[How SQLite Is Tested](http://www.sqlite.org/testing.html)) +but those other test suites are +in separate source repositories. + +The **ext/** subdirectory contains code for extensions. The +Full-text search engine is in **ext/fts3**. The R-Tree engine is in +**ext/rtree**. The **ext/misc** subdirectory contains a number of +smaller, single-file extensions, such as a REGEXP operator. + +The **tool/** subdirectory contains various scripts and programs used +for building generated source code files or for testing or for generating +accessory programs such as "sqlite3_analyzer(.exe)". + +### Generated Source Code Files + +Several of the C-language source files used by SQLite are generated from +other sources rather than being typed in manually by a programmer. This +section will summarize those automatically-generated files. To create all +of the automatically-generated files, simply run "make target_source". +The "target_source" make target will create a subdirectory "tsrc/" and +fill it with all the source files needed to build SQLite, both +manually-edited files and automatically-generated files. + +The SQLite interface is defined by the **sqlite3.h** header file, which is +generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The +TCL script at tool/mksqlite3h.tcl does the conversion. The manifest.uuid +file contains the SHA1 hash of the particular check-in and is used to generate +the SQLITE_SOURCE_ID macro. The VERSION file contains the current SQLite +version number. The sqlite3.h header is really just a copy of src/sqlite.h.in +with the source-id and version number inserted at just the right spots. +Note that comment text in the sqlite3.h file is used to generate much of +the SQLite API documentation. The TCL scripts used to generate that +documentation are in a separate source repository. + +The SQL language parser is **parse.c** which is generate from a grammar in +the src/parse.y file. The conversion of "parse.y" into "parse.c" is done +by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code +for lemon is at tool/lemon.c. Lemon uses a +template for generating its parser. A generic template is in tool/lempar.c, +but SQLite uses a slightly modified template found in src/lempar.c. + +Lemon also generates the **parse.h** header file, at the same time it +generates parse.c. But the parse.h header file is +modified further (to add additional symbols) using the ./addopcodes.awk +AWK script. + +The **opcodes.h** header file contains macros that define the numbers +corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h +file is generated by the scanning the src/vdbe.c source file. The +AWK script at ./mkopcodeh.awk does this scan and generates opcodes.h. +A second AWK script, ./mkopcodec.awk, then scans opcodes.h to generate +the **opcodes.c** source file, which contains a reverse mapping from +opcode-number to opcode-name that is used for EXPLAIN output. + +The **keywordhash.h** header file contains the definition of a hash table +that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into +the numeric codes used by the parse.c parser. The keywordhash.h file is +generated by a C-language program at tool mkkeywordhash.c. + +### The Amalgamation + +All of the individual C source code and header files (both manually-edited +and automatically-generated) can be combined into a single big source file +**sqlite3.c** called "the amalgamation". The amalgamation is the recommended +way of using SQLite in a larger application. Combining all individual +source code files into a single big source code file allows the C compiler +to perform more cross-procedure analysis and generate better code. SQLite +runs about 5% faster when compiled from the amalgamation versus when compiled +from individual source files. + +The amalgamation is generated from the tool/mksqlite3c.tcl TCL script. +First, all of the individual source files must be gathered into the tsrc/ +subdirectory (using the equivalent of "make target_source") then the +tool/mksqlite3c.tcl script is run to copy them all together in just the +right order while resolving internal "#include" references. + +The amalgamation source file is more than 100K lines long. Some symbolic +debuggers (most notably MSVC) are unable to deal with files longer than 64K +lines. To work around this, a separate TCL script, tool/split-sqlite3c.tcl, +can be run on the amalgamation to break it up into a single small C file +called **sqlite3-all.c** that does #include on about five other files +named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-5.c**. In this way, +all of the source code is contained within a single translation unit so +that the compiler can do extra cross-procedure optimization, but no +individual source file exceeds 32K lines in length. + +## How It All Fits Together + +SQLite is modular in design. +See the [architectural description](http://www.sqlite.org/arch.html) +for details. Other documents that are useful in +(helping to understand how SQLite works include the +[file format](http://www.sqlite.org/fileformat2.html) description, +the [virtual machine](http://www.sqlite.org/vdbe.html) that runs +prepared statements, the description of +[how transactions work](http://www.sqlite.org/atomiccommit.html), and +the [overview of the query planner](http://www.sqlite.org/optoverview.html). + +Unfortunately, years of effort have gone into optimizating SQLite, both +for small size and high performance. And optimizations tend to result in +complex code. So there is a lot of complexity in the SQLite implementation. + +Key files: + + * **sqlite3.h** - This file defines the public interface to the SQLite + library. Readers will need to be familiar with this interface before + trying to understand how the library works internally. + + * **sqliteInt.h** - this header file defines many of the data objects + used internally by SQLite. + + * **parse.y** - This file describes the LALR(1) grammer that SQLite uses + to parse SQL statements, and the actions that are taken at each stop + in the parsing process. + + * **vdbe.c** - This file implements the virtual machine that runs + prepared statements. There are various helper files whose names + begin with "vdbe". The VDBE has access to the vdbeInt.h header file + which defines internal data objects. The rest of SQLite interacts + with the VDBE through an interface defined by vdbe.h. + + * **where.c** - This file analyzes the WHERE clause and generates + virtual machine code to run queries efficiently. This file is + sometimes called the "query optimizer". It has its own private + header file, whereInt.h, that defines data objects used internally. + + * **btree.c** - This file contains the implementation of the B-Tree + storage engine used by SQLite. + + * **pager.c** - This file contains the "pager" implementation, the + module that implements transactions. + + * **os_unix.c** and **os_win.c** - These two files implement the interface + between SQLite and the underlying operating system using the run-time + pluggable VFS interface. + + +## Contacts + +The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/) +with geographically distributed backup servers at +[http://www2.sqlite.org/](http://www2.sqlite.org) and +[http://www3.sqlite.org/](http://www3.sqlite.org). diff --git a/manifest b/manifest index 574e8a65cb..be8118db4b 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Avoid\spassing\sa\sflags\sargument\swith\sthe\sinternal\sWAL_SYNC_TRANSACTIONS\sbit\sset\swhen\scalling\ssqlite3OsSync(). -D 2014-02-13T18:46:59.101 +C Change\sREADME\sto\sREADME.md\sand\sexpand\sit.\s\sRemove\sunrelated\sand\sobsolete\sfiles. +D 2014-02-13T19:10:24.061 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 -F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 +F README.md 8ff4548af6f7cdf4b02e585d4dd552b233998a9b w README F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 @@ -143,9 +143,6 @@ F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff F main.mk 3ae543fa446525c1dec55f58de67f41b78651812 -F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a -F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f -F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -1153,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b81ba7a4bc7e840fce25fc6801957a64f877ff60 -R a59cd87bb88fdc66ea1a7d77759b0c27 -U dan -Z 4fedb8574b1ff1640e605452066ee2b1 +P e3b79e920c298a39613631d689d1a2f182d00496 +R 32cef02970d5145eabe1c7cffe4376d1 +U drh +Z 910a038630fdb9ee9dcf69294f2c5c44 diff --git a/manifest.uuid b/manifest.uuid index 8a95093ecf..540465f61a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3b79e920c298a39613631d689d1a2f182d00496 \ No newline at end of file +18d4e258c45c32984b23d97b896a761eeef2dbdf \ No newline at end of file diff --git a/mkdll.sh b/mkdll.sh deleted file mode 100644 index 9e368d1d23..0000000000 --- a/mkdll.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# This script is used to compile SQLite into a DLL. -# -# Two separate DLLs are generated. "sqlite3.dll" is the core -# library. "tclsqlite3.dll" contains the TCL bindings and is the -# library that is loaded into TCL in order to run SQLite. -# -make sqlite3.c -PATH=$PATH:/opt/mingw/bin -TCLDIR=/home/drh/tcltk/846/win/846win -TCLSTUBLIB=$TCLDIR/libtcl84stub.a -OPTS='-DUSE_TCL_STUBS=1 -DBUILD_sqlite=1 -DSQLITE_OS_WIN=1' -OPTS="$OPTS -DSQLITE_THREADSAFE=1" -OPTS="$OPTS -DSQLITE_ENABLE_FTS3=1" -OPTS="$OPTS -DSQLITE_ENABLE_RTREE=1" -OPTS="$OPTS -DSQLITE_ENABLE_COLUMN_METADATA=1" -CC="i386-mingw32msvc-gcc -Os $OPTS -Itsrc -I$TCLDIR" -NM="i386-mingw32msvc-nm" -CMD="$CC -c sqlite3.c" -echo $CMD -$CMD -CMD="$CC -c tclsqlite3.c" -echo $CMD -$CMD -echo 'EXPORTS' >tclsqlite3.def -$NM tclsqlite3.o | grep ' T ' >temp1 -grep '_Init$' temp1 >temp2 -grep '_SafeInit$' temp1 >>temp2 -grep ' T _sqlite3_' temp1 >>temp2 -echo 'EXPORTS' >tclsqlite3.def -sed 's/^.* T _//' temp2 | sort | uniq >>tclsqlite3.def -i386-mingw32msvc-dllwrap \ - --def tclsqlite3.def -v --export-all \ - --driver-name i386-mingw32msvc-gcc \ - --dlltool-name i386-mingw32msvc-dlltool \ - --as i386-mingw32msvc-as \ - --target i386-mingw32 \ - -dllname tclsqlite3.dll -lmsvcrt tclsqlite3.o $TCLSTUBLIB -$NM sqlite3.o | grep ' T ' >temp1 -echo 'EXPORTS' >sqlite3.def -grep ' _sqlite3_' temp1 | sed 's/^.* _//' >>sqlite3.def -i386-mingw32msvc-dllwrap \ - --def sqlite3.def -v --export-all \ - --driver-name i386-mingw32msvc-gcc \ - --dlltool-name i386-mingw32msvc-dlltool \ - --as i386-mingw32msvc-as \ - --target i386-mingw32 \ - -dllname sqlite3.dll -lmsvcrt sqlite3.o diff --git a/mkextu.sh b/mkextu.sh deleted file mode 100644 index 1d96897769..0000000000 --- a/mkextu.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# This script is used to compile SQLite into a shared library on Linux. -# -# Two separate shared libraries are generated. "sqlite3.so" is the core -# library. "tclsqlite3.so" contains the TCL bindings and is the -# library that is loaded into TCL in order to run SQLite. -# -CFLAGS=-O2 -Wall -make fts2amal.c -echo gcc $CFLAGS -shared fts2amal.c -o fts2.so -gcc $CFLAGS -shared fts2amal.c -o fts2.so -strip fts2.so diff --git a/mkextw.sh b/mkextw.sh deleted file mode 100644 index 909a126c38..0000000000 --- a/mkextw.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# -# This script is used to compile SQLite extensions into DLLs. -# -make fts2amal.c -PATH=$PATH:/opt/mingw/bin -OPTS='-DTHREADSAFE=1 -DBUILD_sqlite=1 -DSQLITE_OS_WIN=1' -CC="i386-mingw32msvc-gcc -O2 $OPTS -Itsrc" -NM="i386-mingw32msvc-nm" -CMD="$CC -c fts2amal.c" -echo $CMD -$CMD -echo 'EXPORTS' >fts2.def -echo 'sqlite3_fts2_init' >>fts2.def -i386-mingw32msvc-dllwrap \ - --def fts2.def -v --export-all \ - --driver-name i386-mingw32msvc-gcc \ - --dlltool-name i386-mingw32msvc-dlltool \ - --as i386-mingw32msvc-as \ - --target i386-mingw32 \ - -dllname fts2.dll -lmsvcrt fts2amal.o -zip fts2dll.zip fts2.dll fts2.def From dd973548f129b56f45cdf0eb9580a755f369a160 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 13 Feb 2014 19:27:08 +0000 Subject: [PATCH 07/66] Ensure that if the "psow=0" URI option or FCNTL_POWERSAFE_OVERWRITE file-control is used to clear the power-safe overwrite flag, extra padding frames are added to the WAL file. FossilOrigin-Name: 48c821fd97a8f03757c90560c37a46bd0843570e --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/wal.c | 2 +- test/unixexcl.test | 4 ++-- test/zerodamage.test | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index be8118db4b..e5a8a9f156 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Change\sREADME\sto\sREADME.md\sand\sexpand\sit.\s\sRemove\sunrelated\sand\sobsolete\sfiles. -D 2014-02-13T19:10:24.061 +C Ensure\sthat\sif\sthe\s"psow=0"\sURI\soption\sor\sFCNTL_POWERSAFE_OVERWRITE\sfile-control\sis\sused\sto\sclear\sthe\spower-safe\soverwrite\sflag,\sextra\spadding\sframes\sare\sadded\sto\sthe\sWAL\sfile. +D 2014-02-13T19:27:08.812 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 -F README.md 8ff4548af6f7cdf4b02e585d4dd552b233998a9b w README +F README.md 8ff4548af6f7cdf4b02e585d4dd552b233998a9b F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 @@ -287,7 +287,7 @@ F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd -F src/wal.c d89e386ead8ecfc823b6162b09e1ada0623df37a +F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 F src/where.c b0436385f40e86f0f4cc60355cd018bde2c89d4b @@ -1013,7 +1013,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 -F test/unixexcl.test a9870e46cc6f8390a494513d4f2bf55b5a8b3e46 +F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825 F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb F test/uri.test 63e03df051620a18f794b4f4adcdefb3c23b6751 @@ -1100,7 +1100,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107 F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 -F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd +F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/build-all-msvc.bat e0917e787df675b020d250d60a00de8abaa4e30a x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e3b79e920c298a39613631d689d1a2f182d00496 -R 32cef02970d5145eabe1c7cffe4376d1 -U drh -Z 910a038630fdb9ee9dcf69294f2c5c44 +P 18d4e258c45c32984b23d97b896a761eeef2dbdf +R 8c9ce91bde08452c57ff8bd83f7e4683 +U dan +Z a2f4dabb4be0cf1b9a50023d91f3c52c diff --git a/manifest.uuid b/manifest.uuid index 540465f61a..678e82d8ec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -18d4e258c45c32984b23d97b896a761eeef2dbdf \ No newline at end of file +48c821fd97a8f03757c90560c37a46bd0843570e \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index c2c3d369c1..ad76065f50 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1306,7 +1306,7 @@ int sqlite3WalOpen( sqlite3OsClose(pRet->pWalFd); sqlite3_free(pRet); }else{ - int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd); + int iDC = sqlite3OsDeviceCharacteristics(pDbFd); if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ pRet->padToSectorBoundary = 0; diff --git a/test/unixexcl.test b/test/unixexcl.test index 0147e6bbb4..d6762178dd 100644 --- a/test/unixexcl.test +++ b/test/unixexcl.test @@ -109,7 +109,7 @@ do_multiclient_test tn { } {1 2} do_test unixexcl-3.$tn.3 { sql1 { PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(3, 4); } - } {0 3 3} + } {0 5 5} do_test unixexcl-3.$tn.4 { sql2 { SELECT * FROM t1; } } {1 2} @@ -121,7 +121,7 @@ do_multiclient_test tn { } {1 2 3 4} do_test unixexcl-3.$tn.7 { sql1 { PRAGMA wal_checkpoint; } - } {0 4 4} + } {0 7 7} } } diff --git a/test/zerodamage.test b/test/zerodamage.test index de5088b5a2..dccaba816e 100644 --- a/test/zerodamage.test +++ b/test/zerodamage.test @@ -115,7 +115,7 @@ ifcapable wal { UPDATE t1 SET y=randomblob(50) WHERE x=124; } file size test.db-wal - } {8416} + } {16800} } finish_test From 3f40d40ad90d5198c1f97f947892c6ff3059b7c0 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 13 Feb 2014 21:57:48 +0000 Subject: [PATCH 08/66] Improvements to the makefile and README for MSVC. FossilOrigin-Name: b22b61406899c2694dae984995d2484fdb8122f1 --- Makefile.msc | 4 ++-- README.md | 57 ++++++++++++++++++++++++++++++++++++--------------- manifest | 16 +++++++-------- manifest.uuid | 2 +- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 8dce52b5bc..61e5102607 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -214,7 +214,7 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" # will run on the target platform. (BCC and TCC are usually the # same unless your are cross-compiling.) # -TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src -fp:precise +TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src # Check if assembly code listings should be generated for the source @@ -1219,7 +1219,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION - $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP) > sqlite3.h + $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c $(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS) diff --git a/README.md b/README.md index d8042cee45..5e52dea507 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ For example: ../sqlite/configure ;# Run the configure script make ;# Run the makefile. make sqlite3.c ;# Build the "amalgamation" source file - make test ;# Run some tests (requires TCL) + make test ;# Run some tests (requires Tcl) See the makefile for additional targets. @@ -30,10 +30,33 @@ script does not work out for you, there is a generic makefile named can copy and edit to suit your needs. Comments on the generic makefile show what changes are needed. -SQLite does not require TCL to run, but a TCL installation is required -by the makefiles. SQLite contains a lot of generated code and TCL is -used to do much of that code generation. The makefile also requires -AWK. +## Using MSVC + +On Windows, all applicable build products can be compiled with MSVC. +First open the command prompt window associated with the desired compiler +version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE +with the provided "Makefile.msc" to build one of the supported targets. + +For example: + + mkdir bld + cd bld + nmake /f Makefile.msc TOP=..\sqlite + nmake /f Makefile.msc sqlite3.c TOP=..\sqlite + nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite + nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite + nmake /f Makefile.msc test TOP=..\sqlite + +There are several build options that can be set via the NMAKE command +line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument +to the "sqlite3.dll" command line above. When debugging into the SQLite +code, adding the "DEBUG=1" argument to one of the above command lines is +recommended. + +SQLite does not require Tcl to run, but a Tcl installation is required +by the makefiles (including those for MSVC). SQLite contains a lot of +generated code and Tcl is used to do much of that code generation. The +makefiles also require AWK. ## Source Code Tour @@ -42,11 +65,11 @@ src/ also contains files used to build the "testfixture" test harness; those file all begin with "test". And src/ contains the "shell.c" file which is the main program for the "sqlite3.exe" command-line shell and the "tclsqlite.c" file which implements the bindings to SQLite from the -TCL programming language. (Historical note: SQLite began as a TCL +Tcl programming language. (Historical note: SQLite began as a Tcl extension and only later escaped to the wild as an independent library.) Test scripts and programs are found in the **test/** subdirectory. -There are other test suites for SQLite (see +There are other test suites for SQLite (see [How SQLite Is Tested](http://www.sqlite.org/testing.html)) but those other test suites are in separate source repositories. @@ -67,23 +90,23 @@ other sources rather than being typed in manually by a programmer. This section will summarize those automatically-generated files. To create all of the automatically-generated files, simply run "make target_source". The "target_source" make target will create a subdirectory "tsrc/" and -fill it with all the source files needed to build SQLite, both +fill it with all the source files needed to build SQLite, both manually-edited files and automatically-generated files. The SQLite interface is defined by the **sqlite3.h** header file, which is generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The -TCL script at tool/mksqlite3h.tcl does the conversion. The manifest.uuid +Tcl script at tool/mksqlite3h.tcl does the conversion. The manifest.uuid file contains the SHA1 hash of the particular check-in and is used to generate the SQLITE_SOURCE_ID macro. The VERSION file contains the current SQLite version number. The sqlite3.h header is really just a copy of src/sqlite.h.in with the source-id and version number inserted at just the right spots. Note that comment text in the sqlite3.h file is used to generate much of -the SQLite API documentation. The TCL scripts used to generate that +the SQLite API documentation. The Tcl scripts used to generate that documentation are in a separate source repository. The SQL language parser is **parse.c** which is generate from a grammar in the src/parse.y file. The conversion of "parse.y" into "parse.c" is done -by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code +by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code for lemon is at tool/lemon.c. Lemon uses a template for generating its parser. A generic template is in tool/lempar.c, but SQLite uses a slightly modified template found in src/lempar.c. @@ -117,7 +140,7 @@ to perform more cross-procedure analysis and generate better code. SQLite runs about 5% faster when compiled from the amalgamation versus when compiled from individual source files. -The amalgamation is generated from the tool/mksqlite3c.tcl TCL script. +The amalgamation is generated from the tool/mksqlite3c.tcl Tcl script. First, all of the individual source files must be gathered into the tsrc/ subdirectory (using the equivalent of "make target_source") then the tool/mksqlite3c.tcl script is run to copy them all together in just the @@ -125,23 +148,23 @@ right order while resolving internal "#include" references. The amalgamation source file is more than 100K lines long. Some symbolic debuggers (most notably MSVC) are unable to deal with files longer than 64K -lines. To work around this, a separate TCL script, tool/split-sqlite3c.tcl, +lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl, can be run on the amalgamation to break it up into a single small C file called **sqlite3-all.c** that does #include on about five other files named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-5.c**. In this way, all of the source code is contained within a single translation unit so -that the compiler can do extra cross-procedure optimization, but no +that the compiler can do extra cross-procedure optimization, but no individual source file exceeds 32K lines in length. ## How It All Fits Together SQLite is modular in design. -See the [architectural description](http://www.sqlite.org/arch.html) +See the [architectural description](http://www.sqlite.org/arch.html) for details. Other documents that are useful in (helping to understand how SQLite works include the [file format](http://www.sqlite.org/fileformat2.html) description, the [virtual machine](http://www.sqlite.org/vdbe.html) that runs -prepared statements, the description of +prepared statements, the description of [how transactions work](http://www.sqlite.org/atomiccommit.html), and the [overview of the query planner](http://www.sqlite.org/optoverview.html). @@ -182,7 +205,7 @@ Key files: * **os_unix.c** and **os_win.c** - These two files implement the interface between SQLite and the underlying operating system using the run-time pluggable VFS interface. - + ## Contacts diff --git a/manifest b/manifest index e5a8a9f156..a0e6034070 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Ensure\sthat\sif\sthe\s"psow=0"\sURI\soption\sor\sFCNTL_POWERSAFE_OVERWRITE\sfile-control\sis\sused\sto\sclear\sthe\spower-safe\soverwrite\sflag,\sextra\spadding\sframes\sare\sadded\sto\sthe\sWAL\sfile. -D 2014-02-13T19:27:08.812 +C Improvements\sto\sthe\smakefile\sand\sREADME\sfor\sMSVC. +D 2014-02-13T21:57:48.016 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7 +F Makefile.msc 371a17ef9cd011b103cfa1964119a8528f5427c9 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 -F README.md 8ff4548af6f7cdf4b02e585d4dd552b233998a9b +F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8 F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 18d4e258c45c32984b23d97b896a761eeef2dbdf -R 8c9ce91bde08452c57ff8bd83f7e4683 -U dan -Z a2f4dabb4be0cf1b9a50023d91f3c52c +P 48c821fd97a8f03757c90560c37a46bd0843570e +R e8c48a1ab293ac2d556c755a2d22ba69 +U mistachkin +Z fd16507dbadca8019665c7ea56e69ef4 diff --git a/manifest.uuid b/manifest.uuid index 678e82d8ec..267d4e00eb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48c821fd97a8f03757c90560c37a46bd0843570e \ No newline at end of file +b22b61406899c2694dae984995d2484fdb8122f1 \ No newline at end of file From 2953ba9e20f02dad6c41eab2fbaaab4b5aae77e1 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 14 Feb 2014 00:25:03 +0000 Subject: [PATCH 09/66] Revise how the Tcl system encoding is handled by the test suite. FossilOrigin-Name: 9e573198e107f1b85ee37c52a10343d38968bda1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tclsqlite.c | 1 + test/capi3e.test | 6 +++++- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a0e6034070..823607add4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\smakefile\sand\sREADME\sfor\sMSVC. -D 2014-02-13T21:57:48.016 +C Revise\show\sthe\sTcl\ssystem\sencoding\sis\shandled\sby\sthe\stest\ssuite. +D 2014-02-14T00:25:03.606 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -225,7 +225,7 @@ F src/sqliteInt.h 5b1f4e30c8332270e4c14254ef1fbcbd92a4a4c7 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 649d373f2a3cfbefe8e935a8dec83686616f9a85 +F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299 F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35 F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c @@ -365,7 +365,7 @@ F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32 F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0 -F test/capi3e.test ad90088b18b0367125ff2d4b5400153fd2f99aab +F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763 F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 48c821fd97a8f03757c90560c37a46bd0843570e -R e8c48a1ab293ac2d556c755a2d22ba69 +P b22b61406899c2694dae984995d2484fdb8122f1 +R e61eea6addc7b24a1393827be3ebc05a U mistachkin -Z fd16507dbadca8019665c7ea56e69ef4 +Z f753108c2da8e4ac5af912585f7a37ad diff --git a/manifest.uuid b/manifest.uuid index 267d4e00eb..70012cb83b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b22b61406899c2694dae984995d2484fdb8122f1 \ No newline at end of file +9e573198e107f1b85ee37c52a10343d38968bda1 \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 980032cfd6..9b977e54ae 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3778,6 +3778,7 @@ int TCLSH_MAIN(int argc, char **argv){ sqlite3_shutdown(); Tcl_FindExecutable(argv[0]); + Tcl_SetSystemEncoding(NULL, "utf-8"); interp = Tcl_CreateInterp(); #if TCLSH==2 diff --git a/test/capi3e.test b/test/capi3e.test index d7ab8d0bd4..3e478e7904 100644 --- a/test/capi3e.test +++ b/test/capi3e.test @@ -20,7 +20,11 @@ source $testdir/tester.tcl # Make sure the system encoding is utf-8. Otherwise, if the system encoding # is other than utf-8, [file isfile $x] may not refer to the same file # as [sqlite3 db $x]. -encoding system utf-8 +# +# This is no longer needed here because it should be done within the test +# fixture executable itself, via Tcl_SetSystemEncoding. +# +# encoding system utf-8 # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). From 4a1d365903ef55c06c7731fbd5fbb7811f9805ee Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Feb 2014 15:13:36 +0000 Subject: [PATCH 10/66] Add OP_IdxGT and OP_IdxLE as distinct opcodes. Formerly these operations where done using OP_IdxGE and OP_IdxLT with the P5 flag set. But VDBE code is easier to read with distinct opcode names. Also change OP_SeekGe to OP_SeekGE, and so forth, so that the capitalization is consistent. The whole point of this change is to improve the readability of VDBE listings. FossilOrigin-Name: b6bea903ac8e1717ed50b221d73bd0be061c7663 --- manifest | 16 ++++---- manifest.uuid | 2 +- src/vdbe.c | 102 ++++++++++++++++++++++++++++++-------------------- src/where.c | 45 +++++++++++----------- 4 files changed, 94 insertions(+), 71 deletions(-) diff --git a/manifest b/manifest index 823607add4..b85a23bdd5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Revise\show\sthe\sTcl\ssystem\sencoding\sis\shandled\sby\sthe\stest\ssuite. -D 2014-02-14T00:25:03.606 +C Add\sOP_IdxGT\sand\sOP_IdxLE\sas\sdistinct\sopcodes.\s\sFormerly\sthese\soperations\swhere\ndone\susing\sOP_IdxGE\sand\sOP_IdxLT\swith\sthe\sP5\sflag\sset.\s\sBut\sVDBE\scode\sis\seasier\nto\sread\swith\sdistinct\sopcode\snames.\s\sAlso\schange\sOP_SeekGe\sto\sOP_SeekGE,\sand\nso\sforth,\sso\sthat\sthe\scapitalization\sis\sconsistent.\s\sThe\swhole\spoint\sof\sthis\nchange\sis\sto\simprove\sthe\sreadability\sof\sVDBE\slistings. +D 2014-02-14T15:13:36.850 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,7 +277,7 @@ F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 3f0872b12ec3fc24ee540f8bb09de181ddad6d8d +F src/vdbe.c 543ed4ed0c41b34affad239374d4c07e6e5b2401 F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c b0436385f40e86f0f4cc60355cd018bde2c89d4b +F src/where.c 43eb827f10d90972578eb0759d01bf0094fcb8c7 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b22b61406899c2694dae984995d2484fdb8122f1 -R e61eea6addc7b24a1393827be3ebc05a -U mistachkin -Z f753108c2da8e4ac5af912585f7a37ad +P 9e573198e107f1b85ee37c52a10343d38968bda1 +R 761a583803ea417c3e82fa617fd0a139 +U drh +Z 39171055bea51b7fba314c7bdb8e0ff5 diff --git a/manifest.uuid b/manifest.uuid index 70012cb83b..7c4fe4fd3a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e573198e107f1b85ee37c52a10343d38968bda1 \ No newline at end of file +b6bea903ac8e1717ed50b221d73bd0be061c7663 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 00cff1e21e..610376dd20 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3425,10 +3425,10 @@ case OP_Close: { ** ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt */ -case OP_SeekLt: /* jump, in3 */ -case OP_SeekLe: /* jump, in3 */ -case OP_SeekGe: /* jump, in3 */ -case OP_SeekGt: { /* jump, in3 */ +case OP_SeekLT: /* jump, in3 */ +case OP_SeekLE: /* jump, in3 */ +case OP_SeekGE: /* jump, in3 */ +case OP_SeekGT: { /* jump, in3 */ int res; int oc; VdbeCursor *pC; @@ -3441,9 +3441,9 @@ case OP_SeekGt: { /* jump, in3 */ pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pseudoTableReg==0 ); - assert( OP_SeekLe == OP_SeekLt+1 ); - assert( OP_SeekGe == OP_SeekLt+2 ); - assert( OP_SeekGt == OP_SeekLt+3 ); + assert( OP_SeekLE == OP_SeekLT+1 ); + assert( OP_SeekGE == OP_SeekLT+2 ); + assert( OP_SeekGT == OP_SeekLT+3 ); assert( pC->isOrdered ); assert( pC->pCursor!=0 ); oc = pOp->opcode; @@ -3475,19 +3475,19 @@ case OP_SeekGt: { /* jump, in3 */ ** (x <= 4.9) -> (x < 5) */ if( pIn3->r<(double)iKey ){ - assert( OP_SeekGe==(OP_SeekGt-1) ); - assert( OP_SeekLt==(OP_SeekLe-1) ); - assert( (OP_SeekLe & 0x0001)==(OP_SeekGt & 0x0001) ); - if( (oc & 0x0001)==(OP_SeekGt & 0x0001) ) oc--; + assert( OP_SeekGE==(OP_SeekGT-1) ); + assert( OP_SeekLT==(OP_SeekLE-1) ); + assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; } /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ else if( pIn3->r>(double)iKey ){ - assert( OP_SeekLe==(OP_SeekLt+1) ); - assert( OP_SeekGt==(OP_SeekGe+1) ); - assert( (OP_SeekLt & 0x0001)==(OP_SeekGe & 0x0001) ); - if( (oc & 0x0001)==(OP_SeekLt & 0x0001) ) oc++; + assert( OP_SeekLE==(OP_SeekLT+1) ); + assert( OP_SeekGT==(OP_SeekGE+1) ); + assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); + if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } } rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res); @@ -3506,17 +3506,17 @@ case OP_SeekGt: { /* jump, in3 */ r.nField = (u16)nField; /* The next line of code computes as follows, only faster: - ** if( oc==OP_SeekGt || oc==OP_SeekLe ){ + ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ ** r.flags = UNPACKED_INCRKEY; ** }else{ ** r.flags = 0; ** } */ - r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLt))); - assert( oc!=OP_SeekGt || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekLe || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekGe || r.flags==0 ); - assert( oc!=OP_SeekLt || r.flags==0 ); + r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT))); + assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY ); + assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY ); + assert( oc!=OP_SeekGE || r.flags==0 ); + assert( oc!=OP_SeekLT || r.flags==0 ); r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG @@ -3534,8 +3534,8 @@ case OP_SeekGt: { /* jump, in3 */ #ifdef SQLITE_TEST sqlite3_search_count++; #endif - if( oc>=OP_SeekGe ){ assert( oc==OP_SeekGe || oc==OP_SeekGt ); - if( res<0 || (res==0 && oc==OP_SeekGt) ){ + if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); + if( res<0 || (res==0 && oc==OP_SeekGT) ){ res = 0; rc = sqlite3BtreeNext(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; @@ -3544,8 +3544,8 @@ case OP_SeekGt: { /* jump, in3 */ res = 0; } }else{ - assert( oc==OP_SeekLt || oc==OP_SeekLe ); - if( res>0 || (res==0 && oc==OP_SeekLt) ){ + assert( oc==OP_SeekLT || oc==OP_SeekLE ); + if( res>0 || (res==0 && oc==OP_SeekLT) ){ res = 0; rc = sqlite3BtreePrevious(pC->pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; @@ -4620,32 +4620,50 @@ case OP_IdxRowid: { /* out2-prerelease */ ** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. ** ** If the P1 index entry is greater than or equal to the key value ** then jump to P2. Otherwise fall through to the next instruction. +*/ +/* Opcode: IdxGT P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] ** -** If P5 is non-zero then the key value is increased by an epsilon -** prior to the comparison. This make the opcode work like IdxGT except -** that if the key from register P3 is a prefix of the key in the cursor, -** the result is false whereas it would be true with IdxGT. +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY. Compare this key value against the index +** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID +** fields at the end. +** +** If the P1 index entry is greater than the key value +** then jump to P2. Otherwise fall through to the next instruction. */ /* Opcode: IdxLT P1 P2 P3 P4 P5 ** Synopsis: key=r[P3@P4] ** ** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. ** ** If the P1 index entry is less than the key value then jump to P2. ** Otherwise fall through to the next instruction. -** -** If P5 is non-zero then the key value is increased by an epsilon prior -** to the comparison. This makes the opcode work like IdxLE. */ +/* Opcode: IdxLE P1 P2 P3 P4 P5 +** Synopsis: key=r[P3@P4] +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the PRIMARY KEY or ROWID. Compare this key value against +** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or +** ROWID on the P1 index. +** +** If the P1 index entry is less than or equal to the key value then jump +** to P2. Otherwise fall through to the next instruction. +*/ +case OP_IdxLE: /* jump */ +case OP_IdxGT: /* jump */ case OP_IdxLT: /* jump */ -case OP_IdxGE: { /* jump */ +case OP_IdxGE: { /* jump */ VdbeCursor *pC; int res; UnpackedRecord r; @@ -4660,9 +4678,11 @@ case OP_IdxGE: { /* jump */ assert( pOp->p4type==P4_INT32 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; - if( pOp->p5 ){ + if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; }else{ + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); r.flags = UNPACKED_PREFIX_MATCH; } r.aMem = &aMem[pOp->p3]; @@ -4671,10 +4691,12 @@ case OP_IdxGE: { /* jump */ #endif res = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res); - if( pOp->opcode==OP_IdxLT ){ + assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) ); + if( (pOp->opcode&1)==(OP_IdxLT&1) ){ + assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT ); res = -res; }else{ - assert( pOp->opcode==OP_IdxGE ); + assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); res++; } if( res>0 ){ diff --git a/src/where.c b/src/where.c index d0d95c081d..94e939e27f 100644 --- a/src/where.c +++ b/src/where.c @@ -2505,7 +2505,7 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); - pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLt:OP_SeekGt), + pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), iIdxCur, 0, regBase, nSkip); sqlite3VdbeJumpHere(v, j); for(j=0; ju.btree.nEq; /* Number of == or IN terms */ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ @@ -3093,10 +3094,10 @@ static Bitmask codeOneLoopStart( assert( op!=0 ); testcase( op==OP_Rewind ); testcase( op==OP_Last ); - testcase( op==OP_SeekGt ); - testcase( op==OP_SeekGe ); - testcase( op==OP_SeekLe ); - testcase( op==OP_SeekLt ); + testcase( op==OP_SeekGT ); + testcase( op==OP_SeekGE ); + testcase( op==OP_SeekLE ); + testcase( op==OP_SeekLT ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); /* Load the value for the inequality constraint at the end of the @@ -3124,13 +3125,13 @@ static Bitmask codeOneLoopStart( pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ - op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)]; - testcase( op==OP_Noop ); - testcase( op==OP_IdxGE ); - testcase( op==OP_IdxLT ); - if( op!=OP_Noop ){ + if( pRangeEnd || nEq ){ + op = aEndOp[bRev*2 + endEq]; + testcase( op==OP_IdxGT ); + testcase( op==OP_IdxGE ); + testcase( op==OP_IdxLT ); + testcase( op==OP_IdxLE ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0); } /* If there are inequality constraints, check that the value From f78da0e6afdadd579247630c21a80dda3c906ebd Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Feb 2014 20:59:53 +0000 Subject: [PATCH 11/66] Reduce the number of cases where it is necessary to check for NULL after the loop terminating condition. FossilOrigin-Name: 3c1ae447dec8fc2af1c5105134061717594ac0e0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 12 +++++------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index b85a23bdd5..d8dd849567 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sOP_IdxGT\sand\sOP_IdxLE\sas\sdistinct\sopcodes.\s\sFormerly\sthese\soperations\swhere\ndone\susing\sOP_IdxGE\sand\sOP_IdxLT\swith\sthe\sP5\sflag\sset.\s\sBut\sVDBE\scode\sis\seasier\nto\sread\swith\sdistinct\sopcode\snames.\s\sAlso\schange\sOP_SeekGe\sto\sOP_SeekGE,\sand\nso\sforth,\sso\sthat\sthe\scapitalization\sis\sconsistent.\s\sThe\swhole\spoint\sof\sthis\nchange\sis\sto\simprove\sthe\sreadability\sof\sVDBE\slistings. -D 2014-02-14T15:13:36.850 +C Reduce\sthe\snumber\sof\scases\swhere\sit\sis\snecessary\sto\scheck\sfor\sNULL\safter\nthe\sloop\sterminating\scondition. +D 2014-02-14T20:59:53.587 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 43eb827f10d90972578eb0759d01bf0094fcb8c7 +F src/where.c bf849f08ee09f15e507b5d5f4bc5b608761d5fe2 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9e573198e107f1b85ee37c52a10343d38968bda1 -R 761a583803ea417c3e82fa617fd0a139 +P b6bea903ac8e1717ed50b221d73bd0be061c7663 +R f976ccc3e6f99e20be380cc680402b19 U drh -Z 39171055bea51b7fba314c7bdb8e0ff5 +Z d8a7427791a9ddd9c5e417477ea3c5a6 diff --git a/manifest.uuid b/manifest.uuid index 7c4fe4fd3a..3ff1fc2f3d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6bea903ac8e1717ed50b221d73bd0be061c7663 \ No newline at end of file +3c1ae447dec8fc2af1c5105134061717594ac0e0 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 94e939e27f..96ee0e931e 100644 --- a/src/where.c +++ b/src/where.c @@ -3134,17 +3134,15 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); } - /* If there are inequality constraints, check that the value - ** of the table column that the inequality contrains is not NULL. - ** If it is, jump to the next iteration of the loop. + /* If there are inequality constraint upper bound but not a lower + ** bound, then check that the value of the table column that the + ** inequality contrains is not NULL since there is alway an implied + ** lower bound of "column>NULL". */ r1 = sqlite3GetTempReg(pParse); - testcase( pLoop->wsFlags & WHERE_BTM_LIMIT ); - testcase( pLoop->wsFlags & WHERE_TOP_LIMIT ); - if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 + if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==WHERE_TOP_LIMIT && (j = pIdx->aiColumn[nEq])>=0 && pIdx->pTable->aCol[j].notNull==0 - && (nEq || (pLoop->wsFlags & WHERE_BTM_LIMIT)==0) ){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName)); From cfc6ca41797342ea1d572c982a416024528b7ccd Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Feb 2014 23:49:13 +0000 Subject: [PATCH 12/66] Seek past NULLs in a top-constrained search. Avoid checking for NULLs in the body of the search. FossilOrigin-Name: e07a32f30862acf3b322d4d8deb015846d6f8f5f --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/where.c | 40 ++++++++++++++++++---------------------- test/where.test | 4 ++-- test/where4.test | 4 ++-- test/where8.test | 4 ++-- 6 files changed, 34 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index d8dd849567..8aef1ebcfc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reduce\sthe\snumber\sof\scases\swhere\sit\sis\snecessary\sto\scheck\sfor\sNULL\safter\nthe\sloop\sterminating\scondition. -D 2014-02-14T20:59:53.587 +C Seek\spast\sNULLs\sin\sa\stop-constrained\ssearch.\s\sAvoid\schecking\sfor\sNULLs\sin\nthe\sbody\sof\sthe\ssearch. +D 2014-02-14T23:49:13.552 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c bf849f08ee09f15e507b5d5f4bc5b608761d5fe2 +F src/where.c 7d9c988741c7d0e4a57774ae4b56e59675c4014a F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1068,14 +1068,14 @@ F test/walro.test 6cc247a0cc9b36aeea2057dd28a922a1cdfbd630 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e -F test/where.test 701a633ed16c661cd597b9d504b485197a0f49d7 +F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b F test/where2.test ed6baa9420a109d8be683dbef5d153d186f3690b F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e -F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2 +F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8 -F test/where8.test 84033c4da466d90fe7ef0152661ff67fd218105f +F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1 F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739 F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b @@ -1150,7 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b6bea903ac8e1717ed50b221d73bd0be061c7663 -R f976ccc3e6f99e20be380cc680402b19 +P 3c1ae447dec8fc2af1c5105134061717594ac0e0 +R 20e62eafcdc3ac9a7a16fa36432e6177 U drh -Z d8a7427791a9ddd9c5e417477ea3c5a6 +Z f35a13e794e2689c6821aa3d892fcd6f diff --git a/manifest.uuid b/manifest.uuid index 3ff1fc2f3d..ed5e06552e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c1ae447dec8fc2af1c5105134061717594ac0e0 \ No newline at end of file +e07a32f30862acf3b322d4d8deb015846d6f8f5f \ No newline at end of file diff --git a/src/where.c b/src/where.c index 96ee0e931e..c5bbeea0e1 100644 --- a/src/where.c +++ b/src/where.c @@ -2985,9 +2985,7 @@ static Bitmask codeOneLoopStart( OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */ }; u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ - int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ int regBase; /* Base register holding constraint values */ - int r1; /* Temp register */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ int startEq; /* True if range start uses ==, >= or <= */ @@ -3000,6 +2998,8 @@ static Bitmask codeOneLoopStart( int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char cEndAff = 0; /* Affinity for end of range constraint */ + u8 bSeekPastNull = 0; /* True to seek past initial nulls */ + u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; @@ -3018,7 +3018,7 @@ static Bitmask codeOneLoopStart( && (pIdx->nKeyCol>nEq) ){ assert( pLoop->u.btree.nSkip==0 ); - isMinQuery = 1; + bSeekPastNull = 1; nExtraReg = 1; } @@ -3033,6 +3033,13 @@ static Bitmask codeOneLoopStart( if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; + if( pRangeStart==0 + && (pRangeEnd->wtFlags & TERM_VNULL)==0 + && (j = pIdx->aiColumn[nEq])>=0 + && pIdx->pTable->aCol[j].notNull==0 + ){ + bSeekPastNull = 1; + } } /* Generate code to evaluate all constraint terms using == or IN @@ -3052,6 +3059,7 @@ static Bitmask codeOneLoopStart( || (bRev && pIdx->nKeyCol==nEq) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); + SWAP(u8, bSeekPastNull, bStopAtNull); } testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); @@ -3083,13 +3091,13 @@ static Bitmask codeOneLoopStart( } nConstraint++; testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); - }else if( isMinQuery ){ + }else if( bSeekPastNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); nConstraint++; startEq = 0; start_constraints = 1; } - codeApplyAffinity(pParse, regBase, nConstraint, zStartAff); + codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); testcase( op==OP_Rewind ); @@ -3118,6 +3126,10 @@ static Bitmask codeOneLoopStart( } nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); + }else if( bStopAtNull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + endEq = 0; + nConstraint++; } sqlite3DbFree(db, zStartAff); @@ -3125,7 +3137,7 @@ static Bitmask codeOneLoopStart( pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ - if( pRangeEnd || nEq ){ + if( nConstraint ){ op = aEndOp[bRev*2 + endEq]; testcase( op==OP_IdxGT ); testcase( op==OP_IdxGE ); @@ -3134,22 +3146,6 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); } - /* If there are inequality constraint upper bound but not a lower - ** bound, then check that the value of the table column that the - ** inequality contrains is not NULL since there is alway an implied - ** lower bound of "column>NULL". - */ - r1 = sqlite3GetTempReg(pParse); - if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==WHERE_TOP_LIMIT - && (j = pIdx->aiColumn[nEq])>=0 - && pIdx->pTable->aCol[j].notNull==0 - ){ - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); - VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName)); - sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont); - } - sqlite3ReleaseTempReg(pParse, r1); - /* Seek the table cursor, if required */ disableTerm(pLevel, pRangeStart); disableTerm(pLevel, pRangeEnd); diff --git a/test/where.test b/test/where.test index a50fe7ebcf..f560708cca 100644 --- a/test/where.test +++ b/test/where.test @@ -237,10 +237,10 @@ do_test where-1.34 { } {97 99} do_test where-1.35 { count {SELECT w FROM t1 WHERE w<3} -} {1 2 2} +} {1 2 3} do_test where-1.36 { count {SELECT w FROM t1 WHERE w<=3} -} {1 2 3 3} +} {1 2 3 4} do_test where-1.37 { count {SELECT w FROM t1 WHERE w+1<=4 ORDER BY w} } {1 2 3 99} diff --git a/test/where4.test b/test/where4.test index 280eb5ff7f..a26e9ad355 100644 --- a/test/where4.test +++ b/test/where4.test @@ -71,7 +71,7 @@ do_test where4-1.5 { } {1 2} do_test where4-1.6 { count {SELECT rowid FROM t1 WHERE w=1 AND x<9} -} {1 3} +} {1 2} do_test where4-1.7 { count {SELECT rowid FROM t1 WHERE w=1 AND x IS NULL AND y=3} } {2 2} @@ -98,7 +98,7 @@ do_test where4-1.14 { } {7 2} do_test where4-1.15 { count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y<0} -} {2} +} {1} do_test where4-1.16 { count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y>=0} } {1} diff --git a/test/where8.test b/test/where8.test index 287e4004c8..139251aa07 100644 --- a/test/where8.test +++ b/test/where8.test @@ -87,13 +87,13 @@ do_test where8-1.8 { do_test where8-1.9 { execsql_status2 { SELECT c FROM t1 WHERE a >= 9 OR b <= 'eight' } -} {IX X VIII 0 0 6} +} {IX X VIII 0 0 7} do_test where8-1.10 { execsql_status2 { SELECT c FROM t1 WHERE (a >= 9 AND c != 'X') OR b <= 'eight' } -} {IX VIII 0 0 6} +} {IX VIII 0 0 7} do_test where8-1.11 { execsql_status2 { From 05a86c5c0f0467098c4f6a333bf6daa1fbe443c1 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Feb 2014 01:55:49 +0000 Subject: [PATCH 13/66] Enhance the code generator for INSERT INTO ... SELECT so that the SELECT generates output directly in the registers that INSERT INTO will be using, in many cases, and OP_SCopy operations can thus be avoided. FossilOrigin-Name: aa2d8b0e8154dd2f5e2c837dc11ab362b083495b --- manifest | 27 +++--- manifest.uuid | 2 +- src/expr.c | 42 +++++---- src/insert.c | 232 +++++++++++++++++----------------------------- src/select.c | 12 ++- src/sqliteInt.h | 6 +- src/vdbe.c | 39 +++++--- test/insert.test | 2 +- test/insert4.test | 2 +- 9 files changed, 165 insertions(+), 199 deletions(-) diff --git a/manifest b/manifest index 8aef1ebcfc..392084a893 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Seek\spast\sNULLs\sin\sa\stop-constrained\ssearch.\s\sAvoid\schecking\sfor\sNULLs\sin\nthe\sbody\sof\sthe\ssearch. -D 2014-02-14T23:49:13.552 +C Enhance\sthe\scode\sgenerator\sfor\sINSERT\sINTO\s...\sSELECT\sso\sthat\sthe\sSELECT\ngenerates\soutput\sdirectly\sin\sthe\sregisters\sthat\sINSERT\sINTO\swill\sbe\susing,\nin\smany\scases,\sand\sOP_SCopy\soperations\scan\sthus\sbe\savoided. +D 2014-02-16T01:55:49.753 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3 -F src/expr.c 9bea427f95665c1aa8fdc87b7678546eef50c296 +F src/expr.c 90bba0ca6ec97d6857458f08a8ad2820130e13cf F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 @@ -180,7 +180,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 89526b031cf8f0e2306f02099a73cee56110c580 +F src/insert.c 36e61dd2201c34a11886487e7afb86f3451ffc52 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -216,12 +216,12 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 50961f0d0ab8f2d45ff29ec5f91d8db221330ca7 +F src/select.c ebec4d3fad7fd5aa33cd69e2f50e9c109285dc73 F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 5b1f4e30c8332270e4c14254ef1fbcbd92a4a4c7 +F src/sqliteInt.h 82aa6a9b068b5a827e85af0b7fa12661f5874459 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -277,7 +277,7 @@ F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 543ed4ed0c41b34affad239374d4c07e6e5b2401 +F src/vdbe.c 7b74ce685d05c1123b0360ce6bc377df114b8533 F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -613,10 +613,10 @@ F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 -F test/insert.test 489aa12a027c83d291f5034a83c8c32e6be1dca2 +F test/insert.test c120294273b18cf9c8b1a3158131f7a825bdba41 F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30 -F test/insert4.test b00ddf82d6d4f0a6f3999f42bb6a3c813ea70707 +F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3 F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2 F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4 @@ -1150,7 +1150,10 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3c1ae447dec8fc2af1c5105134061717594ac0e0 -R 20e62eafcdc3ac9a7a16fa36432e6177 +P e07a32f30862acf3b322d4d8deb015846d6f8f5f +R 4c464651f87f73c0925f058052453922 +T *branch * insert-optimization +T *sym-insert-optimization * +T -sym-trunk * U drh -Z f35a13e794e2689c6821aa3d892fcd6f +Z fb4eb5dbe58efaaeaac33be3bebd9bdd diff --git a/manifest.uuid b/manifest.uuid index ed5e06552e..bab4067e49 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e07a32f30862acf3b322d4d8deb015846d6f8f5f \ No newline at end of file +aa2d8b0e8154dd2f5e2c837dc11ab362b083495b \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 0f07181019..79b50fbb33 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3112,7 +3112,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ ** results in register target. The results are guaranteed to appear ** in register target. */ -int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ +void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ int inReg; assert( target>0 && target<=pParse->nMem ); @@ -3125,7 +3125,20 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); } } - return target; +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. If the expression is constant, then this routine +** might choose to code the expression at initialization time. +*/ +void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ + if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target, 0); + }else{ + sqlite3ExprCode(pParse, pExpr, target); + } } /* @@ -3140,25 +3153,16 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ ** times. They are evaluated once and the results of the expression ** are reused. */ -int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ +void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; - int inReg; - inReg = sqlite3ExprCode(pParse, pExpr, target); + int iMem; + assert( target>0 ); - /* The only place, other than this routine, where expressions can be - ** converted to TK_REGISTER is internal subexpressions in BETWEEN and - ** CASE operators. Neither ever calls this routine. And this routine - ** is never called twice on the same expression. Hence it is impossible - ** for the input to this routine to already be a register. Nevertheless, - ** it seems prudent to keep the ALWAYS() in case the conditions above - ** change with future modifications or enhancements. */ - if( ALWAYS(pExpr->op!=TK_REGISTER) ){ - int iMem; - iMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); - exprToRegister(pExpr, iMem); - } - return inReg; + assert( pExpr->op!=TK_REGISTER ); + sqlite3ExprCode(pParse, pExpr, target); + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, target, iMem); + exprToRegister(pExpr, iMem); } #if defined(SQLITE_ENABLE_TREE_EXPLAIN) diff --git a/src/insert.c b/src/insert.c index bd15832ac6..a9e6bd2866 100644 --- a/src/insert.c +++ b/src/insert.c @@ -148,7 +148,7 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ ** a statement of the form "INSERT INTO SELECT ..." can ** run without using temporary table for the results of the SELECT. */ -static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ +static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); int i; int iEnd = sqlite3VdbeCurrentAddr(v); @@ -156,7 +156,7 @@ static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; #endif - for(i=iStartAddr; iopcode==OP_OpenRead && pOp->p3==iDb ){ @@ -335,79 +335,6 @@ void sqlite3AutoincrementEnd(Parse *pParse){ #endif /* SQLITE_OMIT_AUTOINCREMENT */ -/* -** Generate code for a co-routine that will evaluate a subquery one -** row at a time. -** -** The pSelect parameter is the subquery that the co-routine will evaluation. -** Information about the location of co-routine and the registers it will use -** is returned by filling in the pDest object. -** -** Registers are allocated as follows: -** -** pDest->iSDParm The register holding the next entry-point of the -** co-routine. Run the co-routine to its next breakpoint -** by calling "OP_Yield $X" where $X is pDest->iSDParm. -** -** pDest->iSdst First result register. -** -** pDest->nSdst Number of result registers. -** -** At EOF the first result register will be marked as "undefined" so that -** the caller can know when to stop reading results. -** -** This routine handles all of the register allocation and fills in the -** pDest structure appropriately. -** -** Here is a schematic of the generated code assuming that X is the -** co-routine entry-point register reg[pDest->iSDParm], that EOF is the -** completed flag reg[pDest->iSDParm+1], and R and S are the range of -** registers that hold the result set, reg[pDest->iSdst] through -** reg[pDest->iSdst+pDest->nSdst-1]: -** -** X <- A -** goto B -** A: setup for the SELECT -** loop rows in the SELECT -** load results into registers R..S -** yield X -** end loop -** cleanup after the SELECT -** end co-routine R -** B: -** -** To use this subroutine, the caller generates code as follows: -** -** [ Co-routine generated by this subroutine, shown above ] -** S: yield X, at EOF goto E -** if skip this row, goto C -** if terminate loop, goto E -** deal with this row -** C: goto S -** E: -*/ -int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){ - int regYield; /* Register holding co-routine entry-point */ - int addrTop; /* Top of the co-routine */ - int rc; /* Result code */ - Vdbe *v; /* VDBE under construction */ - - regYield = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - addrTop = sqlite3VdbeCurrentAddr(v) + 1; - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); - sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield); - rc = sqlite3Select(pParse, pSelect, pDest); - assert( pParse->nErr==0 || rc ); - if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM; - if( rc ) return rc; - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); - sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ - return rc; -} - - - /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ @@ -531,16 +458,16 @@ void sqlite3Insert( int iIdxCur = 0; /* First index cursor */ int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ int endOfLoop; /* Label for the end of the insertion loop */ - int useTempTable = 0; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ int addrInsTop = 0; /* Jump to label "D" */ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ - int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ - int appendFlag = 0; /* True if the insert is likely to be an append */ - int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ + u8 useTempTable = 0; /* Store SELECT results in intermediate table */ + u8 appendFlag = 0; /* True if the insert is likely to be an append */ + u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ + u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ @@ -652,6 +579,56 @@ void sqlite3Insert( */ regAutoinc = autoIncBegin(pParse, iDb, pTab); + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assemblied row record. + */ + regRowid = regIns = pParse->nMem+1; + pParse->nMem += pTab->nCol + 1; + if( IsVirtual(pTab) ){ + regRowid++; + pParse->nMem++; + } + regData = regRowid+1; + + /* If the INSERT statement included an IDLIST term, then make sure + ** all elements of the IDLIST really are columns of the table and + ** remember the column indices. + ** + ** If the table has an INTEGER PRIMARY KEY column and that column + ** is named in the IDLIST, then record in the ipkColumn variable + ** the index into IDLIST of the primary key column. ipkColumn is + ** the index of the primary key as it appears in IDLIST, not as + ** is appears in the original table. (The index of the INTEGER + ** PRIMARY KEY in the original table is pTab->iPKey.) + */ + if( pColumn ){ + for(i=0; inId; i++){ + pColumn->a[i].idx = -1; + } + for(i=0; inId; i++){ + for(j=0; jnCol; j++){ + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; + if( i!=j ) bIdListInOrder = 0; + if( j==pTab->iPKey ){ + ipkColumn = i; assert( !withoutRowid ); + } + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ + ipkColumn = i; + }else{ + sqlite3ErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); + pParse->checkSchema = 1; + goto insert_cleanup; + } + } + } + } + /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The @@ -659,13 +636,24 @@ void sqlite3Insert( */ if( pSelect ){ /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ - int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest); - if( rc ) goto insert_cleanup; + int regYield; /* Register holding co-routine entry-point */ + int addrTop; /* Top of the co-routine */ + int rc; /* Result code */ + regYield = ++pParse->nMem; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); + dest.iSdst = bIdListInOrder ? regData : 0; + dest.nSdst = pTab->nCol; + rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; + assert( pParse->nErr==0 || rc ); + if( rc || db->mallocFailed ) goto insert_cleanup; + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); + sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; - assert( dest.nSdst==nColumn ); /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to @@ -676,7 +664,7 @@ void sqlite3Insert( ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){ + if( pTrigger || readsTable(pParse, iDb, pTab) ){ useTempTable = 1; } @@ -725,6 +713,14 @@ void sqlite3Insert( } } + /* If there is no IDLIST term but the table has an integer primary + ** key, the set the ipkColumn variable to the integer primary key + ** column index in the original table definition. + */ + if( pColumn==0 && nColumn>0 ){ + ipkColumn = pTab->iPKey; + } + /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. */ @@ -743,52 +739,6 @@ void sqlite3Insert( sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } - - /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and - ** remember the column indices. - ** - ** If the table has an INTEGER PRIMARY KEY column and that column - ** is named in the IDLIST, then record in the ipkColumn variable - ** the index into IDLIST of the primary key column. ipkColumn is - ** the index of the primary key as it appears in IDLIST, not as - ** is appears in the original table. (The index of the INTEGER - ** PRIMARY KEY in the original table is pTab->iPKey.) - */ - if( pColumn ){ - for(i=0; inId; i++){ - pColumn->a[i].idx = -1; - } - for(i=0; inId; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ - pColumn->a[i].idx = j; - if( j==pTab->iPKey ){ - ipkColumn = i; assert( !withoutRowid ); - } - break; - } - } - if( j>=pTab->nCol ){ - if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ - ipkColumn = i; - }else{ - sqlite3ErrorMsg(pParse, "table %S has no column named %s", - pTabList, 0, pColumn->a[i].zName); - pParse->checkSchema = 1; - goto insert_cleanup; - } - } - } - } - - /* If there is no IDLIST term but the table has an integer primary - ** key, the set the ipkColumn variable to the integer primary key - ** column index in the original table definition. - */ - if( pColumn==0 && nColumn>0 ){ - ipkColumn = pTab->iPKey; - } /* Initialize the count of rows to be inserted */ @@ -836,17 +786,6 @@ void sqlite3Insert( addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); } - /* Allocate registers for holding the rowid of the new row, - ** the content of the new row, and the assemblied row record. - */ - regRowid = regIns = pParse->nMem+1; - pParse->nMem += pTab->nCol + 1; - if( IsVirtual(pTab) ){ - regRowid++; - pParse->nMem++; - } - regData = regRowid+1; - /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); @@ -930,7 +869,7 @@ void sqlite3Insert( if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+ipkColumn, regRowid); + sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); @@ -976,8 +915,9 @@ void sqlite3Insert( /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the rowid will be substituted ** in its place. Hence, fill this column with a NULL to avoid - ** taking up data space with information that will never be used. */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); + ** taking up data space with information that will never be used. + ** As there may be shallow copies of this value, make it a soft-NULL */ + sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); continue; } if( pColumn==0 ){ @@ -994,11 +934,13 @@ void sqlite3Insert( } } if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); + sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore); }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + if( regFromSelect!=regData ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + } }else{ sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); } diff --git a/src/select.c b/src/select.c index dd445deed3..a41f4a8254 100644 --- a/src/select.c +++ b/src/select.c @@ -585,13 +585,19 @@ static void selectInnerLoop( /* Pull the requested columns. */ nResultCol = pEList->nExpr; + if( pDest->iSdst==0 ){ pDest->iSdst = pParse->nMem+1; - pDest->nSdst = nResultCol; pParse->nMem += nResultCol; - }else{ - assert( pDest->nSdst==nResultCol ); + }else if( pDest->iSdst+nResultCol > pParse->nMem ){ + /* This is an error condition that can result, for example, when a SELECT + ** on the right-hand side of an INSERT contains more result columns than + ** there are columns in the table on the left. The error will be caught + ** and reported later. But we need to make sure enough memory is allocated + ** to avoid other spurious errors in the meantime. */ + pParse->nMem += nResultCol; } + pDest->nSdst = nResultCol; regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; ip1>0 && pOp->p1<=(p->nMem-p->nCursor) ); + pOut = &aMem[pOp->p1]; + pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; + break; +} /* Opcode: Blob P1 P2 * P4 * ** Synopsis: r[P2]=P4 (len=P1) @@ -2909,23 +2923,17 @@ case OP_AutoCommit: { /* Opcode: Transaction P1 P2 P3 P4 P5 ** -** Begin a transaction. The transaction ends when a Commit or Rollback -** opcode is encountered. Depending on the ON CONFLICT setting, the -** transaction might also be rolled back if an error is encountered. +** Begin a transaction on database P1 if a transaction is not already +** active. +** If P2 is non-zero, then a write-transaction is started, or if a +** read-transaction is already active, it is upgraded to a write-transaction. +** If P2 is zero, then a read-transaction is started. ** ** P1 is the index of the database file on which the transaction is ** started. Index 0 is the main database file and index 1 is the ** file used for temporary tables. Indices of 2 or more are used for ** attached databases. ** -** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is -** obtained on the database file when a write-transaction is started. No -** other process can start another write transaction while this transaction is -** underway. Starting a write transaction also creates a rollback journal. A -** write transaction must be started before any changes can be made to the -** database. If P2 is greater than or equal to 2 then an EXCLUSIVE lock is -** also obtained on the file. -** ** If a write-transaction is started and the Vdbe.usesStmtJournal flag is ** true (this flag is set if the Vdbe may modify more than one row and may ** throw an ABORT exception), a statement transaction may also be opened. @@ -2936,13 +2944,16 @@ case OP_AutoCommit: { ** entire transaction. If no error is encountered, the statement transaction ** will automatically commit when the VDBE halts. ** -** If P2 is zero, then a read-lock is obtained on the database file. -** ** If P5!=0 then this opcode also checks the schema cookie against P3 ** and the schema generation counter against P4. ** The cookie changes its value whenever the database schema changes. ** This operation is used to detect when that the cookie has changed -** and that the current process needs to reread the schema. +** and that the current process needs to reread the schema. If the schema +** cookie in P3 differs from the schema cookie in the database header or +** if the schema generation counter in P4 differs from the current +** generation counter, then an SQLITE_SCHEMA error is raised and execution +** halts. The sqlite3_step() wrapper function might then reprepare the +** statement and rerun it from the beginning. */ case OP_Transaction: { Btree *pBt; diff --git a/test/insert.test b/test/insert.test index e00b9a8028..83168122ab 100644 --- a/test/insert.test +++ b/test/insert.test @@ -398,7 +398,7 @@ ifcapable compound { } {1 2 3 4 5 6 7 8 9} do_test insert-10.2 { catchsql { - INSERT INTO t10 VALUES(11,12,13), (14,15); + INSERT INTO t10 VALUES(11,12,13), (14,15), (16,17,28); } } {1 {all VALUES must have the same number of terms}} } diff --git a/test/insert4.test b/test/insert4.test index 343a08af81..889d5e7807 100644 --- a/test/insert4.test +++ b/test/insert4.test @@ -253,7 +253,7 @@ ifcapable vacuum { # do_test insert4-5.1 { # Table does not exist. - catchsql { INSERT INTO t2 SELECT * FROM nosuchtable } + catchsql { INSERT INTO t2 SELECT a, b FROM nosuchtable } } {1 {no such table: nosuchtable}} do_test insert4-5.2 { # Number of columns does not match. From 2926f9694f7f9ed6669183832a224cc1a7c115c2 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Feb 2014 01:13:28 +0000 Subject: [PATCH 14/66] Fix the VDBE_PROFILE logic. Add a script to process the output file. FossilOrigin-Name: 7adb3da235c8c162c84f05ef4ccf1cc463805d5f --- manifest | 13 +++---- manifest.uuid | 2 +- src/vdbeaux.c | 12 ++++++- tool/vdbe_profile.tcl | 82 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 tool/vdbe_profile.tcl diff --git a/manifest b/manifest index 8aef1ebcfc..567cd67cd1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Seek\spast\sNULLs\sin\sa\stop-constrained\ssearch.\s\sAvoid\schecking\sfor\sNULLs\sin\nthe\sbody\sof\sthe\ssearch. -D 2014-02-14T23:49:13.552 +C Fix\sthe\sVDBE_PROFILE\slogic.\s\sAdd\sa\sscript\sto\sprocess\sthe\soutput\sfile. +D 2014-02-17T01:13:28.650 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 543ed4ed0c41b34affad239374d4c07e6e5b2401 F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c dac6e571262a322b2f889752a8dd36549bdacd2b +F src/vdbeaux.c 9098973ff22c6fdfd68d061e11c2e64f65eea2d1 F src/vdbeblob.c 9542e116c1db5ed813977581d506c176e117c0ec F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 @@ -1147,10 +1147,11 @@ F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 +F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3c1ae447dec8fc2af1c5105134061717594ac0e0 -R 20e62eafcdc3ac9a7a16fa36432e6177 +P e07a32f30862acf3b322d4d8deb015846d6f8f5f +R a089b7b7dc577bc47ffd22f19eb9e985 U drh -Z f35a13e794e2689c6821aa3d892fcd6f +Z f101c06fe6a48199aebfe3f4c9baeea7 diff --git a/manifest.uuid b/manifest.uuid index ed5e06552e..79ba90c802 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e07a32f30862acf3b322d4d8deb015846d6f8f5f \ No newline at end of file +7adb3da235c8c162c84f05ef4ccf1cc463805d5f \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 95c05f7e5c..f7f1d5c288 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1174,7 +1174,7 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS displayComment(pOp, zP4, zCom, sizeof(zCom)); #else - zCom[0] = 0 + zCom[0] = 0; #endif /* NB: The sqlite3OpcodeName() function is implemented by code created ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the @@ -2552,6 +2552,16 @@ int sqlite3VdbeReset(Vdbe *p){ fprintf(out, "%02x", p->aOp[i].opcode); } fprintf(out, "\n"); + if( p->zSql ){ + char c, pc = 0; + fprintf(out, "-- "); + for(i=0; (c = p->zSql[i])!=0; i++){ + if( pc=='\n' ) fprintf(out, "-- "); + putc(c, out); + pc = c; + } + if( pc!='\n' ) fprintf(out, "\n"); + } for(i=0; inOp; i++){ fprintf(out, "%6d %10lld %8lld ", p->aOp[i].cnt, diff --git a/tool/vdbe_profile.tcl b/tool/vdbe_profile.tcl new file mode 100644 index 0000000000..fb1f955391 --- /dev/null +++ b/tool/vdbe_profile.tcl @@ -0,0 +1,82 @@ +#!/bin/tclsh +# +# Run this script in the same directory as the "vdbe_profile.out" file. +# This script summarizes the results contained in that file. +# +if {![file readable vdbe_profile.out]} { + error "run this script in the same directory as the vdbe_profile.out file" +} +set in [open vdbe_profile.out r] +set stmt {} +set allstmt {} +while {![eof $in]} { + set line [gets $in] + if {$line==""} continue + if {[regexp {^---- } $line]} { + set stmt [lindex $line 1] + if {[info exists cnt($stmt)]} { + incr cnt($stmt) + set firsttime 0 + } else { + set cnt($stmt) 1 + set sql($stmt) {} + set firsttime 1 + lappend allstmt $stmt + } + continue; + } + if {[regexp {^-- } $line]} { + if {$firsttime} { + append sql($stmt) [string range $line 3 end]\n + } + continue + } + if {![regexp {^ *\d+ *\d+ *\d+ *\d+ ([A-Z].*)} $line all detail]} continue + set c [lindex $line 0] + set t [lindex $line 1] + set addr [lindex $line 3] + set op [lindex $line 4] + if {[info exists opcnt($op)]} { + incr opcnt($op) $c + incr opcycle($op) $t + } else { + set opcnt($op) $c + set opcycle($op) $t + } + if {[info exists stat($stmt,$addr)]} { + foreach {cx tx detail} $stat($stmt,$addr) break + incr cx $c + incr tx $t + set stat($stmt,$addr) [list $cx $tx $detail] + } else { + set stat($stmt,$addr) [list $c $t $detail] + } +} +close $in + +foreach stmt $allstmt { + puts "********************************************************************" + puts [string trim $sql($stmt)] + puts "Execution count: $cnt($stmt)" + for {set i 0} {[info exists stat($stmt,$i)]} {incr i} { + foreach {cx tx detail} $stat($stmt,$i) break + if {$cx==0} { + set ax 0 + } else { + set ax [expr {$tx/$cx}] + } + puts [format {%8d %12d %12d %4d %s} $cx $tx $ax $i $detail] + } +} +puts "********************************************************************" +puts "OPCODES:" +foreach op [lsort [array names opcnt]] { + set cx $opcnt($op) + set tx $opcycle($op) + if {$cx==0} { + set ax 0 + } else { + set ax [expr {$tx/$cx}] + } + puts [format {%8d %12d %12d %s} $cx $tx $ax $op] +} From 57bf4a8eeb6f0c0c70e16b1682846f57a4cb6595 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Feb 2014 14:59:22 +0000 Subject: [PATCH 15/66] Avoid unnecessary calls to applyAffinity() during INSERT and UPDATE operations, especially for table that have indices and tables for which all columns have affinity "NONE". FossilOrigin-Name: 35b4d6e938164fabaf30b504c54cfd9a69060cee --- manifest | 29 +++++++++++-------------- manifest.uuid | 2 +- src/analyze.c | 2 +- src/delete.c | 2 +- src/fkey.c | 4 ++-- src/insert.c | 58 +++++++++++++++++++++++++++++-------------------- src/pragma.c | 5 ++--- src/sqliteInt.h | 2 +- src/update.c | 5 ++--- src/vdbe.c | 6 ++--- 10 files changed, 60 insertions(+), 55 deletions(-) diff --git a/manifest b/manifest index 392084a893..4d28d8ab47 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\scode\sgenerator\sfor\sINSERT\sINTO\s...\sSELECT\sso\sthat\sthe\sSELECT\ngenerates\soutput\sdirectly\sin\sthe\sregisters\sthat\sINSERT\sINTO\swill\sbe\susing,\nin\smany\scases,\sand\sOP_SCopy\soperations\scan\sthus\sbe\savoided. -D 2014-02-16T01:55:49.753 +C Avoid\sunnecessary\scalls\sto\sapplyAffinity()\sduring\sINSERT\sand\sUPDATE\noperations,\sespecially\sfor\stable\sthat\shave\sindices\sand\stables\sfor\swhich\nall\scolumns\shave\saffinity\s"NONE". +D 2014-02-17T14:59:22.345 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c d5348d0f86a5fc8fb3987727402f023953c021cf -F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f +F src/analyze.c 3ec444402a5d9ac1018ac8c549f8e82ac23d4122 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 @@ -171,16 +171,16 @@ F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3 +F src/delete.c 57a09d3d576dd15cd54d945b7b0b478bac71f379 F src/expr.c 90bba0ca6ec97d6857458f08a8ad2820130e13cf F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5 +F src/fkey.c b3da26dfcd53a68e1b7162a84e0bf70e54092647 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 36e61dd2201c34a11886487e7afb86f3451ffc52 +F src/insert.c ddc56dc855069ddf530127a346ddc2e67f0396e6 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -210,7 +210,7 @@ F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c -F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b +F src/pragma.c 769d08f10b7848dbd1950d0723bfcb12fb22b7f3 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 82aa6a9b068b5a827e85af0b7fa12661f5874459 +F src/sqliteInt.h c5ba0868bddac9fdb0df4686ab43150fefb27da5 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -273,11 +273,11 @@ F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 F src/trigger.c a417d386e214f0abd2e0f756b834b4d9f4d3368a -F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee +F src/update.c b126167ee39470b6148fa3f89182e7c855dc15d0 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 7b74ce685d05c1123b0360ce6bc377df114b8533 +F src/vdbe.c e3ba6ad0111dbd4234fef5e119dbe30d0abb3cf1 F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -1150,10 +1150,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e07a32f30862acf3b322d4d8deb015846d6f8f5f -R 4c464651f87f73c0925f058052453922 -T *branch * insert-optimization -T *sym-insert-optimization * -T -sym-trunk * +P aa2d8b0e8154dd2f5e2c837dc11ab362b083495b +R 76ffa4a9c63f5b066cf1aa1863fa3f56 U drh -Z fb4eb5dbe58efaaeaac33be3bebd9bdd +Z c57e89c4432511b9873eed17e1f87e02 diff --git a/manifest.uuid b/manifest.uuid index bab4067e49..f218979de8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aa2d8b0e8154dd2f5e2c837dc11ab362b083495b \ No newline at end of file +35b4d6e938164fabaf30b504c54cfd9a69060cee \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 3d5c4f6bec..8e230f7571 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1185,7 +1185,7 @@ static void analyzeOneTable( } sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); #endif - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regTemp, "bbbbbb", 0); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); diff --git a/src/delete.c b/src/delete.c index 936517c4a7..4ebda1b183 100644 --- a/src/delete.c +++ b/src/delete.c @@ -443,7 +443,7 @@ void sqlite3DeleteFrom( iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, - sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); }else{ /* Get the rowid of the row to be deleted and remember it in the RowSet */ diff --git a/src/fkey.c b/src/fkey.c index 46c90a0989..c094783a85 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -412,8 +412,8 @@ static void fkLookupParent( sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, + sqlite3IndexAffinityStr(v,pIdx), nCol); sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); sqlite3ReleaseTempReg(pParse, regRec); diff --git a/src/insert.c b/src/insert.c index a9e6bd2866..a9c0641474 100644 --- a/src/insert.c +++ b/src/insert.c @@ -98,10 +98,16 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ } /* -** Set P4 of the most recently inserted opcode to a column affinity -** string for table pTab. A column affinity string has one character -** for each column indexed by the index, according to the affinity of the -** column: +** Compute the affinity string for table pTab, if it has not already been +** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. +** +** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and +** if iReg>0 then code an OP_Affinity opcode that will set the affinities +** for register iReg and following. Or if affinities exists and iReg==0, +** then just set the P4 operand of the previous opcode (which should be +** an OP_MakeRecord) to the affinity string. +** +** A column affinity string has one character column: ** ** Character Column affinity ** ------------------------------ @@ -111,19 +117,11 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** 'd' INTEGER ** 'e' REAL */ -void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ - /* The first time a column affinity string for a particular table - ** is required, it is allocated and populated here. It is then - ** stored as a member of the Table structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqlite3DeleteTable() when the Table structure itself is cleaned up. - */ - if( !pTab->zColAff ){ - char *zColAff; - int i; +void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ + int i; + char *zColAff = pTab->zColAff; + if( zColAff==0 ){ sqlite3 *db = sqlite3VdbeDb(v); - zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); if( !zColAff ){ db->mallocFailed = 1; @@ -133,12 +131,19 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ for(i=0; inCol; i++){ zColAff[i] = pTab->aCol[i].affinity; } - zColAff[pTab->nCol] = '\0'; - + do{ + zColAff[i--] = 0; + }while( i>=0 && zColAff[i]==SQLITE_AFF_NONE ); pTab->zColAff = zColAff; } - - sqlite3VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT); + i = sqlite3Strlen30(zColAff); + if( i ){ + if( iReg ){ + sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); + }else{ + sqlite3VdbeChangeP4(v, -1, zColAff, i); + } + } } /* @@ -846,8 +851,7 @@ void sqlite3Insert( ** table column affinities. */ if( !isView ){ - sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol); - sqlite3TableAffinityStr(v, pTab); + sqlite3TableAffinity(v, pTab, regCols+1); } /* Fire BEFORE or INSTEAD OF triggers */ @@ -1153,6 +1157,7 @@ void sqlite3GenerateConstraintChecks( int ipkTop = 0; /* Top of the rowid change constraint check */ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ + u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ int regRowid = -1; /* Register holding ROWID value */ isUpdate = regOldData!=0; @@ -1364,6 +1369,10 @@ void sqlite3GenerateConstraintChecks( int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ + if( bAffinityDone==0 ){ + sqlite3TableAffinity(v, pTab, regNewData+1); + bAffinityDone = 1; + } iThisCur = iIdxCur+ix; addrUniqueOk = sqlite3VdbeMakeLabel(v); @@ -1394,7 +1403,6 @@ void sqlite3GenerateConstraintChecks( VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT); VdbeComment((v, "for %s", pIdx->zName)); sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn); @@ -1539,12 +1547,14 @@ void sqlite3CompleteInsertion( int regData; /* Content registers (after the rowid) */ int regRec; /* Register holding assemblied record for the table */ int i; /* Loop counter */ + u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; + bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); } @@ -1561,7 +1571,7 @@ void sqlite3CompleteInsertion( regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - sqlite3TableAffinityStr(v, pTab); + if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; diff --git a/src/pragma.c b/src/pragma.c index 7383bce96f..969dce8664 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1727,9 +1727,8 @@ void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); } if( pParent ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); - sqlite3VdbeChangeP4(v, -1, - sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, + sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a82b2e737e..392517c8d7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3224,7 +3224,7 @@ int sqlite3VarintLen(u64 v); const char *sqlite3IndexAffinityStr(Vdbe *, Index *); -void sqlite3TableAffinityStr(Vdbe *, Table *); +void sqlite3TableAffinity(Vdbe*, Table*, int); char sqlite3CompareAffinity(Expr *pExpr, char aff2); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); diff --git a/src/update.c b/src/update.c index a7da4ce71f..41ce7f0c77 100644 --- a/src/update.c +++ b/src/update.c @@ -390,7 +390,7 @@ void sqlite3Update( regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3IndexAffinityStr(v, pPk), nPk); sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); } sqlite3WhereEnd(pWInfo); @@ -524,8 +524,7 @@ void sqlite3Update( ** verified. One could argue that this is wrong. */ if( tmask&TRIGGER_BEFORE ){ - sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); - sqlite3TableAffinityStr(v, pTab); + sqlite3TableAffinity(v, pTab, regNew); sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); diff --git a/src/vdbe.c b/src/vdbe.c index 41ad66215d..5f046a63e2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2498,7 +2498,6 @@ case OP_Affinity: { while( (cAff = *(zAffinity++))!=0 ){ assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); - ExpandBlob(pIn1); applyAffinity(pIn1, cAff, encoding); pIn1++; } @@ -2576,8 +2575,9 @@ case OP_MakeRecord: { if( zAffinity ){ pRec = pData0; do{ - applyAffinity(pRec, *(zAffinity++), encoding); - }while( (++pRec)<=pLast ); + applyAffinity(pRec++, *(zAffinity++), encoding); + assert( zAffinity[0]==0 || pRec<=pLast ); + }while( zAffinity[0] ); } /* Loop through the elements that will make up the record to figure From 8be09304b79dd5a2d5f53ca00b01ba9fcf81f21d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Feb 2014 15:40:19 +0000 Subject: [PATCH 16/66] Add a test case for OP_SoftNull. FossilOrigin-Name: f29d194e03d6bcc78bf883b77e591dbccada02f0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/insert.test | 10 ++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 3a3470f9c7..41fc121645 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sVDBE_PROFILE\sfixes\sfrom\strunk. -D 2014-02-17T15:36:39.392 +C Add\sa\stest\scase\sfor\sOP_SoftNull. +D 2014-02-17T15:40:19.609 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -613,7 +613,7 @@ F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 -F test/insert.test c120294273b18cf9c8b1a3158131f7a825bdba41 +F test/insert.test acf909b067b838eb55338d619e800e148c17f1f5 F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30 F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 35b4d6e938164fabaf30b504c54cfd9a69060cee 7adb3da235c8c162c84f05ef4ccf1cc463805d5f -R 2b995c2f8f9fb3c739cf787130cc4e23 +P 2914e4191121004a3f564b1fbf1c235dcc595503 +R b009af851099e49da0fb1800028a0b8c U drh -Z a75f767ce30ab2f817d9dd9884981718 +Z ba859408f13b87421335d53499aa861e diff --git a/manifest.uuid b/manifest.uuid index 5178dd9e5a..6e6a7e7211 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2914e4191121004a3f564b1fbf1c235dcc595503 \ No newline at end of file +f29d194e03d6bcc78bf883b77e591dbccada02f0 \ No newline at end of file diff --git a/test/insert.test b/test/insert.test index 83168122ab..776bce1146 100644 --- a/test/insert.test +++ b/test/insert.test @@ -403,6 +403,16 @@ ifcapable compound { } {1 {all VALUES must have the same number of terms}} } +# Need for the OP_SoftNull opcode +# +do_execsql_test insert-11.1 { + CREATE TABLE t11a AS SELECT '123456789' AS x; + CREATE TABLE t11b (a INTEGER PRIMARY KEY, b, c); + INSERT INTO t11b SELECT x, x, x FROM t11a; + SELECT quote(a), quote(b), quote(c) FROM t11b; +} {123456789 '123456789' '123456789'} + + integrity_check insert-99.0 finish_test From 688852ab15b7d9f6a3c1f113f25f3c72bcfe3856 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Feb 2014 22:40:43 +0000 Subject: [PATCH 17/66] Add logic to do test coverage measurements on the VDBE code. FossilOrigin-Name: ce184c7bb16988641d37c908d9b3042456d4be3d --- manifest | 48 ++++++++++++++-------------- manifest.uuid | 2 +- src/alter.c | 2 +- src/analyze.c | 8 +++-- src/build.c | 12 +++---- src/delete.c | 12 +++++-- src/expr.c | 46 +++++++++++++++++---------- src/fkey.c | 18 ++++++----- src/insert.c | 54 ++++++++++++++++++-------------- src/main.c | 15 +++++++++ src/pragma.c | 48 +++++++++++++++------------- src/select.c | 83 +++++++++++++++++++++++++++---------------------- src/sqlite.h.in | 3 +- src/sqliteInt.h | 7 +++++ src/trigger.c | 3 +- src/update.c | 19 ++++++++--- src/vdbe.c | 70 ++++++++++++++++++++++++++++++++--------- src/vdbe.h | 15 ++++++++- src/vdbeaux.c | 19 ++++++++++- src/vdbeblob.c | 5 ++- src/where.c | 38 ++++++++++++++++------ 21 files changed, 349 insertions(+), 178 deletions(-) diff --git a/manifest b/manifest index 41fc121645..79158f64cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stest\scase\sfor\sOP_SoftNull. -D 2014-02-17T15:40:19.609 +C Add\slogic\sto\sdo\stest\scoverage\smeasurements\son\sthe\sVDBE\scode. +D 2014-02-17T22:40:43.958 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,8 +156,8 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c d5348d0f86a5fc8fb3987727402f023953c021cf -F src/analyze.c 3ec444402a5d9ac1018ac8c549f8e82ac23d4122 +F src/alter.c 829d67a359b7c5d37120be994af2c0eac730070c +F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 @@ -166,26 +166,26 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200 F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 -F src/build.c 13b9d82181d95af7b00ec8a8e1304bac096432d4 +F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c 57a09d3d576dd15cd54d945b7b0b478bac71f379 -F src/expr.c 90bba0ca6ec97d6857458f08a8ad2820130e13cf +F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7 +F src/expr.c d1a8ccbf7e4dac6198674d33853e8ed01072eca4 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c b3da26dfcd53a68e1b7162a84e0bf70e54092647 +F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c ddc56dc855069ddf530127a346ddc2e67f0396e6 +F src/insert.c 5d5e1d78f74804739b424c92346bdc26c146dfa4 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 07225af6a00be0b7f34ac52e60f99cf5cbb2a475 +F src/main.c e054917b1beb3081b0f23e8bdd3d6c0e12933dd3 F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b @@ -210,18 +210,18 @@ F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c -F src/pragma.c 769d08f10b7848dbd1950d0723bfcb12fb22b7f3 +F src/pragma.c 2635d6bf8b54003ebefd773df2f50258cece2bec F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c ebec4d3fad7fd5aa33cd69e2f50e9c109285dc73 +F src/select.c 618b53bd4553bd7a9ef95069396f12a8f28489e7 F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 -F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b +F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h c5ba0868bddac9fdb0df4686ab43150fefb27da5 +F src/sqliteInt.h 004bd50575a05eefba7228c2d0fee432a53200de F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -272,17 +272,17 @@ F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9 F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 -F src/trigger.c a417d386e214f0abd2e0f756b834b4d9f4d3368a -F src/update.c b126167ee39470b6148fa3f89182e7c855dc15d0 +F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc +F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c e3ba6ad0111dbd4234fef5e119dbe30d0abb3cf1 -F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26 +F src/vdbe.c 392f03b25152eb44565a78b8b809743c97e5852b +F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 9098973ff22c6fdfd68d061e11c2e64f65eea2d1 -F src/vdbeblob.c 9542e116c1db5ed813977581d506c176e117c0ec +F src/vdbeaux.c 0e01d6fda149c689039caadb8c89b20abb58e21d +F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 7d9c988741c7d0e4a57774ae4b56e59675c4014a +F src/where.c 7825dce3f92d7c7de9329505deefe176cbd5ba43 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 2914e4191121004a3f564b1fbf1c235dcc595503 -R b009af851099e49da0fb1800028a0b8c +P f29d194e03d6bcc78bf883b77e591dbccada02f0 +R 3842d7f2fc20472907a26e6db9a0b24a U drh -Z ba859408f13b87421335d53499aa861e +Z 8a746710251048df8d65813e18590ec6 diff --git a/manifest.uuid b/manifest.uuid index 6e6a7e7211..be861c2b1c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f29d194e03d6bcc78bf883b77e591dbccada02f0 \ No newline at end of file +ce184c7bb16988641d37c908d9b3042456d4be3d \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 67070a5891..b8bf20cfd9 100644 --- a/src/alter.c +++ b/src/alter.c @@ -604,7 +604,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); diff --git a/src/analyze.c b/src/analyze.c index 8e230f7571..235a2abaf8 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1077,6 +1077,7 @@ static void analyzeOneTable( ** */ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng); addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto); @@ -1098,6 +1099,7 @@ static void analyzeOneTable( aGotoChng[i] = sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng); aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto); @@ -1144,7 +1146,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp); sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 2+IsStat34); - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); @@ -1171,10 +1173,12 @@ static void analyzeOneTable( addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); + VdbeCoverage(v); callStatGet(v, regStat4, STAT_GET_NEQ, regEq); callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); + VdbeCoverage(v); #ifdef SQLITE_ENABLE_STAT3 sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pIdx->aiColumn[0], regSample); @@ -1205,7 +1209,7 @@ static void analyzeOneTable( if( pOnlyIdx==0 && needTableCnt ){ VdbeComment((v, "%s", pTab->zName)); sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); + jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); diff --git a/src/build.c b/src/build.c index 99bba67dd2..5b6c87f220 100644 --- a/src/build.c +++ b/src/build.c @@ -948,7 +948,7 @@ void sqlite3StartTable( reg3 = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); - j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); + j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? 1 : SQLITE_MAX_FILE_FORMAT; sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); @@ -2675,27 +2675,27 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); sqlite3VdbeResolveLabel(v, iPartIdxLabel); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); - addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); assert( pKey!=0 || db->mallocFailed || pParse->nErr ); if( pIndex->onError!=OE_None && pKey!=0 ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); addr2 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, - pKey->nField - pIndex->nKeyCol); + pKey->nField - pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); }else{ addr2 = sqlite3VdbeCurrentAddr(v); @@ -2704,7 +2704,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); + sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Close, iTab); diff --git a/src/delete.c b/src/delete.c index 4ebda1b183..3fa41c53f0 100644 --- a/src/delete.c +++ b/src/delete.c @@ -481,13 +481,15 @@ void sqlite3DeleteFrom( if( aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); + VdbeCoverage(v); } }else if( pPk ){ - addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); + addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); + VdbeCoverage(v); assert( nKey==1 ); } @@ -511,7 +513,7 @@ void sqlite3DeleteFrom( if( okOnePass ){ sqlite3VdbeResolveLabel(v, addrBypass); }else if( pPk ){ - sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); + sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop); @@ -609,7 +611,10 @@ void sqlite3GenerateRowDelete( ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; - if( !bNoSeek ) sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); + if( !bNoSeek ){ + sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); + VdbeCoverage(v); + } /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ @@ -651,6 +656,7 @@ void sqlite3GenerateRowDelete( */ if( addrStartnOnce++); + int addr = sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); + VdbeCoverage(v); + return addr; } /* @@ -1837,6 +1839,7 @@ int sqlite3CodeSubselect( if( isRowid ){ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); @@ -1960,10 +1963,11 @@ static void sqlite3ExprCodeIN( if( destIfNull==destIfFalse ){ /* Shortcut for the common case where the false and NULL outcomes are ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); + sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); + int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); sqlite3VdbeJumpHere(v, addr1); } @@ -1971,8 +1975,9 @@ static void sqlite3ExprCodeIN( if( eType==IN_INDEX_ROWID ){ /* In this case, the RHS is the ROWID of table b-tree */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + VdbeCoverage(v); }else{ /* In this case, the RHS is an index b-tree. */ @@ -1993,7 +1998,7 @@ static void sqlite3ExprCodeIN( ** for this particular IN operator. */ sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - + VdbeCoverage(v); }else{ /* In this branch, the RHS of the IN might contain a NULL and ** the presence of a NULL on the RHS makes a difference in the @@ -2006,6 +2011,7 @@ static void sqlite3ExprCodeIN( ** over all of the code that follows. */ j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); + VdbeCoverage(v); /* Here we begin generating code that runs if the LHS is not ** contained within the RHS. Generate additional code that @@ -2013,8 +2019,9 @@ static void sqlite3ExprCodeIN( ** jump to destIfNull. If there are no NULLs in the RHS then ** jump to destIfFalse. */ - j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); + j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); VdbeCoverage(v); j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); sqlite3VdbeJumpHere(v, j3); sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); @@ -2023,7 +2030,7 @@ static void sqlite3ExprCodeIN( /* Jump to the appropriate target depending on whether or not ** the RHS contains a NULL */ - sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); + sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); /* The OP_Found at the top of this branch jumps here when true, @@ -2560,7 +2567,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2); + r1, r2, inReg, SQLITE_STOREP2); VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -2574,6 +2581,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); + VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -2663,7 +2671,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(v, OP_Integer, 1, target); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); - addr = sqlite3VdbeAddOp1(v, op, r1); + addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); break; @@ -2715,6 +2723,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); for(i=1; ia[i].pExpr, target); @@ -2853,12 +2862,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ r4 = sqlite3GetTempReg(pParse); codeCompare(pParse, pLeft, pRight, OP_Ge, r1, r2, r3, SQLITE_STOREP2); + VdbeCoverage(v); pLItem++; pRight = pLItem->pExpr; sqlite3ReleaseTempReg(pParse, regFree2); r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); @@ -3025,6 +3036,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pExpr->affinity==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); + VdbeCoverage(v); }else{ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, pExpr->affinity, pExpr->u.zToken, 0, 0); @@ -3613,7 +3625,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); + r1, r2, dest, jumpIfNull); VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3626,7 +3638,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); + r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3638,7 +3650,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ testcase( op==TK_ISNULL ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); + sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v); testcase( regFree1==0 ); break; } @@ -3665,6 +3677,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); testcase( regFree1==0 ); testcase( jumpIfNull==0 ); } @@ -3766,7 +3779,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); + r1, r2, dest, jumpIfNull); VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3779,7 +3792,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); + r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3789,7 +3802,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ testcase( op==TK_ISNULL ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); + sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v); testcase( regFree1==0 ); break; } @@ -3818,6 +3831,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ }else{ r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + VdbeCoverage(v); testcase( regFree1==0 ); testcase( jumpIfNull==0 ); } diff --git a/src/fkey.c b/src/fkey.c index c094783a85..c94f969238 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -340,10 +340,11 @@ static void fkLookupParent( ** search for a matching row in the parent table. */ if( nIncr<0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); + VdbeCoverage(v); } for(i=0; inCol; i++){ int iReg = aiCol[i] + regData + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); + sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v); } if( isIgnore==0 ){ @@ -360,17 +361,18 @@ static void fkLookupParent( ** will have INTEGER affinity applied to it, which may not be correct. */ sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); + VdbeCoverage(v); /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not ** increment the constraint-counter. */ if( pTab==pFKey->pFrom && nIncr==1 ){ - sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); + sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); } sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); sqlite3VdbeJumpHere(v, iMustBeInt); @@ -406,7 +408,7 @@ static void fkLookupParent( /* The parent key is a composite key that includes the IPK column */ iParent = regData; } - sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); + sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); @@ -414,7 +416,7 @@ static void fkLookupParent( sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, sqlite3IndexAffinityStr(v,pIdx), nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); + sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempRange(pParse, regTemp, nCol); @@ -552,6 +554,7 @@ static void fkScanChildren( if( nIncr<0 ){ iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); + VdbeCoverage(v); } /* Create an Expr object representing an SQL expression like: @@ -714,7 +717,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ } if( !p ) return; iSkip = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); + sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); } pParse->disableTriggers = 1; @@ -732,6 +735,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ */ if( (db->flags & SQLITE_DeferFKs)==0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, 0, P4_STATIC, P5_ConstraintFK); } @@ -891,7 +895,7 @@ void sqlite3FkCheck( int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; for(i=0; inCol; i++){ int iReg = pFKey->aCol[i].iFrom + regOld + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); + sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); } diff --git a/src/insert.c b/src/insert.c index a9c0641474..64786ee112 100644 --- a/src/insert.c +++ b/src/insert.c @@ -262,14 +262,14 @@ void sqlite3AutoincrementBegin(Parse *pParse){ sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); + sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); + sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); sqlite3VdbeAddOp0(v, OP_Close); } @@ -311,11 +311,11 @@ void sqlite3AutoincrementEnd(Parse *pParse){ iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); - j2 = sqlite3VdbeAddOp0(v, OP_Rewind); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp0(v, OP_Rewind); VdbeCoverage(v); j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); - j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); - sqlite3VdbeAddOp2(v, OP_Next, 0, j3); + j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Next, 0, j3); VdbeCoverage(v); sqlite3VdbeJumpHere(v, j2); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); j5 = sqlite3VdbeAddOp0(v, OP_Goto); @@ -692,7 +692,7 @@ void sqlite3Insert( regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); @@ -777,7 +777,7 @@ void sqlite3Insert( ** end loop ** D: ... */ - addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); + addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v); addrCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ /* This block codes the top of loop only. The complete loop is the @@ -789,6 +789,7 @@ void sqlite3Insert( ** D: ... */ addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); + VdbeCoverage(v); } /* Run the BEFORE and INSTEAD OF triggers, if there are any @@ -814,10 +815,10 @@ void sqlite3Insert( assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); } - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } /* Cannot have triggers on a virtual table. If it were possible, @@ -892,14 +893,14 @@ void sqlite3Insert( if( !appendFlag ){ int j1; if( !IsVirtual(pTab) ){ - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); sqlite3VdbeJumpHere(v, j1); }else{ j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); + sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v); } - sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v); } }else if( IsVirtual(pTab) || withoutRowid ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); @@ -990,7 +991,7 @@ void sqlite3Insert( */ sqlite3VdbeResolveLabel(v, endOfLoop); if( useTempTable ){ - sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); + sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ @@ -1212,15 +1213,17 @@ void sqlite3GenerateConstraintChecks( sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, regNewData+1+i, zMsg, P4_DYNAMIC); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); + VdbeCoverage(v); break; } case OE_Ignore: { sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); + VdbeCoverage(v); break; } default: { assert( onError==OE_Replace ); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v); sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); sqlite3VdbeJumpHere(v, j1); break; @@ -1272,6 +1275,7 @@ void sqlite3GenerateConstraintChecks( ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); + VdbeCoverage(v); } /* If the response to a rowid conflict is REPLACE but the response @@ -1291,6 +1295,7 @@ void sqlite3GenerateConstraintChecks( /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); + VdbeCoverage(v); /* Generate code that deals with a rowid collision */ switch( onError ){ @@ -1430,7 +1435,7 @@ void sqlite3GenerateConstraintChecks( /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, - regIdx, pIdx->nKeyCol); + regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); @@ -1441,6 +1446,7 @@ void sqlite3GenerateConstraintChecks( ** is different from old-rowid */ if( isUpdate ){ sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); + VdbeCoverage(v); } }else{ int x; @@ -1475,7 +1481,7 @@ void sqlite3GenerateConstraintChecks( } sqlite3VdbeAddOp4(v, op, regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ - ); + ); VdbeCoverage(v); } } } @@ -1557,6 +1563,7 @@ void sqlite3CompleteInsertion( bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); pik_flags = 0; @@ -1940,16 +1947,17 @@ static int xferOptimization( ** ** (3) onError is something other than OE_Abort and OE_Rollback. */ - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); - emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + VdbeCoverage(v); sqlite3RowidConstraint(pParse, onError, pDest); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); @@ -1963,7 +1971,7 @@ static int xferOptimization( sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ @@ -1982,10 +1990,10 @@ static int xferOptimization( sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); diff --git a/src/main.c b/src/main.c index 45e31a8076..8b7495dd49 100644 --- a/src/main.c +++ b/src/main.c @@ -3307,6 +3307,21 @@ int sqlite3_test_control(int op, ...){ break; } + + /* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr); + ** + ** Set the VDBE coverage callback function to xCallback with context + ** pointer ptr. + */ + case SQLITE_TESTCTRL_VDBE_COVERAGE: { +#ifdef SQLITE_VDBE_COVERAGE + typedef void (*branch_callback)(void*,int,u8,u8); + sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); + sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); +#endif + break; + } + } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/pragma.c b/src/pragma.c index 969dce8664..a586370b8d 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -824,6 +824,7 @@ void sqlite3Pragma( ** size of historical compatibility. */ case PragTyp_DEFAULT_CACHE_SIZE: { + static const int iLn = __LINE__+2; static const VdbeOpList getCacheSize[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ @@ -841,7 +842,7 @@ void sqlite3Pragma( sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; - addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); @@ -1086,6 +1087,7 @@ void sqlite3Pragma( ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ + static const int iLn = __LINE__+2; static const VdbeOpList setMeta6[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, @@ -1095,7 +1097,7 @@ void sqlite3Pragma( { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ }; int iAddr; - iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); + iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); @@ -1121,10 +1123,10 @@ void sqlite3Pragma( } sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); - addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); + addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_ResultRow, 1); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); break; } @@ -1695,7 +1697,7 @@ void sqlite3Pragma( assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTabnTab = i; - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); pIdx = 0; @@ -1711,25 +1713,26 @@ void sqlite3Pragma( if( iKey!=pTab->iPKey ){ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); - sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, - sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, + sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } - sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); + sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ for(j=0; jnCol; j++){ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); } if( pParent ){ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); + VdbeCoverage(v); } } sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); @@ -1740,7 +1743,7 @@ void sqlite3Pragma( sqlite3VdbeResolveLabel(v, addrOk); sqlite3DbFree(db, aiCols); } - sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrTop); } } @@ -1787,6 +1790,7 @@ void sqlite3Pragma( ** messages have been generated, output OK. Otherwise output the ** error message */ + static const int iLn = __LINE__+2; static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ { OP_IfNeg, 1, 0, 0}, /* 1 */ @@ -1835,6 +1839,7 @@ void sqlite3Pragma( sqlite3CodeVerifySchema(pParse, i); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); @@ -1866,7 +1871,7 @@ void sqlite3Pragma( /* Do the b-tree integrity checks */ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); sqlite3VdbeChangeP5(v, (u8)i); - addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); + addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); @@ -1888,6 +1893,7 @@ void sqlite3Pragma( if( pTab->pIndex==0 ) continue; pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); sqlite3ExprCacheClear(pParse); @@ -1898,7 +1904,7 @@ void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ } pParse->nMem = MAX(pParse->nMem, 8+j); - sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2, jmp3, jmp4; @@ -1908,7 +1914,7 @@ void sqlite3Pragma( pPrior = pIdx; sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1, - pIdx->nColumn); + pIdx->nColumn); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC); sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); @@ -1918,13 +1924,13 @@ void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); - jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); + jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeJumpHere(v, jmp4); sqlite3VdbeJumpHere(v, jmp2); sqlite3VdbeResolveLabel(v, jmp3); } - sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); + sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); #ifndef SQLITE_OMIT_BTREECOUNT sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, @@ -1932,10 +1938,10 @@ void sqlite3Pragma( for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ if( pPk==pIdx ) continue; addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); - sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); + sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); @@ -1944,7 +1950,7 @@ void sqlite3Pragma( #endif /* SQLITE_OMIT_BTREECOUNT */ } } - addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); + addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); sqlite3VdbeChangeP2(v, addr, -mxErr); sqlite3VdbeJumpHere(v, addr+1); sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); @@ -2082,7 +2088,7 @@ void sqlite3Pragma( { OP_Integer, 0, 1, 0}, /* 1 */ { OP_SetCookie, 0, 0, 1}, /* 2 */ }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); sqlite3VdbeChangeP1(v, addr+2, iDb); @@ -2094,7 +2100,7 @@ void sqlite3Pragma( { OP_ReadCookie, 0, 1, 0}, /* 1 */ { OP_ResultRow, 1, 1, 0} }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+1, iDb); sqlite3VdbeChangeP3(v, addr+1, iCookie); diff --git a/src/select.c b/src/select.c index a41f4a8254..fcd8b7ea0b 100644 --- a/src/select.c +++ b/src/select.c @@ -455,7 +455,7 @@ static void pushOntoSorter( }else{ iLimit = pSelect->iLimit; } - addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); + addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); addr2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); @@ -476,7 +476,7 @@ static void codeOffset( if( iOffset>0 && iContinue!=0 ){ int addr; sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1); - addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); + addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); VdbeComment((v, "skip OFFSET records")); sqlite3VdbeJumpHere(v, addr); @@ -504,7 +504,7 @@ static void codeDistinct( v = pParse->pVdbe; r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); + sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3ReleaseTempReg(pParse, r1); @@ -644,9 +644,11 @@ static void selectInnerLoop( CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); if( iiLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } } @@ -1080,12 +1083,13 @@ static void generateSortTail( int ptab2 = pParse->nTab++; sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); + VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow); sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); }else{ - addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); + addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow); } @@ -1143,9 +1147,9 @@ static void generateSortTail( */ sqlite3VdbeResolveLabel(v, addrContinue); if( p->selFlags & SF_UseSorter ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); + sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v); }else{ - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); } sqlite3VdbeResolveLabel(v, addrBreak); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ @@ -1693,22 +1697,22 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ } }else{ sqlite3ExprCode(pParse, p->pLimit, iLimit); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); + sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; pParse->nMem++; /* Allocate an extra register for limit+offset */ sqlite3ExprCode(pParse, p->pOffset, iOffset); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); VdbeComment((v, "OFFSET counter")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); VdbeComment((v, "LIMIT+OFFSET")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); sqlite3VdbeJumpHere(v, addr1); } @@ -1897,7 +1901,7 @@ static void generateWithRecursiveQuery( if( rc ) goto end_of_recursive_query; /* Find the next row in the Queue and output that row */ - addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); + addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v); /* Transfer the next row in Queue over to Current */ sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */ @@ -1913,7 +1917,10 @@ static void generateWithRecursiveQuery( codeOffset(v, regOffset, addrCont); selectInnerLoop(pParse, p, p->pEList, iCurrent, 0, 0, pDest, addrCont, addrBreak); - if( regLimit ) sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); + if( regLimit ){ + sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); + VdbeCoverage(v); + } sqlite3VdbeResolveLabel(v, addrCont); /* Execute the recursive SELECT taking the single row in Current as @@ -2073,7 +2080,7 @@ static int multiSelect( p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); + addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); } explainSetInteger(iSub2, pParse->iNextSelectId); @@ -2180,12 +2187,12 @@ static int multiSelect( iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); iStart = sqlite3VdbeCurrentAddr(v); selectInnerLoop(pParse, p, p->pEList, unionTab, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } @@ -2255,15 +2262,15 @@ static int multiSelect( iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); @@ -2370,10 +2377,10 @@ static int generateOutputSubroutine( */ if( regPrev ){ int j1, j2; - j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); + j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); + sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); @@ -2474,7 +2481,7 @@ static int generateOutputSubroutine( /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); + sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); } /* Generate the subroutine return @@ -2790,6 +2797,7 @@ static int multiSelectOrderBy( VdbeNoopComment((v, "eof-A subroutine")); addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); + VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); p->nSelectRow += pPrior->nSelectRow; } @@ -2803,7 +2811,7 @@ static int multiSelectOrderBy( }else{ VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); } @@ -2811,7 +2819,7 @@ static int multiSelectOrderBy( */ VdbeNoopComment((v, "A-lt-B subroutine")); addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* Generate code to handle the case of A==B @@ -2824,7 +2832,7 @@ static int multiSelectOrderBy( }else{ VdbeNoopComment((v, "A-eq-B subroutine")); addrAeqB = - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); } @@ -2835,14 +2843,14 @@ static int multiSelectOrderBy( if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); } - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); /* Implement the main merge loop */ @@ -2851,7 +2859,7 @@ static int multiSelectOrderBy( sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); /* Jump to the this point in order to terminate the query. */ @@ -4391,7 +4399,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ** values to an OP_Copy. */ if( regHit ){ - addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); } sqlite3ExprCacheClear(pParse); for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ @@ -4925,7 +4933,7 @@ int sqlite3Select( sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); - VdbeComment((v, "GROUP BY sort")); + VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); sAggInfo.useSortingIdx = 1; sqlite3ExprCacheClear(pParse); } @@ -4952,7 +4960,7 @@ int sqlite3Select( sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); + sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v); /* Generate code that runs whenever the GROUP BY changes. ** Changes in the GROUP BY are detected by the previous code @@ -4966,7 +4974,7 @@ int sqlite3Select( sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); VdbeComment((v, "output one row")); - sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); + sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v); VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); VdbeComment((v, "reset accumulator")); @@ -4983,6 +4991,7 @@ int sqlite3Select( */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); + VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); @@ -5010,7 +5019,7 @@ int sqlite3Select( sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeResolveLabel(v, addrOutputRow); addrOutputRow = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); + sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 51c864c5e2..5d2c87552c 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6117,7 +6117,8 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 -#define SQLITE_TESTCTRL_LAST 20 +#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 +#define SQLITE_TESTCTRL_LAST 21 /* ** CAPI3REF: SQLite Runtime Status diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 392517c8d7..5f5ce63d48 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2657,6 +2657,13 @@ struct Sqlite3Config { void(*xSqllog)(void*,sqlite3*,const char*, int); void *pSqllogArg; #endif +#ifdef SQLITE_VDBE_COVERAGE + /* The following callback (if not NULL) is invoked on every VDBE branch + ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. + */ + void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void *pVdbeBranchArg; /* 1st argument */ +#endif }; /* diff --git a/src/trigger.c b/src/trigger.c index cbc87abf45..dcbaf5d332 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -566,6 +566,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ int base; + static const int iLn = __LINE__+2; static const VdbeOpList dropTrigger[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String8, 0, 1, 0}, /* 1 */ @@ -580,7 +581,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); - base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); + base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn); sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3ChangeCookie(pParse, iDb); diff --git a/src/update.c b/src/update.c index 41ce7f0c77..4c45a4b40d 100644 --- a/src/update.c +++ b/src/update.c @@ -434,18 +434,23 @@ void sqlite3Update( if( aToOpen[iDataCur-iBaseCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); + VdbeCoverage(v); } labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); + VdbeCoverage(v); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); + VdbeCoverage(v); }else{ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, regOldRowid); + VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); } /* If the record number will change, set register regNewRowid to @@ -455,7 +460,7 @@ void sqlite3Update( assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); if( chngRowid ){ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } /* Compute the old pre-UPDATE content of the row being changed, if that @@ -536,8 +541,10 @@ void sqlite3Update( */ if( pPk ){ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); + VdbeCoverage(v); }else{ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); + VdbeCoverage(v); } /* If it did not delete it, the row-trigger may still have modified @@ -570,8 +577,10 @@ void sqlite3Update( if( bReplace || chngKey ){ if( pPk ){ j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); + VdbeCoverage(v); }else{ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); + VdbeCoverage(v); } } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); @@ -616,7 +625,7 @@ void sqlite3Update( /* Nothing to do at end-of-loop for a single-pass */ }else if( pPk ){ sqlite3VdbeResolveLabel(v, labelContinue); - sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); + sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); } @@ -745,7 +754,7 @@ static void updateVirtualTable( /* Generate code to scan the ephemeral table and call VUpdate. */ iReg = ++pParse->nMem; pParse->nMem += pTab->nCol+1; - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); + addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); for(i=0; inCol; i++){ @@ -755,7 +764,7 @@ static void updateVirtualTable( sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); diff --git a/src/vdbe.c b/src/vdbe.c index 5f046a63e2..002309bc3b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -107,6 +107,18 @@ int sqlite3_found_count = 0; # define UPDATE_MAX_BLOBSIZE(P) #endif +/* +** Invoke the VDBE coverage callback, if defined +*/ +#if !defined(SQLITE_VDBE_COVERAGE) +# define VdbeBranchTaken(I,M) +#else +# define VdbeBranchTaken(I,M) \ + if( sqlite3GlobalConfig.xVdbeBranch!=0 ){ \ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, \ + pOp->iSrcLine,(I),(M)); } +#endif + /* ** Convert the given register into a string if it isn't one ** already. Return non-zero if a malloc() fails. @@ -1638,6 +1650,7 @@ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); if( (pIn1->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; @@ -1891,12 +1904,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ - if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; - }else if( pOp->p5 & SQLITE_STOREP2 ){ + if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); + }else{ + VdbeBranchTaken((pOp->p5 & SQLITE_JUMPIFNULL)?2:3,4); + if( pOp->p5 & SQLITE_JUMPIFNULL ){ + pc = pOp->p2-1; + } } break; } @@ -1929,10 +1945,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ MemSetTypeFlag(pOut, MEM_Int); pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); - }else if( res ){ - pc = pOp->p2-1; + }else{ + VdbeBranchTaken(res!=0, 4); + if( res ){ + pc = pOp->p2-1; + } } - /* Undo any changes made by applyAffinity() to the input registers. */ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask); pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask); @@ -2029,11 +2047,11 @@ case OP_Compare: { */ case OP_Jump: { /* jump */ if( iCompare<0 ){ - pc = pOp->p1 - 1; + pc = pOp->p1 - 1; VdbeBranchTaken(0,3); }else if( iCompare==0 ){ - pc = pOp->p2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,3); }else{ - pc = pOp->p3 - 1; + pc = pOp->p3 - 1; VdbeBranchTaken(2,3); } break; } @@ -2137,6 +2155,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ */ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); + VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ @@ -2171,6 +2190,7 @@ case OP_IfNot: { /* jump, in1 */ #endif if( pOp->opcode==OP_IfNot ) c = !c; } + VdbeBranchTaken(c!=0, 2); if( c ){ pc = pOp->p2-1; } @@ -2184,6 +2204,7 @@ case OP_IfNot: { /* jump, in1 */ */ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; } @@ -2197,6 +2218,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ */ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; + VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } @@ -3474,7 +3496,7 @@ case OP_SeekGT: { /* jump, in3 */ if( (pIn3->flags & MEM_Real)==0 ){ /* If the P3 value cannot be converted into any kind of a number, ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); break; } @@ -3569,6 +3591,7 @@ case OP_SeekGT: { /* jump, in3 */ } } assert( pOp->p2>0 ); + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2 - 1; } @@ -3702,7 +3725,7 @@ case OP_Found: { /* jump, in3 */ ** conflict */ for(ii=0; iip2 - 1; + pc = pOp->p2 - 1; VdbeBranchTaken(1,2); break; } } @@ -3720,8 +3743,10 @@ case OP_Found: { /* jump, in3 */ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ + VdbeBranchTaken(alreadyExists!=0,2); if( alreadyExists ) pc = pOp->p2 - 1; }else{ + VdbeBranchTaken(alreadyExists==0,2); if( !alreadyExists ) pc = pOp->p2 - 1; } break; @@ -3764,6 +3789,7 @@ case OP_NotExists: { /* jump, in3 */ pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; + VdbeBranchTaken(res!=0,2); if( res!=0 ){ pc = pOp->p2 - 1; assert( pC->rowidIsValid==0 ); @@ -4138,6 +4164,7 @@ case OP_SorterCompare: { pIn3 = &aMem[pOp->p3]; nIgnore = pOp->p4.i; rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res); + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2-1; } @@ -4337,8 +4364,9 @@ case OP_Last: { /* jump */ pC->deferredMoveto = 0; pC->rowidIsValid = 0; pC->cacheStatus = CACHE_STALE; - if( pOp->p2>0 && res ){ - pc = pOp->p2 - 1; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) pc = pOp->p2 - 1; } break; } @@ -4395,6 +4423,7 @@ case OP_Rewind: { /* jump */ } pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2 - 1; } @@ -4485,6 +4514,7 @@ case OP_Next: /* jump */ rc = pOp->p4.xAdvance(pC->pCursor, &res); next_tail: pC->cacheStatus = CACHE_STALE; + VdbeBranchTaken(res==0,2); if( res==0 ){ pC->nullRow = 0; pc = pOp->p2 - 1; @@ -4710,6 +4740,7 @@ case OP_IdxGE: { /* jump */ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT ); res++; } + VdbeBranchTaken(res>0,2); if( res>0 ){ pc = pOp->p2 - 1 ; } @@ -5071,9 +5102,11 @@ case OP_RowSetRead: { /* jump, in1, out3 */ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); pc = pOp->p2 - 1; + VdbeBranchTaken(1,2); }else{ /* A value was pulled from the index */ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); + VdbeBranchTaken(0,2); } goto check_for_interrupt; } @@ -5125,6 +5158,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ exists = sqlite3RowSetTest(pIn1->u.pRowSet, (u8)(iSet>=0 ? iSet & 0xf : 0xff), pIn3->u.i); + VdbeBranchTaken(exists!=0,2); if( exists ){ pc = pOp->p2 - 1; break; @@ -5317,8 +5351,10 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ + VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ + VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; @@ -5367,6 +5403,7 @@ case OP_MemMax: { /* in2 */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken( pIn1->u.i>0, 2); if( pIn1->u.i>0 ){ pc = pOp->p2 - 1; } @@ -5384,6 +5421,7 @@ case OP_IfPos: { /* jump, in1 */ case OP_IfNeg: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i<0, 2); if( pIn1->u.i<0 ){ pc = pOp->p2 - 1; } @@ -5403,6 +5441,7 @@ case OP_IfZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); pIn1->u.i += pOp->p3; + VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ){ pc = pOp->p2 - 1; } @@ -5674,6 +5713,7 @@ case OP_IncrVacuum: { /* jump */ assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); + VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; @@ -5880,7 +5920,7 @@ case OP_VFilter: { /* jump */ if( rc==SQLITE_OK ){ res = pModule->xEof(pVtabCursor); } - + VdbeBranchTaken(res!=0,2); if( res ){ pc = pOp->p2 - 1; } @@ -5985,7 +6025,7 @@ case OP_VNext: { /* jump */ if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); } - + VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; diff --git a/src/vdbe.h b/src/vdbe.h index 620f2eaf72..f1f28cb1b5 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -68,6 +68,9 @@ struct VdbeOp { int cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif +#ifdef SQLITE_VDBE_COVERAGE + int iSrcLine; /* Source-code line that generated this opcode */ +#endif }; typedef struct VdbeOp VdbeOp; @@ -167,7 +170,7 @@ int sqlite3VdbeAddOp2(Vdbe*,int,int,int); int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); -int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); @@ -238,4 +241,14 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); # define VdbeModuleComment(X) #endif +/* Set the Opcode.iSrcline field of the previous opcode */ +#ifdef SQLITE_VDBE_COVERAGE + void sqlite3VdbeSetLineNumber(Vdbe*,int); +# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +#else +# define VdbeCoverage(v) +# define VdbeCoverageIf(v,x) +#endif + #endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index f7f1d5c288..89bb8975a5 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -173,6 +173,9 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ #ifdef VDBE_PROFILE pOp->cycles = 0; pOp->cnt = 0; +#endif +#ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; #endif return i; } @@ -535,7 +538,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. */ -int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ +int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){ @@ -563,6 +566,11 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOut->zComment = 0; #endif +#ifdef SQLITE_VDBE_COVERAGE + pOut->iSrcLine = iLineno+i; +#else + (void)iLineno; +#endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); @@ -851,6 +859,15 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ } #endif /* NDEBUG */ +#ifdef SQLITE_VDBE_COVERAGE +/* +** Set the value if the iSrcLine field for the previously coded instruction. +*/ +void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ + sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine; +} +#endif /* SQLITE_VDBE_COVERAGE */ + /* ** Return the opcode for a given address. If the address is -1, then ** return the most recently inserted opcode. diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 0fbc1ad477..4b34f2c295 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -133,14 +133,13 @@ int sqlite3_blob_open( ** which closes the b-tree cursor and (possibly) commits the ** transaction. */ + static const int iLn = __LINE__+4; static const VdbeOpList openBlob[] = { /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ - /* One of the following two instructions is replaced by an OP_Noop. */ {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ - {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */ {OP_Column, 0, 0, 1}, /* 6 */ @@ -265,7 +264,7 @@ int sqlite3_blob_open( pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); sqlite3VdbeChangeP5(v, 1); - sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); + sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); diff --git a/src/where.c b/src/where.c index c5bbeea0e1..15bcb1ebde 100644 --- a/src/where.c +++ b/src/where.c @@ -1708,12 +1708,12 @@ static void constructAutomaticIndex( VdbeComment((v, "for %s", pTable->zName)); /* Fill the automatic index with content */ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); regRecord = sqlite3GetTempReg(pParse); sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0); sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); @@ -2388,7 +2388,7 @@ static int codeEqualityTerm( bRev = !bRev; } iTab = pX->iTable; - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ @@ -2408,7 +2408,7 @@ static int codeEqualityTerm( pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); } pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; - sqlite3VdbeAddOp1(v, OP_IsNull, iReg); + sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v); }else{ pLevel->u.in.nIn = 0; } @@ -2502,11 +2502,11 @@ static int codeAllEqualityTerms( if( nSkip ){ int iIdxCur = pLevel->iIdxCur; - sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); + sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverage(v); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), - iIdxCur, 0, regBase, nSkip); + iIdxCur, 0, regBase, nSkip); VdbeCoverage(v); sqlite3VdbeJumpHere(v, j); for(j=0; jregReturn; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); + VdbeCoverage(v); VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); pLevel->op = OP_Goto; }else @@ -2819,6 +2820,7 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); + VdbeCoverage(v); pLoop->u.vtab.needFree = 0; for(j=0; ju.vtab.omitMask>>j)&1 ){ @@ -2850,8 +2852,9 @@ static Bitmask codeOneLoopStart( testcase( pTerm->wtFlags & TERM_VIRTUAL ); iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); + sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); + VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); VdbeComment((v, "pk")); @@ -2901,12 +2904,13 @@ static Bitmask codeOneLoopStart( testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); - VdbeComment((v, "pk")); + VdbeComment((v, "pk")); VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); + VdbeCoverage(v); } if( pEnd ){ Expr *pX; @@ -2934,6 +2938,7 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); + VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ @@ -3107,6 +3112,13 @@ static Bitmask codeOneLoopStart( testcase( op==OP_SeekLE ); testcase( op==OP_SeekLT ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_Rewind); + VdbeCoverageIf(v, op==OP_Last); + VdbeCoverageIf(v, op==OP_SeekGT); + VdbeCoverageIf(v, op==OP_SeekGE); + VdbeCoverageIf(v, op==OP_SeekLE); + VdbeCoverageIf(v, op==OP_SeekLT); /* Load the value for the inequality constraint at the end of the ** range (if any). @@ -3144,6 +3156,7 @@ static Bitmask codeOneLoopStart( testcase( op==OP_IdxLT ); testcase( op==OP_IdxLE ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + VdbeCoverage(v); } /* Seek the table cursor, if required */ @@ -3164,7 +3177,7 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); } sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, - iRowidReg, pPk->nKeyCol); + iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } /* Record the instruction used to terminate the loop. Disable @@ -3348,6 +3361,7 @@ static Bitmask codeOneLoopStart( regRowid, 0); sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeCurrentAddr(v)+2, r, iSet); + VdbeCoverage(v); } sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); @@ -3416,6 +3430,8 @@ static Bitmask codeOneLoopStart( pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); + VdbeCoverageIf(v, bRev); + VdbeCoverageIf(v, !bRev); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } @@ -5785,6 +5801,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); + VdbeCoverage(v); } if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; @@ -5793,6 +5810,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } sqlite3DbFree(db, pLevel->u.in.aInLoop); @@ -5805,7 +5823,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); } if( pLevel->iLeftJoin ){ - addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ From 552fd4544162c4ae28dda3ef29a62175c7bf630f Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 18 Feb 2014 01:07:38 +0000 Subject: [PATCH 18/66] Improvements to "NOT IN (SELECT ...)" processing. Only test for NULL values on the RHS on the first iteration, then remember the result. There has been logic to do this for year, but it didn't work right and ended up repeating the NULL test on every iteration. This inefficiency was found using the VDBE coverage testing tools. FossilOrigin-Name: 915f6f1c7aab54583729e60bdc1565f25ecc6f74 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/expr.c | 22 +++++++++------------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index d42c6f04ff..85cf3d05cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sperformance\senhancements\sfor\sINSERT\soperations,\sespecially\sINSERTs\non\stables\sthat\shave\sno\saffinity\scolumns\sor\sthat\shave\smany\sindices\sor\sINSERTs\nwith\scontent\scoming\sfrom\sa\sSELECT.\s\sAdd\sthe\sSQLITE_TESTCTRL_VDBE_COVERAGE\ntest\scontrol\sand\sthe\sSQLITE_VDBE_COVERAGE\scompile-time\soption\sused\sfor\smeasure\ncoverage\sof\sbranches\sin\sVDBE\sprograms. -D 2014-02-17T23:52:13.448 +C Improvements\sto\s"NOT\sIN\s(SELECT\s...)"\sprocessing.\s\sOnly\stest\sfor\sNULL\svalues\non\sthe\sRHS\son\sthe\sfirst\siteration,\sthen\sremember\sthe\sresult.\s\sThere\shas\sbeen\nlogic\sto\sdo\sthis\sfor\syear,\sbut\sit\sdidn't\swork\sright\sand\sended\sup\srepeating\nthe\sNULL\stest\son\severy\siteration.\s\sThis\sinefficiency\swas\sfound\susing\sthe\nVDBE\scoverage\stesting\stools. +D 2014-02-18T01:07:38.047 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7 -F src/expr.c d1a8ccbf7e4dac6198674d33853e8ed01072eca4 +F src/expr.c e908787e4728beefdf742db90666248f89b1da01 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 7adb3da235c8c162c84f05ef4ccf1cc463805d5f ce184c7bb16988641d37c908d9b3042456d4be3d -R 3842d7f2fc20472907a26e6db9a0b24a +P a72687699ba2af2e7383be7371d4121750c7e34f +R babb7ab4a8213aedecd107bc9c2410b3 U drh -Z d2a564f325f5059be0c19074b4cb10b9 +Z 3cb428699d451ff8a4012effde517352 diff --git a/manifest.uuid b/manifest.uuid index ac77c8b312..3fe9659239 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a72687699ba2af2e7383be7371d4121750c7e34f \ No newline at end of file +915f6f1c7aab54583729e60bdc1565f25ecc6f74 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 85354e5860..06fc1a54a8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1630,11 +1630,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } + sqlite3VdbeJumpHere(v, iAddr); } } } @@ -2004,7 +2004,7 @@ static void sqlite3ExprCodeIN( ** the presence of a NULL on the RHS makes a difference in the ** outcome. */ - int j1, j2, j3; + int j1, j2; /* First check to see if the LHS is contained in the RHS. If so, ** then the presence of NULLs in the RHS does not matter, so jump @@ -2019,19 +2019,15 @@ static void sqlite3ExprCodeIN( ** jump to destIfNull. If there are no NULLs in the RHS then ** jump to destIfFalse. */ - j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); - sqlite3VdbeJumpHere(v, j3); - sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); - sqlite3VdbeJumpHere(v, j2); - - /* Jump to the appropriate target depending on whether or not - ** the RHS contains a NULL - */ sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v); + j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull); sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull); + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); /* The OP_Found at the top of this branch jumps here when true, ** causing the overall IN expression evaluation to fall through. From 7d1761059b7818a98c5476e9e2040c78e28bc590 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 18 Feb 2014 03:07:12 +0000 Subject: [PATCH 19/66] Add VdbeCoverage() and VdbeCoverageIf() macros for improved VDBE coverage testing. FossilOrigin-Name: b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a --- manifest | 18 +++--- manifest.uuid | 2 +- src/expr.c | 164 ++++++++++++++++++------------------------------ src/select.c | 2 +- src/sqliteInt.h | 1 - src/where.c | 83 +++++++++++++++--------- 6 files changed, 124 insertions(+), 146 deletions(-) diff --git a/manifest b/manifest index 85cf3d05cb..4606d87635 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\s"NOT\sIN\s(SELECT\s...)"\sprocessing.\s\sOnly\stest\sfor\sNULL\svalues\non\sthe\sRHS\son\sthe\sfirst\siteration,\sthen\sremember\sthe\sresult.\s\sThere\shas\sbeen\nlogic\sto\sdo\sthis\sfor\syear,\sbut\sit\sdidn't\swork\sright\sand\sended\sup\srepeating\nthe\sNULL\stest\son\severy\siteration.\s\sThis\sinefficiency\swas\sfound\susing\sthe\nVDBE\scoverage\stesting\stools. -D 2014-02-18T01:07:38.047 +C Add\sVdbeCoverage()\sand\sVdbeCoverageIf()\smacros\sfor\simproved\sVDBE\scoverage\ntesting. +D 2014-02-18T03:07:12.342 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7 -F src/expr.c e908787e4728beefdf742db90666248f89b1da01 +F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846 F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 @@ -216,12 +216,12 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 618b53bd4553bd7a9ef95069396f12a8f28489e7 +F src/select.c 28bff39f9bc5ec618b0719fe3f7b4be9f88b6f02 F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 004bd50575a05eefba7228c2d0fee432a53200de +F src/sqliteInt.h 22111056d7d5c404fef783b13088ef87d98074d0 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 7825dce3f92d7c7de9329505deefe176cbd5ba43 +F src/where.c d622974f30d3347c7b71bfe49ce1f1e9b6570980 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a72687699ba2af2e7383be7371d4121750c7e34f -R babb7ab4a8213aedecd107bc9c2410b3 +P 915f6f1c7aab54583729e60bdc1565f25ecc6f74 +R d0043e1267f21a1ea521214d42169c3d U drh -Z 3cb428699d451ff8a4012effde517352 +Z f5a439caf79133298419241dae122f4e diff --git a/manifest.uuid b/manifest.uuid index 3fe9659239..2e856727c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -915f6f1c7aab54583729e60bdc1565f25ecc6f74 \ No newline at end of file +b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 06fc1a54a8..722a77db73 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1369,24 +1369,6 @@ int sqlite3ExprCanBeNull(const Expr *p){ } } -/* -** Generate an OP_IsNull instruction that tests register iReg and jumps -** to location iDest if the value in iReg is NULL. The value in iReg -** was computed by pExpr. If we can look at pExpr at compile-time and -** determine that it can never generate a NULL, then the OP_IsNull operation -** can be omitted. -*/ -void sqlite3ExprCodeIsNullJump( - Vdbe *v, /* The VDBE under construction */ - const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */ - int iReg, /* Test the value in this register for NULL */ - int iDest /* Jump here if the value is null */ -){ - if( sqlite3ExprCanBeNull(pExpr) ){ - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); VdbeCoverage(v); - } -} - /* ** Return TRUE if the given expression is a constant which would be ** unchanged by OP_Affinity with the affinity given in the second @@ -1486,9 +1468,7 @@ static int isCandidateForInOpt(Select *p){ */ int sqlite3CodeOnce(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - int addr = sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); - VdbeCoverage(v); - return addr; + return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); } /* @@ -1596,9 +1576,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ */ assert(v); if( iCol<0 ){ - int iAddr; - - iAddr = sqlite3CodeOnce(pParse); + int iAddr = sqlite3CodeOnce(pParse); + VdbeCoverage(v); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); eType = IN_INDEX_ROWID; @@ -1623,7 +1602,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None)) ){ - int iAddr = sqlite3CodeOnce(pParse); + int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); @@ -1723,7 +1702,7 @@ int sqlite3CodeSubselect( ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ - testAddr = sqlite3CodeOnce(pParse); + testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); } #ifndef SQLITE_OMIT_EXPLAIN @@ -2548,22 +2527,16 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_GE: case TK_NE: case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2); VdbeCoverage(v); + r1, r2, inReg, SQLITE_STOREP2); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -2577,7 +2550,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); - VdbeCoverage(v); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -2594,28 +2568,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_LSHIFT: case TK_RSHIFT: case TK_CONCAT: { - assert( TK_AND==OP_And ); - assert( TK_OR==OP_Or ); - assert( TK_PLUS==OP_Add ); - assert( TK_MINUS==OP_Subtract ); - assert( TK_REM==OP_Remainder ); - assert( TK_BITAND==OP_BitAnd ); - assert( TK_BITOR==OP_BitOr ); - assert( TK_SLASH==OP_Divide ); - assert( TK_LSHIFT==OP_ShiftLeft ); - assert( TK_RSHIFT==OP_ShiftRight ); - assert( TK_CONCAT==OP_Concat ); - testcase( op==TK_AND ); - testcase( op==TK_OR ); - testcase( op==TK_PLUS ); - testcase( op==TK_MINUS ); - testcase( op==TK_REM ); - testcase( op==TK_BITAND ); - testcase( op==TK_BITOR ); - testcase( op==TK_SLASH ); - testcase( op==TK_LSHIFT ); - testcase( op==TK_RSHIFT ); - testcase( op==TK_CONCAT ); + assert( TK_AND==OP_And ); testcase( op==TK_AND ); + assert( TK_OR==OP_Or ); testcase( op==TK_OR ); + assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); + assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); + assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); + assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); + assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); + assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH ); + assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); + assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT ); + assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); sqlite3VdbeAddOp3(v, op, r2, r1, target); @@ -2647,10 +2610,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ } case TK_BITNOT: case TK_NOT: { - assert( TK_BITNOT==OP_BitNot ); - assert( TK_NOT==OP_Not ); - testcase( op==TK_BITNOT ); - testcase( op==TK_NOT ); + assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT ); + assert( TK_NOT==OP_Not ); testcase( op==TK_NOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); inReg = target; @@ -2660,14 +2621,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_ISNULL: case TK_NOTNULL: { int addr; - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); - addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, op, r1); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); break; @@ -2857,8 +2818,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ r3 = sqlite3GetTempReg(pParse); r4 = sqlite3GetTempReg(pParse); codeCompare(pParse, pLeft, pRight, OP_Ge, - r1, r2, r3, SQLITE_STOREP2); - VdbeCoverage(v); + r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v); pLItem++; pRight = pLItem->pExpr; sqlite3ReleaseTempReg(pParse, regFree2); @@ -3605,23 +3565,17 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_GE: case TK_NE: case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); VdbeCoverage(v); + r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3634,19 +3588,21 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v); + r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, op, r1, dest); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; } @@ -3765,17 +3721,17 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_GE: case TK_NE: case TK_EQ: { - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); VdbeCoverage(v); + r1, r2, dest, jumpIfNull); + assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); + assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); + assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); + assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); + assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); + assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); testcase( regFree1==0 ); testcase( regFree2==0 ); break; @@ -3788,17 +3744,19 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v); + r1, r2, dest, SQLITE_NULLEQ); + VdbeCoverageIf(v, op==TK_EQ); + VdbeCoverageIf(v, op==TK_NE); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); + testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); testcase( regFree1==0 ); break; } diff --git a/src/select.c b/src/select.c index fcd8b7ea0b..93947d56b2 100644 --- a/src/select.c +++ b/src/select.c @@ -4595,7 +4595,7 @@ int sqlite3Select( /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ - onceAddr = sqlite3CodeOnce(pParse); + onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); }else{ VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5f5ce63d48..038215a055 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3087,7 +3087,6 @@ int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); -void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); diff --git a/src/where.c b/src/where.c index 15bcb1ebde..d606ba4c18 100644 --- a/src/where.c +++ b/src/where.c @@ -1601,7 +1601,7 @@ static void constructAutomaticIndex( ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); + addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ @@ -2388,7 +2388,9 @@ static int codeEqualityTerm( bRev = !bRev; } iTab = pX->iTable; - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); + VdbeCoverageIf(v, bRev); + VdbeCoverageIf(v, !bRev); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ @@ -2502,11 +2504,15 @@ static int codeAllEqualityTerms( if( nSkip ){ int iIdxCur = pLevel->iIdxCur; - sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverage(v); + sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), - iIdxCur, 0, regBase, nSkip); VdbeCoverage(v); + iIdxCur, 0, regBase, nSkip); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); sqlite3VdbeJumpHere(v, j); for(j=0; jeOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ Expr *pRight = pTerm->pExpr->pRight; - sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk); + if( sqlite3ExprCanBeNull(pRight) ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); + VdbeCoverage(v); + } if( zAff ){ if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){ zAff[j] = SQLITE_AFF_NONE; @@ -2904,13 +2913,18 @@ static Bitmask codeOneLoopStart( testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); - VdbeComment((v, "pk")); VdbeCoverage(v); + VdbeComment((v, "pk")); + VdbeCoverageIf(v, pX->op==TK_GT); + VdbeCoverageIf(v, pX->op==TK_LE); + VdbeCoverageIf(v, pX->op==TK_LT); + VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); - VdbeCoverage(v); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); } if( pEnd ){ Expr *pX; @@ -2938,7 +2952,10 @@ static Bitmask codeOneLoopStart( sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); - VdbeCoverage(v); + VdbeCoverageIf(v, testOp==OP_Le); + VdbeCoverageIf(v, testOp==OP_Lt); + VdbeCoverageIf(v, testOp==OP_Ge); + VdbeCoverageIf(v, testOp==OP_Gt); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ @@ -3080,8 +3097,11 @@ static Bitmask codeOneLoopStart( if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); + if( (pRangeStart->wtFlags & TERM_VNULL)==0 + && sqlite3ExprCanBeNull(pRight) + ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); + VdbeCoverage(v); } if( zStartAff ){ if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){ @@ -3105,20 +3125,14 @@ static Bitmask codeOneLoopStart( codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); - testcase( op==OP_Rewind ); - testcase( op==OP_Last ); - testcase( op==OP_SeekGT ); - testcase( op==OP_SeekGE ); - testcase( op==OP_SeekLE ); - testcase( op==OP_SeekLT ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); VdbeCoverage(v); - VdbeCoverageIf(v, op==OP_Rewind); - VdbeCoverageIf(v, op==OP_Last); - VdbeCoverageIf(v, op==OP_SeekGT); - VdbeCoverageIf(v, op==OP_SeekGE); - VdbeCoverageIf(v, op==OP_SeekLE); - VdbeCoverageIf(v, op==OP_SeekLT); + VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); + VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); + VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); + VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); + VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); /* Load the value for the inequality constraint at the end of the ** range (if any). @@ -3128,8 +3142,11 @@ static Bitmask codeOneLoopStart( Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 + && sqlite3ExprCanBeNull(pRight) + ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); + VdbeCoverage(v); } if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff) @@ -3151,12 +3168,11 @@ static Bitmask codeOneLoopStart( /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ op = aEndOp[bRev*2 + endEq]; - testcase( op==OP_IdxGT ); - testcase( op==OP_IdxGE ); - testcase( op==OP_IdxLT ); - testcase( op==OP_IdxLE ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - VdbeCoverage(v); + testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); + testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); + testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } /* Seek the table cursor, if required */ @@ -3430,8 +3446,8 @@ static Bitmask codeOneLoopStart( pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); - VdbeCoverageIf(v, bRev); - VdbeCoverageIf(v, !bRev); + VdbeCoverageIf(v, bRev==0); + VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } @@ -5802,6 +5818,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); VdbeCoverage(v); + VdbeCoverageIf(v, pLevel->op==OP_Next); + VdbeCoverageIf(v, pLevel->op==OP_Prev); + VdbeCoverageIf(v, pLevel->op==OP_VNext); } if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; @@ -5811,6 +5830,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); VdbeCoverage(v); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } sqlite3DbFree(db, pLevel->u.in.aInLoop); From f4345e40a03a4d68dcab0556669573135ebbfd9b Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 18 Feb 2014 11:31:59 +0000 Subject: [PATCH 20/66] Fix VDBE branch accounting on comparison operators. FossilOrigin-Name: b287520c9226f7a9fab98142f5c207bfe959cd7e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 4606d87635..03e22ae49a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sVdbeCoverage()\sand\sVdbeCoverageIf()\smacros\sfor\simproved\sVDBE\scoverage\ntesting. -D 2014-02-18T03:07:12.342 +C Fix\sVDBE\sbranch\saccounting\son\scomparison\soperators. +D 2014-02-18T11:31:59.914 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,7 +277,7 @@ F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 392f03b25152eb44565a78b8b809743c97e5852b +F src/vdbe.c 6e3d5d4c68076c09724c74bc5c39985a204e55a0 F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 915f6f1c7aab54583729e60bdc1565f25ecc6f74 -R d0043e1267f21a1ea521214d42169c3d +P b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a +R ac3bce6c9f7bb42059d2e404010fd2bc U drh -Z f5a439caf79133298419241dae122f4e +Z fa645aebf1d7fefe7cb4cc20303fc9e2 diff --git a/manifest.uuid b/manifest.uuid index 2e856727c0..5eb83b599d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a \ No newline at end of file +b287520c9226f7a9fab98142f5c207bfe959cd7e \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 002309bc3b..966d0431d0 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1909,7 +1909,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ MemSetTypeFlag(pOut, MEM_Null); REGISTER_TRACE(pOp->p2, pOut); }else{ - VdbeBranchTaken((pOp->p5 & SQLITE_JUMPIFNULL)?2:3,4); + VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ pc = pOp->p2-1; } @@ -1946,7 +1946,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ pOut->u.i = res; REGISTER_TRACE(pOp->p2, pOut); }else{ - VdbeBranchTaken(res!=0, 4); + VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res ){ pc = pOp->p2-1; } From 49d9ba6354fea331413a5fd21af0e25d63edaaae Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 19 Feb 2014 00:53:46 +0000 Subject: [PATCH 21/66] Tweaks in support of VDBE branch test coverage. FossilOrigin-Name: b97825646996792d0a67b83f135658027c8569ca --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/alter.c | 3 ++- src/delete.c | 6 ++++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 03e22ae49a..21d08689e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sVDBE\sbranch\saccounting\son\scomparison\soperators. -D 2014-02-18T11:31:59.914 +C Tweaks\sin\ssupport\sof\sVDBE\sbranch\stest\scoverage. +D 2014-02-19T00:53:46.757 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 829d67a359b7c5d37120be994af2c0eac730070c +F src/alter.c 1a630c6579b05d93530d4289182a4e8449e722f2 F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 @@ -171,7 +171,7 @@ F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7 +F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280 F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b92d31a97d5fe4606d9ae1393c7f3e052f46bf5a -R ac3bce6c9f7bb42059d2e404010fd2bc +P b287520c9226f7a9fab98142f5c207bfe959cd7e +R db3eaca30cb3f9a4bcbd920e67b64796 U drh -Z fa645aebf1d7fefe7cb4cc20303fc9e2 +Z 6e0e07262b8661a34d8eb8aae8107f91 diff --git a/manifest.uuid b/manifest.uuid index 5eb83b599d..b1881b184d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b287520c9226f7a9fab98142f5c207bfe959cd7e \ No newline at end of file +b97825646996792d0a67b83f135658027c8569ca \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index b8bf20cfd9..7afce403dc 100644 --- a/src/alter.c +++ b/src/alter.c @@ -604,7 +604,8 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); VdbeCoverage(v); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); diff --git a/src/delete.c b/src/delete.c index 3fa41c53f0..79e83cae52 100644 --- a/src/delete.c +++ b/src/delete.c @@ -613,7 +613,8 @@ void sqlite3GenerateRowDelete( opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; if( !bNoSeek ){ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); - VdbeCoverage(v); + VdbeCoverageIf(v, opSeek==OP_NotExists); + VdbeCoverageIf(v, opSeek==OP_NotFound); } /* If there are any triggers to fire, allocate a range of registers to @@ -656,7 +657,8 @@ void sqlite3GenerateRowDelete( */ if( addrStart Date: Wed, 19 Feb 2014 01:31:02 +0000 Subject: [PATCH 22/66] Make sure a multi-row VALUES clause works correctly in a compound SELECT. FossilOrigin-Name: 85b355cfb40e8dbeb171980204ffad897184063f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/parse.y | 16 ++++++++++++---- test/select4.test | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 21d08689e4..f819451ca7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tweaks\sin\ssupport\sof\sVDBE\sbranch\stest\scoverage. -D 2014-02-19T00:53:46.757 +C Make\ssure\sa\smulti-row\sVALUES\sclause\sworks\scorrectly\sin\sa\scompound\sSELECT. +D 2014-02-19T01:31:02.841 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -206,7 +206,7 @@ F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5 F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 -F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb +F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0 F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c @@ -777,7 +777,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 F test/select1.test fc2a61f226a649393664ad54bc5376631801517c F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 -F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d +F test/select4.test 8c5a60d439e2df824aed56223566877a883c5c84 F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2 F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b287520c9226f7a9fab98142f5c207bfe959cd7e -R db3eaca30cb3f9a4bcbd920e67b64796 +P b97825646996792d0a67b83f135658027c8569ca +R e0d510b78dfc0d79538a4222d29a9363 U drh -Z 6e0e07262b8661a34d8eb8aae8107f91 +Z f971c993fbd0c297278e42fafe3ac2dc diff --git a/manifest.uuid b/manifest.uuid index b1881b184d..7a4f65bb4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b97825646996792d0a67b83f135658027c8569ca \ No newline at end of file +85b355cfb40e8dbeb171980204ffad897184063f \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 373c126a25..ad9bedf0b4 100644 --- a/src/parse.y +++ b/src/parse.y @@ -437,14 +437,22 @@ select(A) ::= with(W) selectnowith(X). { selectnowith(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { - if( Z ){ - Z->op = (u8)Y; - Z->pPrior = X; + Select *pRhs = Z; + if( pRhs && pRhs->pPrior ){ + SrcList *pFrom; + Token x; + x.n = 0; + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); + } + if( pRhs ){ + pRhs->op = (u8)Y; + pRhs->pPrior = X; if( Y!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, X); } - A = Z; + A = pRhs; } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP;} diff --git a/test/select4.test b/test/select4.test index e205b37a4f..8fc200d434 100644 --- a/test/select4.test +++ b/test/select4.test @@ -824,4 +824,40 @@ do_test select4-13.1 { } } {1 2} +# 2014-02-18: Make sure compound SELECTs work with VALUES clauses +# +do_execsql_test select4-14.1 { + CREATE TABLE t14(a,b,c); + INSERT INTO t14 VALUES(1,2,3),(4,5,6); + SELECT * FROM t14 INTERSECT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3} +do_execsql_test select4-14.2 { + SELECT * FROM t14 INTERSECT VALUES(1,2,3); +} {1 2 3} +do_execsql_test select4-14.3 { + SELECT * FROM t14 + UNION VALUES(3,2,1),(2,3,1),(1,2,3),(7,8,9),(4,5,6) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 2 3 1 3 2 1 4 5 6 7 8 9} +do_execsql_test select4-14.4 { + SELECT * FROM t14 + UNION VALUES(3,2,1) + UNION SELECT * FROM t14 ORDER BY 1, 2, 3 +} {1 2 3 3 2 1 4 5 6} +do_execsql_test select4-14.5 { + SELECT * FROM t14 EXCEPT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {4 5 6} +do_execsql_test select4-14.6 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) +} {4 5 6} +do_execsql_test select4-14.7 { + SELECT * FROM t14 EXCEPT VALUES(1,2,3) EXCEPT VALUES(4,5,6) +} {} +do_execsql_test select4-14.8 { + SELECT * FROM t14 EXCEPT VALUES('a','b','c') EXCEPT VALUES(4,5,6) +} {1 2 3} +do_execsql_test select4-14.9 { + SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); +} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3} + finish_test From 3d77dee9356115e817158168ad252592304deb1f Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 19 Feb 2014 14:20:49 +0000 Subject: [PATCH 23/66] Add the SQLITE_NOTNULL P5 code for comparison operations - really a composite of SQLITE_NULLEQ and SQLITE_JUMPIFNULL. This flag indicates that NULL operands are not possible and raises and assert() if NULL operands are seen. Also omit an unnecessary scan of the sqlite_sequence table when writing into an AUTOINCREMENT table. FossilOrigin-Name: d2c047f304848e49864ed8c216b48fd671fa3916 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/alter.c | 2 +- src/fkey.c | 1 + src/insert.c | 18 +++++++----------- src/sqliteInt.h | 6 ++++++ src/vdbe.c | 2 +- 7 files changed, 27 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index f819451ca7..9293877a3f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sa\smulti-row\sVALUES\sclause\sworks\scorrectly\sin\sa\scompound\sSELECT. -D 2014-02-19T01:31:02.841 +C Add\sthe\sSQLITE_NOTNULL\sP5\scode\sfor\scomparison\soperations\s-\sreally\sa\scomposite\nof\sSQLITE_NULLEQ\sand\sSQLITE_JUMPIFNULL.\s\sThis\sflag\sindicates\sthat\sNULL\soperands\nare\snot\spossible\sand\sraises\sand\sassert()\sif\sNULL\soperands\sare\sseen.\nAlso\somit\san\sunnecessary\sscan\sof\sthe\ssqlite_sequence\stable\swhen\swriting\ninto\san\sAUTOINCREMENT\stable. +D 2014-02-19T14:20:49.685 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 1a630c6579b05d93530d4289182a4e8449e722f2 +F src/alter.c 75a0b861e98968c0f3b27606e7d9462228d04827 F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 @@ -174,13 +174,13 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280 F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846 +F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5 F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 5d5e1d78f74804739b424c92346bdc26c146dfa4 +F src/insert.c 429adb670176eb5471be9867ff7c88a190b23cb3 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 22111056d7d5c404fef783b13088ef87d98074d0 +F src/sqliteInt.h 616f8a225bfd6cf09f7f5906c7b91b29a3591b34 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -277,7 +277,7 @@ F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 6e3d5d4c68076c09724c74bc5c39985a204e55a0 +F src/vdbe.c 16c220ae23bbd6755f66bb32eb4c8c0fadda6c8f F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b97825646996792d0a67b83f135658027c8569ca -R e0d510b78dfc0d79538a4222d29a9363 +P 85b355cfb40e8dbeb171980204ffad897184063f +R 6054409536840db43eb58dd38378a2df U drh -Z f971c993fbd0c297278e42fafe3ac2dc +Z 59cedb1de1bf2e430d47d82062cddf85 diff --git a/manifest.uuid b/manifest.uuid index 7a4f65bb4a..30fa60d6f1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85b355cfb40e8dbeb171980204ffad897184063f \ No newline at end of file +d2c047f304848e49864ed8c216b48fd671fa3916 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 7afce403dc..e9f06a9f72 100644 --- a/src/alter.c +++ b/src/alter.c @@ -605,7 +605,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); sqlite3VdbeJumpHere(v, j1); sqlite3ReleaseTempReg(pParse, r1); diff --git a/src/fkey.c b/src/fkey.c index c94f969238..336256e0f3 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -369,6 +369,7 @@ static void fkLookupParent( ** increment the constraint-counter. */ if( pTab==pFKey->pFrom && nIncr==1 ){ sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); } sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); diff --git a/src/insert.c b/src/insert.c index 64786ee112..7aa9329b8d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -304,7 +304,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){ assert( v ); for(p = pParse->pAinc; p; p = p->pNext){ Db *pDb = &db->aDb[p->iDb]; - int j1, j2, j3, j4, j5; + int j1; int iRec; int memId = p->regCtr; @@ -312,17 +312,8 @@ void sqlite3AutoincrementEnd(Parse *pParse){ assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); - j2 = sqlite3VdbeAddOp0(v, OP_Rewind); VdbeCoverage(v); - j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); - j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Next, 0, j3); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, j2); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - j5 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, j4); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeJumpHere(v, j5); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); @@ -1275,6 +1266,7 @@ void sqlite3GenerateConstraintChecks( ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } @@ -1446,6 +1438,7 @@ void sqlite3GenerateConstraintChecks( ** is different from old-rowid */ if( isUpdate ){ sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } }else{ @@ -1481,7 +1474,10 @@ void sqlite3GenerateConstraintChecks( } sqlite3VdbeAddOp4(v, op, regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ - ); VdbeCoverage(v); + ); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + VdbeCoverageIf(v, op==OP_Eq); + VdbeCoverageIf(v, op==OP_Ne); } } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 038215a055..a6663ff679 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1314,10 +1314,16 @@ struct CollSeq { /* ** Additional bit values that can be ORed with an affinity without ** changing the affinity. +** +** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. +** It causes an assert() to fire if either operand to a comparison +** operator is NULL. It is added to certain comparison operators to +** prove that the operands are always NOT NULL. */ #define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ #define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ +#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in diff --git a/src/vdbe.c b/src/vdbe.c index 966d0431d0..1e9e31116f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1891,6 +1891,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); + assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); if( (flags1&MEM_Null)!=0 && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 @@ -4833,7 +4834,6 @@ case OP_Clear: { nChange = 0; assert( p->readOnly==0 ); - assert( pOp->p1!=1 ); assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) From 5655c549aa202c957cf3610d9faa99aac5996475 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 19 Feb 2014 19:14:34 +0000 Subject: [PATCH 24/66] Add the VdbeCoverageNeverTaken() macro, and comments that better describe how the VDBE branch coverage measurement works. Add some tags to provide 100% VDBE branch coverage. FossilOrigin-Name: c1e94169dd8eb80b4d18c73be9f81585330d11ad --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/pragma.c | 1 + src/update.c | 5 ++--- src/vdbe.c | 26 +++++++++++++++++++++----- src/vdbe.h | 27 ++++++++++++++++++++++++++- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 9293877a3f..2b91bf1936 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_NOTNULL\sP5\scode\sfor\scomparison\soperations\s-\sreally\sa\scomposite\nof\sSQLITE_NULLEQ\sand\sSQLITE_JUMPIFNULL.\s\sThis\sflag\sindicates\sthat\sNULL\soperands\nare\snot\spossible\sand\sraises\sand\sassert()\sif\sNULL\soperands\sare\sseen.\nAlso\somit\san\sunnecessary\sscan\sof\sthe\ssqlite_sequence\stable\swhen\swriting\ninto\san\sAUTOINCREMENT\stable. -D 2014-02-19T14:20:49.685 +C Add\sthe\sVdbeCoverageNeverTaken()\smacro,\sand\scomments\sthat\sbetter\sdescribe\show\nthe\sVDBE\sbranch\scoverage\smeasurement\sworks.\s\sAdd\ssome\stags\sto\sprovide\s100%\nVDBE\sbranch\scoverage. +D 2014-02-19T19:14:34.983 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -210,7 +210,7 @@ F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0 F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c -F src/pragma.c 2635d6bf8b54003ebefd773df2f50258cece2bec +F src/pragma.c a46ee83671f5c95f53d2ceeb5e1a818d7b1df99a F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece @@ -273,12 +273,12 @@ F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc -F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97 +F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 16c220ae23bbd6755f66bb32eb4c8c0fadda6c8f -F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320 +F src/vdbe.c b82ffb8ca4a7b163f0d4450dce353259cbb12240 +F src/vdbe.h 6c703ccef97f4504bd0d79cc09180185a60ae8ad F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 F src/vdbeaux.c 0e01d6fda149c689039caadb8c89b20abb58e21d @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 85b355cfb40e8dbeb171980204ffad897184063f -R 6054409536840db43eb58dd38378a2df +P d2c047f304848e49864ed8c216b48fd671fa3916 +R 290109175fc6aecf9e37def55ff4d8d1 U drh -Z 59cedb1de1bf2e430d47d82062cddf85 +Z 8351cefc3ed205778666dc9ef6e2430a diff --git a/manifest.uuid b/manifest.uuid index 30fa60d6f1..a6ed2e8a06 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2c047f304848e49864ed8c216b48fd671fa3916 \ No newline at end of file +c1e94169dd8eb80b4d18c73be9f81585330d11ad \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index a586370b8d..a211633f23 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1942,6 +1942,7 @@ void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); diff --git a/src/update.c b/src/update.c index 4c45a4b40d..4138749f80 100644 --- a/src/update.c +++ b/src/update.c @@ -434,7 +434,7 @@ void sqlite3Update( if( aToOpen[iDataCur-iBaseCur] ){ assert( pPk!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); - VdbeCoverage(v); + VdbeCoverageNeverTaken(v); } labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); @@ -577,11 +577,10 @@ void sqlite3Update( if( bReplace || chngKey ){ if( pPk ){ j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); - VdbeCoverage(v); }else{ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); - VdbeCoverage(v); } + VdbeCoverageNeverTaken(v); } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx); diff --git a/src/vdbe.c b/src/vdbe.c index 1e9e31116f..2b3396223c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -108,15 +108,31 @@ int sqlite3_found_count = 0; #endif /* -** Invoke the VDBE coverage callback, if defined +** Invoke the VDBE coverage callback, if that callback is defined. This +** feature is used for test suite validation only and does not appear an +** production builds. +** +** M is an integer, 2 or 3, that indices how many different ways the +** branch can go. It is usually 2. "I" is the direction the branch +** goes. 0 means falls through. 1 means branch is taken. 2 means the +** second alternative branch is taken. */ #if !defined(SQLITE_VDBE_COVERAGE) # define VdbeBranchTaken(I,M) #else -# define VdbeBranchTaken(I,M) \ - if( sqlite3GlobalConfig.xVdbeBranch!=0 ){ \ - sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, \ - pOp->iSrcLine,(I),(M)); } +# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) + static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ + if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ + M = iSrcLine; + /* Assert the truth of VdbeCoverageAlwaysTaken() and + ** VdbeCoverageNeverTaken() */ + assert( (M & I)==I ); + }else{ + if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, + iSrcLine,I,M); + } + } #endif /* diff --git a/src/vdbe.h b/src/vdbe.h index f1f28cb1b5..44cd9123aa 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -241,14 +241,39 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); # define VdbeModuleComment(X) #endif -/* Set the Opcode.iSrcline field of the previous opcode */ +/* +** The VdbeCoverage macros are used to set a coverage testing point +** for VDBE branch instructions. The coverage testing points are line +** numbers in the sqlite3.c source file. VDBE branch coverage testing +** only works with an amalagmation build. That's ok since a VDBE branch +** coverage build designed for testing the test suite only. No application +** should ever ship with VDBE branch coverage measuring turned on. +** +** VdbeCoverage(v) // Mark the previously coded instruction +** // as a branch +** +** VdbeCoverageIf(v, conditional) // Mark previous if conditional true +** +** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken +** +** VdbeCoverageNeverTaken(v) // Previous branch is never taken +** +** Every VDBE branch operation must be tagged with one of the macros above. +** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and +** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() +** routine in vdbe.c, alerting the developer to the missed tag. +*/ #ifdef SQLITE_VDBE_COVERAGE void sqlite3VdbeSetLineNumber(Vdbe*,int); # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) +# define VdbeCoverageAlwaysTaken(v) +# define VdbeCoverageNeverTaken(v) #endif #endif From 4300c1ae3b5464e2a11c20eec3cf1139f161799a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 20 Feb 2014 19:23:15 +0000 Subject: [PATCH 25/66] Make sure that the difference between two string pointers is passed into sqlite3_mprintf() as type "int". FossilOrigin-Name: d5d973fedcf5a2eea219f10e11ba3dacdd0593f0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/alter.c | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 2b91bf1936..e726d97238 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sVdbeCoverageNeverTaken()\smacro,\sand\scomments\sthat\sbetter\sdescribe\show\nthe\sVDBE\sbranch\scoverage\smeasurement\sworks.\s\sAdd\ssome\stags\sto\sprovide\s100%\nVDBE\sbranch\scoverage. -D 2014-02-19T19:14:34.983 +C Make\ssure\sthat\sthe\sdifference\sbetween\stwo\sstring\spointers\sis\spassed\sinto\nsqlite3_mprintf()\sas\stype\s"int". +D 2014-02-20T19:23:15.279 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 75a0b861e98968c0f3b27606e7d9462228d04827 +F src/alter.c 5d99edbac5bc416032772b723ee30182ee6e5de0 F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d2c047f304848e49864ed8c216b48fd671fa3916 -R 290109175fc6aecf9e37def55ff4d8d1 +P c1e94169dd8eb80b4d18c73be9f81585330d11ad +R 09bf9547df25315bb17290d72fbff966 U drh -Z 8351cefc3ed205778666dc9ef6e2430a +Z 6fdf325f579b53033b4ff3e16a9cc3b3 diff --git a/manifest.uuid b/manifest.uuid index a6ed2e8a06..1b31602821 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c1e94169dd8eb80b4d18c73be9f81585330d11ad \ No newline at end of file +d5d973fedcf5a2eea219f10e11ba3dacdd0593f0 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index e9f06a9f72..1a83e570db 100644 --- a/src/alter.c +++ b/src/alter.c @@ -77,8 +77,8 @@ static void renameTableFunc( assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } @@ -130,7 +130,7 @@ static void renameParentFunc( sqlite3Dequote(zParent); if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", - (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew + (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew ); sqlite3DbFree(db, zOutput); zOutput = zOut; @@ -216,8 +216,8 @@ static void renameTriggerFunc( /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), + zSql, zTableName, tname.z+tname.n); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } From 06280ee58293795b94f03b830d83db3d72e901cc Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 20 Feb 2014 19:32:38 +0000 Subject: [PATCH 26/66] Fix a harmless shadowed-variable warning. FossilOrigin-Name: 824029090d1c4c4c608f67dd197961eba29c039d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index e726d97238..260e627beb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\sthe\sdifference\sbetween\stwo\sstring\spointers\sis\spassed\sinto\nsqlite3_mprintf()\sas\stype\s"int". -D 2014-02-20T19:23:15.279 +C Fix\sa\sharmless\sshadowed-variable\swarning. +D 2014-02-20T19:32:38.618 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -180,7 +180,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 429adb670176eb5471be9867ff7c88a190b23cb3 +F src/insert.c d3d1164299faa53b5347f8ff676d3787537fa9e5 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c1e94169dd8eb80b4d18c73be9f81585330d11ad -R 09bf9547df25315bb17290d72fbff966 +P d5d973fedcf5a2eea219f10e11ba3dacdd0593f0 +R 76d0c1c651bb2a560b0883244ae73572 U drh -Z 6fdf325f579b53033b4ff3e16a9cc3b3 +Z 5adb32a47d049f70cd5fc6a5768d989a diff --git a/manifest.uuid b/manifest.uuid index 1b31602821..d04a194920 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5d973fedcf5a2eea219f10e11ba3dacdd0593f0 \ No newline at end of file +824029090d1c4c4c608f67dd197961eba29c039d \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7aa9329b8d..1d29da3092 100644 --- a/src/insert.c +++ b/src/insert.c @@ -677,18 +677,18 @@ void sqlite3Insert( */ int regRec; /* Register to hold packed record */ int regTempRowid; /* Register to hold temp table ROWID */ - int addrTop; /* Label "L" */ + int addrL; /* Label "L" */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regTempRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); + addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - sqlite3VdbeJumpHere(v, addrTop); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL); + sqlite3VdbeJumpHere(v, addrL); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regTempRowid); } From 4d87aaed5668ffa435da8e81631f3331fe94d3fe Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 20 Feb 2014 19:42:00 +0000 Subject: [PATCH 27/66] Fix the text of a comment used to generate VDBE opcode documentation so that it omits symbols that can be mistaken for a hyperlink by the parser. FossilOrigin-Name: b46d4e8923e6e367412bba7aeac07039bbcbabd1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 260e627beb..419633cc87 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\sshadowed-variable\swarning. -D 2014-02-20T19:32:38.618 +C Fix\sthe\stext\sof\sa\scomment\sused\sto\sgenerate\sVDBE\sopcode\sdocumentation\sso\sthat\nit\somits\ssymbols\sthat\scan\sbe\smistaken\sfor\sa\shyperlink\sby\sthe\sparser. +D 2014-02-20T19:42:00.531 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,7 +277,7 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c b82ffb8ca4a7b163f0d4450dce353259cbb12240 +F src/vdbe.c c5ff7b384ed108be747220d4c47fcea6a36b062b F src/vdbe.h 6c703ccef97f4504bd0d79cc09180185a60ae8ad F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d5d973fedcf5a2eea219f10e11ba3dacdd0593f0 -R 76d0c1c651bb2a560b0883244ae73572 +P 824029090d1c4c4c608f67dd197961eba29c039d +R 819e2e4df777a2f59b5f5445b2831eb5 U drh -Z 5adb32a47d049f70cd5fc6a5768d989a +Z c4d587ace814e560a6dc901fdec24d15 diff --git a/manifest.uuid b/manifest.uuid index d04a194920..32d13dfb30 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -824029090d1c4c4c608f67dd197961eba29c039d \ No newline at end of file +b46d4e8923e6e367412bba7aeac07039bbcbabd1 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 2b3396223c..2253af4719 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1175,7 +1175,7 @@ case OP_SCopy: { /* out2 */ ** The registers P1 through P1+P2-1 contain a single row of ** results. This opcode causes the sqlite3_step() call to terminate ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the r[P1]..r[P1+P2-1] values as +** structure to provide access to the r(P1)..r(P1+P2-1) values as ** the result row. */ case OP_ResultRow: { From 15ab9418d9b220a826c033847e074529c2b22dd0 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Feb 2014 14:24:01 +0000 Subject: [PATCH 28/66] Remove an unused variable from the VDBE_PROFILE compile-time option. Keep the opcode count in an u32 instead of an int. FossilOrigin-Name: 4df0ac9023d9261145a4425a508ba009a10276fc --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 6 ------ src/vdbe.h | 2 +- src/vdbeaux.c | 4 +++- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 419633cc87..349983f4f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\stext\sof\sa\scomment\sused\sto\sgenerate\sVDBE\sopcode\sdocumentation\sso\sthat\nit\somits\ssymbols\sthat\scan\sbe\smistaken\sfor\sa\shyperlink\sby\sthe\sparser. -D 2014-02-20T19:42:00.531 +C Remove\san\sunused\svariable\sfrom\sthe\sVDBE_PROFILE\scompile-time\soption.\s\sKeep\sthe\nopcode\scount\sin\san\su32\sinstead\sof\san\sint. +D 2014-02-24T14:24:01.038 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,11 +277,11 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c c5ff7b384ed108be747220d4c47fcea6a36b062b -F src/vdbe.h 6c703ccef97f4504bd0d79cc09180185a60ae8ad +F src/vdbe.c 6c8f28911e702151c8ef03c568db5a066d3a85d4 +F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 0e01d6fda149c689039caadb8c89b20abb58e21d +F src/vdbeaux.c 8b8eeb3cd89e4b3d4f40186344915b49b7c1c0f7 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 824029090d1c4c4c608f67dd197961eba29c039d -R 819e2e4df777a2f59b5f5445b2831eb5 +P b46d4e8923e6e367412bba7aeac07039bbcbabd1 +R e5107e17f1549034e719556b6caa9337 U drh -Z c4d587ace814e560a6dc901fdec24d15 +Z 29723a7a1d524b99d64cf7ed14fa2052 diff --git a/manifest.uuid b/manifest.uuid index 32d13dfb30..2aabeadce3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b46d4e8923e6e367412bba7aeac07039bbcbabd1 \ No newline at end of file +4df0ac9023d9261145a4425a508ba009a10276fc \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 2253af4719..5ab0127658 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -492,7 +492,6 @@ int sqlite3VdbeExec( i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ - int origPc; /* Program counter at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ @@ -554,7 +553,6 @@ int sqlite3VdbeExec( assert( pc>=0 && pcnOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE - origPc = pc; start = sqlite3Hwtime(); #endif nVmStep++; @@ -6275,10 +6273,6 @@ default: { /* This is really OP_Noop and OP_Explain */ u64 elapsed = sqlite3Hwtime() - start; pOp->cycles += elapsed; pOp->cnt++; -#if 0 - fprintf(stdout, "%10llu ", elapsed); - sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]); -#endif } #endif diff --git a/src/vdbe.h b/src/vdbe.h index 44cd9123aa..66c69eec23 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -65,7 +65,7 @@ struct VdbeOp { char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE - int cnt; /* Number of times this instruction was executed */ + u32 cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif #ifdef SQLITE_VDBE_COVERAGE diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 89bb8975a5..ef70f8ae3f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2580,11 +2580,13 @@ int sqlite3VdbeReset(Vdbe *p){ if( pc!='\n' ) fprintf(out, "\n"); } for(i=0; inOp; i++){ - fprintf(out, "%6d %10lld %8lld ", + char zHdr[100]; + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", p->aOp[i].cnt, p->aOp[i].cycles, p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 ); + fprintf(out, "%s", zHdr); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); From 9d41bc105d1bc5da9431180f8295ce52bcc344e6 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Feb 2014 19:07:51 +0000 Subject: [PATCH 29/66] In memsys5, initialize new allocations to non-zero bytes. Change the content of freed allocations to prevent use after free. These changes in SQLITE_DEBUG only. FossilOrigin-Name: ba5f0a5599dece6d8f3dfe652800c28875c74a24 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/mem5.c | 13 +++++++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 349983f4f3..ea4b646be9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\svariable\sfrom\sthe\sVDBE_PROFILE\scompile-time\soption.\s\sKeep\sthe\nopcode\scount\sin\san\su32\sinstead\sof\san\sint. -D 2014-02-24T14:24:01.038 +C In\smemsys5,\sinitialize\snew\sallocations\sto\snon-zero\sbytes.\s\sChange\sthe\scontent\nof\sfreed\sallocations\sto\sprevent\suse\safter\sfree.\s\sThese\schanges\sin\sSQLITE_DEBUG\nonly. +D 2014-02-24T19:07:51.519 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 -F src/mem5.c 19d9271cb936742707b6118ed44d779657c7c511 +F src/mem5.c aeb019f271ea53de83d651ec526877e6ba863450 F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785 F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P b46d4e8923e6e367412bba7aeac07039bbcbabd1 -R e5107e17f1549034e719556b6caa9337 +P 4df0ac9023d9261145a4425a508ba009a10276fc +R d75bf2d1dc1afee51bd2a2b5f0c23dc4 U drh -Z 29723a7a1d524b99d64cf7ed14fa2052 +Z e260958c722bfd17d5ba07190b7e2529 diff --git a/manifest.uuid b/manifest.uuid index 2aabeadce3..99dcc1b1b7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4df0ac9023d9261145a4425a508ba009a10276fc \ No newline at end of file +ba5f0a5599dece6d8f3dfe652800c28875c74a24 \ No newline at end of file diff --git a/src/mem5.c b/src/mem5.c index 4674ec68f5..5d75611a32 100644 --- a/src/mem5.c +++ b/src/mem5.c @@ -275,6 +275,12 @@ static void *memsys5MallocUnsafe(int nByte){ if( mem5.maxCount Date: Mon, 24 Feb 2014 19:49:36 +0000 Subject: [PATCH 30/66] Close some stray connections in walro.test. FossilOrigin-Name: d6746cabaa22429644c956a4b5fd91896376de2d --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/walro.test | 14 ++++++++------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index ea4b646be9..916f53cc00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\smemsys5,\sinitialize\snew\sallocations\sto\snon-zero\sbytes.\s\sChange\sthe\scontent\nof\sfreed\sallocations\sto\sprevent\suse\safter\sfree.\s\sThese\schanges\sin\sSQLITE_DEBUG\nonly. -D 2014-02-24T19:07:51.519 +C Close\ssome\sstray\sconnections\sin\swalro.test. +D 2014-02-24T19:49:36.852 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1064,7 +1064,7 @@ F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483 F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 -F test/walro.test 6cc247a0cc9b36aeea2057dd28a922a1cdfbd630 +F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 4df0ac9023d9261145a4425a508ba009a10276fc -R d75bf2d1dc1afee51bd2a2b5f0c23dc4 -U drh -Z e260958c722bfd17d5ba07190b7e2529 +P ba5f0a5599dece6d8f3dfe652800c28875c74a24 +R 55b5056ebfab7e0aa95c7fc2968f106d +U dan +Z 43d53118dac35420ad2faa5a259188da diff --git a/manifest.uuid b/manifest.uuid index 99dcc1b1b7..62abb66e87 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ba5f0a5599dece6d8f3dfe652800c28875c74a24 \ No newline at end of file +d6746cabaa22429644c956a4b5fd91896376de2d \ No newline at end of file diff --git a/test/walro.test b/test/walro.test index f1ed275a1d..6d920b1e24 100644 --- a/test/walro.test +++ b/test/walro.test @@ -32,9 +32,6 @@ ifcapable !wal { } do_multiclient_test tn { - # Do not run tests with the connections in the same process. - # - if {$tn==2} continue # Close all connections and delete the database. # @@ -43,6 +40,10 @@ do_multiclient_test tn { code3 { db3 close } forcedelete test.db forcedelete walro + + # Do not run tests with the connections in the same process. + # + if {$tn==2} continue foreach c {code1 code2 code3} { $c { @@ -232,9 +233,6 @@ forcedelete test.db # database file while a checkpoint operation is ongoing. # do_multiclient_test tn { - # Do not run tests with the connections in the same process. - # - if {$tn==2} continue # Close all connections and delete the database. # @@ -243,6 +241,10 @@ do_multiclient_test tn { code3 { db3 close } forcedelete test.db forcedelete walro + + # Do not run tests with the connections in the same process. + # + if {$tn==2} continue foreach c {code1 code2 code3} { $c { From 1925a2e6f88d288b38474053356cb399df5d410f Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 24 Feb 2014 21:20:25 +0000 Subject: [PATCH 31/66] Enhance testing support for the Win32 VFS dynamic extension loading facilities. FossilOrigin-Name: 53081e7202fb55f792a78e73627466eb0200f11c --- Makefile.msc | 11 +++++++++++ manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/os_win.c | 13 ++++++++----- src/test_loadext.c | 6 ++++++ test/loadext.test | 21 +++++++++++++++++---- 6 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 61e5102607..119468a92d 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1319,6 +1319,10 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR) $(TESTFIXTURE_SRC) \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +extensiontest: testfixture.exe testloadext.dll + .\testfixture.exe $(TOP)\test\loadext.test + .\testfixture.exe $(TOP)\test\loadext2.test + fulltest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test @@ -1345,6 +1349,12 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +testloadext.lo: $(TOP)\src\test_loadext.c + $(LTCOMPILE) -c $(TOP)\src\test_loadext.c + +testloadext.dll: testloadext.lo + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo + showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showdb.c $(SQLITE3C) @@ -1371,6 +1381,7 @@ clean: -rmdir /Q/S tsrc del /Q .target_source del /Q tclsqlite3.exe tclsqlite3.exp + del /Q testloadext.dll testloadext.exp del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c sqlite3-*.c diff --git a/manifest b/manifest index 916f53cc00..7b0e38f502 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Close\ssome\sstray\sconnections\sin\swalro.test. -D 2014-02-24T19:49:36.852 +C Enhance\stesting\ssupport\sfor\sthe\sWin32\sVFS\sdynamic\sextension\sloading\sfacilities. +D 2014-02-24T21:20:25.412 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 371a17ef9cd011b103cfa1964119a8528f5427c9 +F Makefile.msc 4b39e17eb244d2fd3fb825d896380b38b782e69a F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8 F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7 @@ -203,7 +203,7 @@ F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5 -F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b +F src/os_win.c 166d2f195ea0b7b4ea948229f727f0a293dd3c65 F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0 @@ -249,7 +249,7 @@ F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61 F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64 -F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e +F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4 F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3 F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8 F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1 @@ -647,7 +647,7 @@ F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da F test/limit.test cc0ab63385239b63c72452b0e93700bf5e8f0b99 -F test/loadext.test 92e6dfefd1229c3ef4aaabd87419efd8fa57a7a5 +F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7 F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4 F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ba5f0a5599dece6d8f3dfe652800c28875c74a24 -R 55b5056ebfab7e0aa95c7fc2968f106d -U dan -Z 43d53118dac35420ad2faa5a259188da +P d6746cabaa22429644c956a4b5fd91896376de2d +R 92acab9fb5e448fe2bef6b9a7d9bb046 +U mistachkin +Z 2600b243b92aaa5b75c087148e5db2b4 diff --git a/manifest.uuid b/manifest.uuid index 62abb66e87..8331b56d75 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d6746cabaa22429644c956a4b5fd91896376de2d \ No newline at end of file +53081e7202fb55f792a78e73627466eb0200f11c \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index d393c0d016..ac5eb886e3 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5135,15 +5135,12 @@ static int winFullPathname( ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. */ -/* -** Interfaces for opening a shared library, finding entry points -** within the shared library, and closing the shared library. -*/ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; void *zConverted = winConvertFromUtf8Filename(zFilename); UNUSED_PARAMETER(pVfs); if( zConverted==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); return 0; } if( osIsNT() ){ @@ -5158,6 +5155,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ h = osLoadLibraryA((char*)zConverted); } #endif + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h)); sqlite3_free(zConverted); return (void*)h; } @@ -5166,12 +5164,17 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); } static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ + FARPROC pProc; UNUSED_PARAMETER(pVfs); - return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym); + pProc = osGetProcAddressA((HANDLE)pH, zSym); + OSTRACE(("DLSYM handle=%p, symbol=%s, proc=%p\n", + (void*)pH, zSym, (void*)pProc)); + return (void(*)(void))pProc; } static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ UNUSED_PARAMETER(pVfs); osFreeLibrary((HANDLE)pHandle); + OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle)); } #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ #define winDlOpen 0 diff --git a/src/test_loadext.c b/src/test_loadext.c index 1137e3a9aa..5a1f46da9c 100644 --- a/src/test_loadext.c +++ b/src/test_loadext.c @@ -91,6 +91,9 @@ static void statusFunc( /* ** Extension load function. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif int testloadext_init( sqlite3 *db, char **pzErrMsg, @@ -109,6 +112,9 @@ int testloadext_init( /* ** Another extension entry point. This one always fails. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif int testbrokenext_init( sqlite3 *db, char **pzErrMsg, diff --git a/test/loadext.test b/test/loadext.test index 0d5b841980..7ba4c0cf77 100644 --- a/test/loadext.test +++ b/test/loadext.test @@ -66,6 +66,12 @@ if {$::tcl_platform(os) eq "Darwin"} { set dlerror_nosymbol {dlsym(XXX, %2$s): symbol not found} } +if {$::tcl_platform(platform) eq "windows"} { + set dlerror_nosuchfile {The specified module could not be found.*} + set dlerror_notadll {%%1 is not a valid Win32 application.*} + set dlerror_nosymbol {The specified procedure could not be found.*} +} + # Make sure the test extension actually exists. If it does not # exist, try to create it. If unable to create it, then skip this # test file. @@ -167,7 +173,7 @@ do_test loadext-2.3 { regsub {0x[1234567890abcdefABCDEF]*} $msg XXX msg } list $rc $msg -} [list 1 [format $dlerror_nosymbol $testextension icecream]] +} /[list 1 [format $dlerror_nosymbol $testextension icecream]]/ # Try to load an extension for which the entry point fails (returns non-zero) # @@ -267,10 +273,17 @@ do_malloc_test loadext-5 -tclprep { } -tclbody { if {[autoinstall_test_functions]==7} {error "out of memory"} } -do_malloc_test loadext-6 -tclbody { - db enable_load_extension 1 - sqlite3_load_extension db $::testextension testloadext_init + +# On Windows, this malloc test must be skipped because the winDlOpen +# function itself can fail due to "out of memory" conditions. +# +if {$::tcl_platform(platform) ne "windows"} { + do_malloc_test loadext-6 -tclbody { + db enable_load_extension 1 + sqlite3_load_extension db $::testextension testloadext_init + } } + autoinstall_test_functions finish_test From 151d05cd39f6693cd085c281bec6fd96c73bfe3c Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 24 Feb 2014 21:42:33 +0000 Subject: [PATCH 32/66] Fix several small style/consistency issues with the previous check-in. FossilOrigin-Name: 2477b3a294beb35f806a38f3ebc008942ba01617 --- Makefile.msc | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 119468a92d..5d6460b7d5 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1321,7 +1321,6 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR) extensiontest: testfixture.exe testloadext.dll .\testfixture.exe $(TOP)\test\loadext.test - .\testfixture.exe $(TOP)\test\loadext2.test fulltest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\all.test @@ -1373,6 +1372,7 @@ clean: del /Q sqlite3.h opcodes.c opcodes.h del /Q lemon.exe lempar.c parse.* del /Q mkkeywordhash.exe keywordhash.h + del /Q notasharedlib.* -rmdir /Q/S .deps -rmdir /Q/S .libs -rmdir /Q/S quota2a diff --git a/manifest b/manifest index 7b0e38f502..ee235b0695 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Enhance\stesting\ssupport\sfor\sthe\sWin32\sVFS\sdynamic\sextension\sloading\sfacilities. -D 2014-02-24T21:20:25.412 +C Fix\sseveral\ssmall\sstyle/consistency\sissues\swith\sthe\sprevious\scheck-in. +D 2014-02-24T21:42:33.898 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 4b39e17eb244d2fd3fb825d896380b38b782e69a +F Makefile.msc fdacba6fb574868c71fde6db6b77789a383a4c19 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8 F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7 @@ -203,7 +203,7 @@ F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5 -F src/os_win.c 166d2f195ea0b7b4ea948229f727f0a293dd3c65 +F src/os_win.c c47f107fc5c9d3466c06ea4aa35822f3568e81ee F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d6746cabaa22429644c956a4b5fd91896376de2d -R 92acab9fb5e448fe2bef6b9a7d9bb046 +P 53081e7202fb55f792a78e73627466eb0200f11c +R eaeb88d7c9d1a25aae3665432185c5f6 U mistachkin -Z 2600b243b92aaa5b75c087148e5db2b4 +Z 8d06aaa0b8bcae8ffbf3fa0332e7604d diff --git a/manifest.uuid b/manifest.uuid index 8331b56d75..9798e1319d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -53081e7202fb55f792a78e73627466eb0200f11c \ No newline at end of file +2477b3a294beb35f806a38f3ebc008942ba01617 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index ac5eb886e3..55ade5c7e2 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5164,12 +5164,12 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); } static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ - FARPROC pProc; + FARPROC proc; UNUSED_PARAMETER(pVfs); - pProc = osGetProcAddressA((HANDLE)pH, zSym); - OSTRACE(("DLSYM handle=%p, symbol=%s, proc=%p\n", - (void*)pH, zSym, (void*)pProc)); - return (void(*)(void))pProc; + proc = osGetProcAddressA((HANDLE)pH, zSym); + OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n", + (void*)pH, zSym, (void*)proc)); + return (void(*)(void))proc; } static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ UNUSED_PARAMETER(pVfs); From 5e990bea516af17f76e29853f2eb65cdd7bafe46 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 25 Feb 2014 14:52:01 +0000 Subject: [PATCH 33/66] QNX requires that _FILE_OFFSET_BITS be set prior to any system #include. FossilOrigin-Name: 953cdd6adadfd46b51ad61d7939cecca154a02cb --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqliteInt.h | 6 +++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index ee235b0695..c264178bb7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sseveral\ssmall\sstyle/consistency\sissues\swith\sthe\sprevious\scheck-in. -D 2014-02-24T21:42:33.898 +C QNX\srequires\sthat\s_FILE_OFFSET_BITS\sbe\sset\sprior\sto\sany\ssystem\s#include. +D 2014-02-25T14:52:01.414 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 616f8a225bfd6cf09f7f5906c7b91b29a3591b34 +F src/sqliteInt.h 6725dc99b3985a97bad315910e59c3f7f5058916 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 53081e7202fb55f792a78e73627466eb0200f11c -R eaeb88d7c9d1a25aae3665432185c5f6 -U mistachkin -Z 8d06aaa0b8bcae8ffbf3fa0332e7604d +P 2477b3a294beb35f806a38f3ebc008942ba01617 +R 2f8f4da586e3827cd7880a024d14180d +U drh +Z d8c76b3503c5028bde8839a0e5ab0156 diff --git a/manifest.uuid b/manifest.uuid index 9798e1319d..bb142df59c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2477b3a294beb35f806a38f3ebc008942ba01617 \ No newline at end of file +953cdd6adadfd46b51ad61d7939cecca154a02cb \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a6663ff679..72fe47be5a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -12,7 +12,6 @@ ** Internal interface definitions for SQLite. ** */ -#include "sqlite3.h" #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -48,6 +47,11 @@ # define _LARGEFILE_SOURCE 1 #endif +/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear +** first in QNX. +*/ +#include "sqlite3.h" + /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build From e8c1eba9a99a0251433aa58d0fd96155d47b18fe Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 25 Feb 2014 18:12:58 +0000 Subject: [PATCH 34/66] Also adjust the order of files in the amalgamation to ensure that _FILE_OFFSET_BITS is defined before any #include, for QNX. FossilOrigin-Name: 23001a85cd334090cf6c70d4d7e722a01f4f6899 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/mksqlite3c.tcl | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index c264178bb7..f25d3185ff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C QNX\srequires\sthat\s_FILE_OFFSET_BITS\sbe\sset\sprior\sto\sany\ssystem\s#include. -D 2014-02-25T14:52:01.414 +C Also\sadjust\sthe\sorder\sof\sfiles\sin\sthe\samalgamation\sto\sensure\sthat\n_FILE_OFFSET_BITS\sis\sdefined\sbefore\sany\s#include,\sfor\sQNX. +D 2014-02-25T18:12:58.878 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1120,7 +1120,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 -F tool/mksqlite3c.tcl e2ba20d3f690990079d17f3e5a7417dfb7ada543 +F tool/mksqlite3c.tcl ed5b4e9ca8bf209ff401059a16362f37710fd8b8 F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12 F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5 @@ -1151,7 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 2477b3a294beb35f806a38f3ebc008942ba01617 -R 2f8f4da586e3827cd7880a024d14180d +P 953cdd6adadfd46b51ad61d7939cecca154a02cb +R d169e5164f16cb0355a3972eba04326c U drh -Z d8c76b3503c5028bde8839a0e5ab0156 +Z 6c6f89e1dd41d2a146386cfa06ae53d9 diff --git a/manifest.uuid b/manifest.uuid index bb142df59c..a069c374c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -953cdd6adadfd46b51ad61d7939cecca154a02cb \ No newline at end of file +23001a85cd334090cf6c70d4d7e722a01f4f6899 \ No newline at end of file diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index de9b48b97b..7a4fe1b389 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -121,7 +121,6 @@ foreach hdr { set available_hdr($hdr) 1 } set available_hdr(sqliteInt.h) 0 -set available_hdr(sqlite3.h) 0 # 78 stars used for comment formatting. set s78 \ @@ -229,7 +228,6 @@ proc copy_file {filename} { # inlining opportunities. # foreach file { - sqlite3.h sqliteInt.h global.c From 1fed5dab0dedceca104c51670cf74114587b536f Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 25 Feb 2014 21:01:25 +0000 Subject: [PATCH 35/66] Attempt to speed up sqlite3VdbeRecordCompare() by various means. This code is in an interim state. FossilOrigin-Name: 85206e0bbac29adab52bef795f6d1479f2ae2c0e --- manifest | 31 ++-- manifest.uuid | 2 +- src/btree.c | 12 +- src/sqliteInt.h | 7 +- src/vdbe.c | 23 ++- src/vdbe.h | 3 + src/vdbeaux.c | 413 ++++++++++++++++++++++++++++++++++++++++++++--- src/vdbemem.c | 113 ------------- src/vdbesort.c | 2 +- test/pragma.test | 3 + 10 files changed, 440 insertions(+), 169 deletions(-) diff --git a/manifest b/manifest index f25d3185ff..2d70d7d908 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Also\sadjust\sthe\sorder\sof\sfiles\sin\sthe\samalgamation\sto\sensure\sthat\n_FILE_OFFSET_BITS\sis\sdefined\sbefore\sany\s#include,\sfor\sQNX. -D 2014-02-25T18:12:58.878 +C Attempt\sto\sspeed\sup\ssqlite3VdbeRecordCompare()\sby\svarious\smeans.\sThis\scode\sis\sin\san\sinterim\sstate. +D 2014-02-25T21:01:25.824 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -163,7 +163,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200 +F src/btree.c f4d85c3e2e189a219965d6d4525330333735fd1d F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0 @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 6725dc99b3985a97bad315910e59c3f7f5058916 +F src/sqliteInt.h 6d868994f476b616ddb1795a51aa83c331ef5a62 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -277,14 +277,14 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 6c8f28911e702151c8ef03c568db5a066d3a85d4 -F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8 +F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a +F src/vdbe.h 0758eff7f1bf939bcafa377b2fafba4f5be63007 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 8b8eeb3cd89e4b3d4f40186344915b49b7c1c0f7 +F src/vdbeaux.c 988269c675ebb75a3610479840b65bcb8ea92647 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda -F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 +F src/vdbemem.c 25cc487244bf6ad647105c5adbc3052403dfd143 +F src/vdbesort.c 5144d84bd7d0d2545af1c6322edbbf07f97e3892 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 @@ -735,7 +735,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04 -F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429 +F test/pragma.test c1bc3a29f664b57d0ae40b498ad31f370de8daa6 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1 @@ -1151,7 +1151,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 953cdd6adadfd46b51ad61d7939cecca154a02cb -R d169e5164f16cb0355a3972eba04326c -U drh -Z 6c6f89e1dd41d2a146386cfa06ae53d9 +P 23001a85cd334090cf6c70d4d7e722a01f4f6899 +R 04ade79c9b23add6f2d6adf0c34db1e4 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * +U dan +Z d3f147085a7b8a8eca4578239439871b diff --git a/manifest.uuid b/manifest.uuid index a069c374c5..dd611d410f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -23001a85cd334090cf6c70d4d7e722a01f4f6899 \ No newline at end of file +85206e0bbac29adab52bef795f6d1479f2ae2c0e \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4fd8e27bf4..6c5f02403e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4547,6 +4547,7 @@ int sqlite3BtreeMovetoUnpacked( int *pRes /* Write search results here */ ){ int rc; + int (*xRecordCompare)(int, const void*, UnpackedRecord*); assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); @@ -4568,6 +4569,11 @@ int sqlite3BtreeMovetoUnpacked( } } + if( pIdxKey ){ + xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); + assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1); + } + rc = moveToRoot(pCur); if( rc ){ return rc; @@ -4652,14 +4658,14 @@ int sqlite3BtreeMovetoUnpacked( ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated @@ -4680,7 +4686,7 @@ int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); + c = xRecordCompare(nCell, pCellKey, pIdxKey); sqlite3_free(pCellKey); } if( c<0 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 72fe47be5a..76dea413e0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1590,15 +1590,10 @@ struct KeyInfo { struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ - u8 flags; /* Boolean settings. UNPACKED_... below */ + char default_rc; /* Comparison result if keys are equal */ Mem *aMem; /* Values */ }; -/* -** Allowed values of UnpackedRecord.flags -*/ -#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */ -#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */ /* ** Each SQL index is represented in memory by an diff --git a/src/vdbe.c b/src/vdbe.c index 5ab0127658..097f182a23 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3555,16 +3555,16 @@ case OP_SeekGT: { /* jump, in3 */ /* The next line of code computes as follows, only faster: ** if( oc==OP_SeekGT || oc==OP_SeekLE ){ - ** r.flags = UNPACKED_INCRKEY; + ** r.default_rc = -1; ** }else{ - ** r.flags = 0; + ** r.default_rc = +1; ** } */ - r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT))); - assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY ); - assert( oc!=OP_SeekGE || r.flags==0 ); - assert( oc!=OP_SeekLT || r.flags==0 ); + r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); + assert( oc!=OP_SeekGT || r.default_rc==-1 ); + assert( oc!=OP_SeekLE || r.default_rc==-1 ); + assert( oc!=OP_SeekGE || r.default_rc==+1 ); + assert( oc!=OP_SeekLT || r.default_rc==+1 ); r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG @@ -3722,7 +3722,6 @@ case OP_Found: { /* jump, in3 */ if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]); #endif } - r.flags = UNPACKED_PREFIX_MATCH; pIdxKey = &r; }else{ pIdxKey = sqlite3VdbeAllocUnpackedRecord( @@ -3732,8 +3731,8 @@ case OP_Found: { /* jump, in3 */ assert( pIn3->flags & MEM_Blob ); assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); - pIdxKey->flags |= UNPACKED_PREFIX_MATCH; } + pIdxKey->default_rc = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not @@ -4622,7 +4621,7 @@ case OP_IdxDelete: { assert( pOp->p5==0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p3; - r.flags = UNPACKED_PREFIX_MATCH; + r.default_rc = 0; r.aMem = &aMem[pOp->p2]; #ifdef SQLITE_DEBUG { int i; for(i=0; ip4.i; if( pOp->opcodeopcode==OP_IdxLE || pOp->opcode==OP_IdxGT ); - r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; + r.default_rc = -1; }else{ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT ); - r.flags = UNPACKED_PREFIX_MATCH; + r.default_rc = 0; } r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG diff --git a/src/vdbe.h b/src/vdbe.h index 66c69eec23..af07831faa 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -214,6 +214,9 @@ void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); +typedef int (*RecordCompare)(int,const void*, UnpackedRecord*); +RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *); + #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ef70f8ae3f..e817ccb23f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3102,7 +3102,7 @@ void sqlite3VdbeRecordUnpack( u32 szHdr; Mem *pMem = p->aMem; - p->flags = 0; + p->default_rc = 0; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); idx = getVarint32(aKey, szHdr); d = szHdr; @@ -3123,6 +3123,215 @@ void sqlite3VdbeRecordUnpack( p->nField = u; } +static int vdbeRecordCompareString( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey1 = (const u8*)pKey1; + int szHdr; + int serial_type; + int res; + + szHdr = aKey1[0]; + getVarint32(&aKey1[1], serial_type); + + if( serial_type<12 ){ + res = -1; /* (pKey1/nKey1) is a number or a null */ + }else if( !(serial_type & 0x01) ){ + res = +1; /* (pKey1/nKey1) is a blob */ + }else{ + int nCmp; + int nStr; + aKey1 = &aKey1[szHdr]; + + nStr = (serial_type-12) / 2; + if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ + nCmp = MIN( pPKey2->aMem[0].n, nStr ); + res = memcmp(aKey1, pPKey2->aMem[0].z, nCmp); + + if( res==0 ){ + res = nStr - pPKey2->aMem[0].n; + if( res==0 ) res = pPKey2->default_rc; + } + } + + assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) + || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) + || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) + ); + return res; +} + +static int vdbeRecordCompareInt( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey1 = (const u8*)pKey1; + int szHdr; + int serial_type; + int res; + + szHdr = aKey1[0]; + getVarint32(&aKey1[1], serial_type); + + if( serial_type==0 ){ + res = -1; /* NULL values are smaller than integers */ + }else if( serial_type>=12 ){ + res = +1; /* text/blob values are greater */ + }else{ + Mem mem; + sqlite3VdbeSerialGet(&aKey1[szHdr], serial_type, &mem); + if( mem.flags & MEM_Int ){ + i64 v = pPKey2->aMem[0].u.i; + if( v>mem.u.i ){ + res = -1; + }else if( vdefault_rc; + } + }else{ + double v = (double)pPKey2->aMem[0].u.i; + if( v>mem.r ){ + res = -1; + }else if( vdefault_rc; + } + } + } + + assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) + || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) + || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) + ); + return res; +} + +static int vdbeCompareMemString( + const Mem *pMem1, + const Mem *pMem2, + const CollSeq *pColl +){ + if( pMem1->enc==pColl->enc ){ + /* The strings are already in the correct encoding. Call the + ** comparison function directly */ + return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); + }else{ + int rc; + const void *v1, *v2; + int n1, n2; + Mem c1; + Mem c2; + memset(&c1, 0, sizeof(c1)); + memset(&c2, 0, sizeof(c2)); + sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); + sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); + v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); + n1 = v1==0 ? 0 : c1.n; + v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); + n2 = v2==0 ? 0 : c2.n; + rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); + sqlite3VdbeMemRelease(&c1); + sqlite3VdbeMemRelease(&c2); + return rc; + } +} + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int rc; + int f1, f2; + int combined_flags; + + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; + assert( (combined_flags & MEM_RowSet)==0 ); + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. + */ + if( combined_flags&MEM_Null ){ + return (f2&MEM_Null) - (f1&MEM_Null); + } + + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. + */ + if( combined_flags&(MEM_Int|MEM_Real) ){ + double r1, r2; + if( (f1 & f2 & MEM_Int)!=0 ){ + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return 1; + return 0; + } + if( (f1&MEM_Real)!=0 ){ + r1 = pMem1->r; + }else if( (f1&MEM_Int)!=0 ){ + r1 = (double)pMem1->u.i; + }else{ + return 1; + } + if( (f2&MEM_Real)!=0 ){ + r2 = pMem2->r; + }else if( (f2&MEM_Int)!=0 ){ + r2 = (double)pMem2->u.i; + }else{ + return -1; + } + if( r1r2 ) return 1; + return 0; + } + + /* If one value is a string and the other is a blob, the string is less. + ** If both are strings, compare using the collating functions. + */ + if( combined_flags&MEM_Str ){ + if( (f1 & MEM_Str)==0 ){ + return 1; + } + if( (f2 & MEM_Str)==0 ){ + return -1; + } + + assert( pMem1->enc==pMem2->enc ); + assert( pMem1->enc==SQLITE_UTF8 || + pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); + + /* The collation sequence must be defined at this point, even if + ** the user deletes the collation sequence after the vdbe program is + ** compiled (this was not always the case). + */ + assert( !pColl || pColl->xCmp ); + + if( pColl ){ + return vdbeCompareMemString(pMem1, pMem2, pColl); + } + /* If a NULL pointer was passed as the collate function, fall through + ** to the blob case and use memcmp(). */ + } + + /* Both values must be blobs. Compare using memcmp(). */ + rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); + if( rc==0 ){ + rc = pMem1->n - pMem2->n; + } + return rc; +} + + /* ** This function compares the two table rows or index records ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero @@ -3140,7 +3349,7 @@ void sqlite3VdbeRecordUnpack( ** equal, then the keys are considered to be equal and ** the parts beyond the common prefix are ignored. */ -int sqlite3VdbeRecordCompare( +static int vdbeRecordComparePrev( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ @@ -3216,25 +3425,192 @@ int sqlite3VdbeRecordCompare( assert( mem1.zMalloc==0 ); /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. If the UNPACKED_INCRKEY - ** flag is set, then break the tie by treating key2 as larger. - ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes - ** are considered to be equal. Otherwise, the longer key is the - ** larger. As it happens, the pPKey2 will always be the longer - ** if there is a difference. - */ - assert( rc==0 ); - if( pPKey2->flags & UNPACKED_INCRKEY ){ - rc = -1; - }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){ - /* Leave rc==0 */ - }else if( idx1default_rc; } +int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + u32 d1; /* Offset into aKey[] of next data element */ + u32 idx1; /* Offset into aKey[] of next header element */ + u32 szHdr1; /* Number of bytes in header */ + int i = 0; + int rc = 0; + KeyInfo *pKeyInfo = pPKey2->pKeyInfo; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + Mem mem1; + +#ifdef SQLITE_DEBUG + int expected = vdbeRecordComparePrev(nKey1, pKey1, pPKey2); + static int nCall = 0; + nCall++; +#endif + + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ + + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField + || CORRUPT_DB ); + assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->nField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + Mem *pRhs = &pPKey2->aMem[i]; + u32 serial_type; + + /* RHS is an integer */ + if( pRhs->flags & MEM_Int ){ + serial_type = aKey1[idx1]; + if( serial_type>=12 ){ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else{ + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( serial_type==7 ){ + double rhs = (double)pRhs->u.i; + if( mem1.rrhs ){ + rc = +1; + } + }else{ + i64 rhs = pRhs->u.i; + if( mem1.u.irhs ){ + rc = +1; + } + } + } + } + + /* RHS is real */ + else if( pRhs->flags & MEM_Real ){ + serial_type = aKey1[idx1]; + if( serial_type>=12 ){ + rc = +1; + }else if( serial_type==0 ){ + rc = -1; + }else{ + double rhs = pRhs->r; + double lhs; + sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); + if( serial_type==7 ){ + lhs = mem1.r; + }else{ + lhs = mem1.u.i; + } + if( lhsrhs ){ + rc = +1; + } + } + } + + /* RHS is a string */ + else if( pRhs->flags & MEM_Str ){ + getVarint32(&aKey1[idx1], serial_type); + if( serial_type<12 ){ + rc = -1; + }else if( !(serial_type & 0x01) ){ + rc = +1; + }else{ + mem1.n = (serial_type - 12) / 2; + if( (d1+mem1.n) > nKey1 ){ + rc = 1; /* Corruption */ + }else if( pKeyInfo->aColl[i] ){ + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = MEM_Str; + mem1.z = &aKey1[d1]; + rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]); + }else{ + int nCmp = MIN(mem1.n, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = mem1.n - pRhs->n; + } + } + } + + /* RHS is a blob */ + else if( pRhs->flags & MEM_Blob ){ + getVarint32(&aKey1[idx1], serial_type); + if( serial_type<12 || (serial_type & 0x01) ){ + rc = -1; + }else{ + int nStr = (serial_type - 12) / 2; + if( (d1+nStr) > nKey1 ){ + rc = 1; /* Corruption */ + }else{ + int nCmp = MIN(nStr, pRhs->n); + rc = memcmp(&aKey1[d1], pRhs->z, nCmp); + if( rc==0 ) rc = nStr - pRhs->n; + } + } + } + + /* RHS is null */ + else{ + serial_type = aKey1[idx1]; + rc = (serial_type!=0); + } + + if( rc!=0 ){ + assert( mem1.zMalloc==0 ); /* See comment below */ + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; +#if 0 + assert( (rc>0 && (rc^(int)0x80000000)<0) + || (rc<0 && (rc^(int)0x80000000)>0) ); + assert( sizeof(int)==4 ); + rc ^= (int)0x80000000; /* similar in spirit to: "rc = -rc;" */ + assert( rc!=0 ); +#endif + } + assert( (rc<0 && expected<0) || (rc>0 && expected>0) || CORRUPT_DB ); + return rc; + } + + i++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); + idx1 += sqlite3VarintLen(serial_type); + }while( idx1nField && d1<=nKey1 ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). + */ + assert( mem1.zMalloc==0 ); + + /* rc==0 here means that one or both of the keys ran out of fields and + ** all the fields up to that point were equal. Return the the default_rc + ** value. */ + assert( pPKey2->default_rc==expected ); + return pPKey2->default_rc; +} + +RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ + if( p->nField==1 && p->pKeyInfo->aSortOrder[0]==0 ){ + int flags = p->aMem[0].flags; + if( (flags & MEM_Int) ){ + return vdbeRecordCompareInt; + }else if( (p->aMem[0].flags&(MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 + && p->pKeyInfo->aColl[0]==0 + ){ + return vdbeRecordCompareString; + } + } + return sqlite3VdbeRecordCompare; +} + + /* ** pCur points at an index entry created using the OP_MakeRecord opcode. ** Read the rowid (the last field in the record) and store it in *rowid. @@ -3347,7 +3723,6 @@ int sqlite3VdbeIdxKeyCompare( if( rc ){ return rc; } - assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH ); *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); sqlite3VdbeMemRelease(&m); return SQLITE_OK; diff --git a/src/vdbemem.c b/src/vdbemem.c index bcf9586b3f..4936f40016 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -754,119 +754,6 @@ int sqlite3VdbeMemSetStr( return SQLITE_OK; } -/* -** Compare the values contained by the two memory cells, returning -** negative, zero or positive if pMem1 is less than, equal to, or greater -** than pMem2. Sorting order is NULL's first, followed by numbers (integers -** and reals) sorted numerically, followed by text ordered by the collating -** sequence pColl and finally blob's ordered by memcmp(). -** -** Two NULL values are considered equal by this function. -*/ -int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ - int rc; - int f1, f2; - int combined_flags; - - f1 = pMem1->flags; - f2 = pMem2->flags; - combined_flags = f1|f2; - assert( (combined_flags & MEM_RowSet)==0 ); - - /* If one value is NULL, it is less than the other. If both values - ** are NULL, return 0. - */ - if( combined_flags&MEM_Null ){ - return (f2&MEM_Null) - (f1&MEM_Null); - } - - /* If one value is a number and the other is not, the number is less. - ** If both are numbers, compare as reals if one is a real, or as integers - ** if both values are integers. - */ - if( combined_flags&(MEM_Int|MEM_Real) ){ - double r1, r2; - if( (f1 & f2 & MEM_Int)!=0 ){ - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return 1; - return 0; - } - if( (f1&MEM_Real)!=0 ){ - r1 = pMem1->r; - }else if( (f1&MEM_Int)!=0 ){ - r1 = (double)pMem1->u.i; - }else{ - return 1; - } - if( (f2&MEM_Real)!=0 ){ - r2 = pMem2->r; - }else if( (f2&MEM_Int)!=0 ){ - r2 = (double)pMem2->u.i; - }else{ - return -1; - } - if( r1r2 ) return 1; - return 0; - } - - /* If one value is a string and the other is a blob, the string is less. - ** If both are strings, compare using the collating functions. - */ - if( combined_flags&MEM_Str ){ - if( (f1 & MEM_Str)==0 ){ - return 1; - } - if( (f2 & MEM_Str)==0 ){ - return -1; - } - - assert( pMem1->enc==pMem2->enc ); - assert( pMem1->enc==SQLITE_UTF8 || - pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); - - /* The collation sequence must be defined at this point, even if - ** the user deletes the collation sequence after the vdbe program is - ** compiled (this was not always the case). - */ - assert( !pColl || pColl->xCmp ); - - if( pColl ){ - if( pMem1->enc==pColl->enc ){ - /* The strings are already in the correct encoding. Call the - ** comparison function directly */ - return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); - }else{ - const void *v1, *v2; - int n1, n2; - Mem c1; - Mem c2; - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); - sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); - v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - n1 = v1==0 ? 0 : c1.n; - v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - n2 = v2==0 ? 0 : c2.n; - rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); - sqlite3VdbeMemRelease(&c1); - sqlite3VdbeMemRelease(&c2); - return rc; - } - } - /* If a NULL pointer was passed as the collate function, fall through - ** to the blob case and use memcmp(). */ - } - - /* Both values must be blobs. Compare using memcmp(). */ - rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); - if( rc==0 ){ - rc = pMem1->n - pMem2->n; - } - return rc; -} - /* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing diff --git a/src/vdbesort.c b/src/vdbesort.c index 3e4cad5b4a..c4d15d6872 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -409,7 +409,7 @@ static void vdbeSorterCompare( return; } } - r2->flags |= UNPACKED_PREFIX_MATCH; + assert( r2->default_rc==0 ); } *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2); diff --git a/test/pragma.test b/test/pragma.test index 1043170378..fcbb1808fa 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -1575,6 +1575,8 @@ do_test pragma-20.8 { forcedelete data_dir } ;# endif windows +database_may_be_corrupt + do_test 21.1 { # Create a corrupt database in testerr.db. And a non-corrupt at test.db. # @@ -1680,4 +1682,5 @@ do_test 23.5 { } } {0 0 t1 y {} {NO ACTION} {NO ACTION} NONE} +database_never_corrupt finish_test From 0baa035a1e3339d8bb0aea2205a2dee4f56fcc9e Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 25 Feb 2014 21:55:16 +0000 Subject: [PATCH 36/66] Do not allow temporary registers to be in use across an OP_Yield within a co-routine. Fix for ticket [8c63ff0eca81a9132d8]. FossilOrigin-Name: 97a8c9733cba97c78e979dfd5c66610c23e90288 --- manifest | 15 +++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 1 - src/where.c | 8 +++---- test/tkt-8c63ff0ec.test | 48 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 test/tkt-8c63ff0ec.test diff --git a/manifest b/manifest index f25d3185ff..e66acbb7e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Also\sadjust\sthe\sorder\sof\sfiles\sin\sthe\samalgamation\sto\sensure\sthat\n_FILE_OFFSET_BITS\sis\sdefined\sbefore\sany\s#include,\sfor\sQNX. -D 2014-02-25T18:12:58.878 +C Do\snot\sallow\stemporary\sregisters\sto\sbe\sin\suse\sacross\san\sOP_Yield\swithin\sa\nco-routine.\s\sFix\sfor\sticket\s[8c63ff0eca81a9132d8]. +D 2014-02-25T21:55:16.402 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 6725dc99b3985a97bad315910e59c3f7f5058916 +F src/sqliteInt.h 46dfbe0b58282421188a6c25b6c0c0fae18e0134 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c d622974f30d3347c7b71bfe49ce1f1e9b6570980 +F src/where.c 0b5a4d45fdf05ad541893d986abd2f660f6e0094 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -881,6 +881,7 @@ F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8 F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7 F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c F test/tkt-868145d012.test a5f941107ece6a64410ca4755c6329b7eb57a356 +F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5 F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223 F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67 @@ -1151,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 953cdd6adadfd46b51ad61d7939cecca154a02cb -R d169e5164f16cb0355a3972eba04326c +P 23001a85cd334090cf6c70d4d7e722a01f4f6899 +R 53d871612a374a058c13125cf02ae108 U drh -Z 6c6f89e1dd41d2a146386cfa06ae53d9 +Z 196bbfe69fc9298304e0610559f3cd1e diff --git a/manifest.uuid b/manifest.uuid index a069c374c5..a96614dc89 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -23001a85cd334090cf6c70d4d7e722a01f4f6899 \ No newline at end of file +97a8c9733cba97c78e979dfd5c66610c23e90288 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 72fe47be5a..c7f2941d5d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2358,7 +2358,6 @@ struct Parse { u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ - u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ diff --git a/src/where.c b/src/where.c index d606ba4c18..f5d44a3877 100644 --- a/src/where.c +++ b/src/where.c @@ -2853,13 +2853,14 @@ static Bitmask codeOneLoopStart( ** construct. */ assert( pLoop->u.btree.nEq==1 ); - iReleaseReg = sqlite3GetTempReg(pParse); pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); + iReleaseReg = ++pParse->nMem; iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); + if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); @@ -2948,7 +2949,7 @@ static Bitmask codeOneLoopStart( pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); @@ -3181,7 +3182,7 @@ static Bitmask codeOneLoopStart( if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); + iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ @@ -3529,7 +3530,6 @@ static Bitmask codeOneLoopStart( pTerm->wtFlags |= TERM_CODED; } } - sqlite3ReleaseTempReg(pParse, iReleaseReg); return pLevel->notReady; } diff --git a/test/tkt-8c63ff0ec.test b/test/tkt-8c63ff0ec.test new file mode 100644 index 0000000000..d4aaefd74a --- /dev/null +++ b/test/tkt-8c63ff0ec.test @@ -0,0 +1,48 @@ +# 2014-02-25 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases to show that ticket [8c63ff0eca81a9132d8d67b31cd6ae9712a2cc6f] +# "Incorrect query result on a UNION ALL" which was caused by using the same +# temporary register in concurrent co-routines, as been fixed. +# + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix tkt-8c63ff0ec + +do_execsql_test 1.1 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e); + INSERT INTO t1 VALUES(1,20,30,40,50),(3,60,70,80,90); + CREATE TABLE t2(x INTEGER PRIMARY KEY); + INSERT INTO t2 VALUES(2); + CREATE TABLE t3(z); + INSERT INTO t3 VALUES(2),(2),(2),(2); + + SELECT a, b+c FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 50 2 5 2 5 2 5 2 5 3 130} +do_execsql_test 1.2 { + SELECT a, b+c+d FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 90 2 5 2 5 2 5 2 5 3 210} +do_execsql_test 1.3 { + SELECT a, b+c+d+e FROM t1 + UNION ALL + SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2 + ORDER BY a; +} {1 140 2 5 2 5 2 5 2 5 3 300} + +finish_test From 434a93147cfa23b7a9bd49fef8f1f1b59c9da4d3 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Feb 2014 02:26:09 +0000 Subject: [PATCH 37/66] Improved handling of constants and especially constant functions in the ORDER BY clause of a query. Do not optimize out "ORDER BY random()". Fix for ticket [65bdeb9739605cc2296]. FossilOrigin-Name: dca1945aeb3fb005263f9be00ee8e72b966ae303 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 21 ++++----------------- test/where2.test | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index e66acbb7e2..1acd1fc253 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\stemporary\sregisters\sto\sbe\sin\suse\sacross\san\sOP_Yield\swithin\sa\nco-routine.\s\sFix\sfor\sticket\s[8c63ff0eca81a9132d8]. -D 2014-02-25T21:55:16.402 +C Improved\shandling\sof\sconstants\sand\sespecially\sconstant\sfunctions\sin\sthe\nORDER\sBY\sclause\sof\sa\squery.\s\sDo\snot\soptimize\sout\s"ORDER\sBY\srandom()".\nFix\sfor\sticket\s[65bdeb9739605cc2296]. +D 2014-02-26T02:26:09.921 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 0b5a4d45fdf05ad541893d986abd2f660f6e0094 +F src/where.c 6042e1a377cf7dc72c10493269ed75e276275cd8 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1070,7 +1070,7 @@ F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b -F test/where2.test ed6baa9420a109d8be683dbef5d153d186f3690b +F test/where2.test 455a2eb2666e66c1e84e2cb5815173a85e6237db F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 23001a85cd334090cf6c70d4d7e722a01f4f6899 -R 53d871612a374a058c13125cf02ae108 +P 97a8c9733cba97c78e979dfd5c66610c23e90288 +R a3177866e2afe2abf843086af2a9a3a2 U drh -Z 196bbfe69fc9298304e0610559f3cd1e +Z c50f86b62c93dcd00c53d2ca75883787 diff --git a/manifest.uuid b/manifest.uuid index a96614dc89..68c025b08a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97a8c9733cba97c78e979dfd5c66610c23e90288 \ No newline at end of file +dca1945aeb3fb005263f9be00ee8e72b966ae303 \ No newline at end of file diff --git a/src/where.c b/src/where.c index f5d44a3877..a5dd7b59e7 100644 --- a/src/where.c +++ b/src/where.c @@ -4901,9 +4901,12 @@ static int wherePathSatisfiesOrderBy( orderDistinctMask |= pLoop->maskSelf; for(i=0; ia[i].pExpr; - if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){ + mTerm = exprTableUsage(&pWInfo->sMaskSet,p); + if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; + if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } @@ -5526,22 +5529,6 @@ WhereInfo *sqlite3WhereBegin( goto whereBeginError; } - /* If the ORDER BY (or GROUP BY) clause contains references to general - ** expressions, then we won't be able to satisfy it using indices, so - ** go ahead and disable it now. - */ - if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ){ - pWInfo->pOrderBy = pOrderBy = 0; - break; - }else if( pExpr->iColumn<0 ){ - break; - } - } - } - if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ diff --git a/test/where2.test b/test/where2.test index 45ea486d95..d9b2b23de9 100644 --- a/test/where2.test +++ b/test/where2.test @@ -121,6 +121,42 @@ do_test where2-2.3 { } } {85 6 7396 7402 nosort t1 *} +# Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26 +# Make sure "ORDER BY random" does not gets optimized out. +# +do_test where2-2.4 { + db eval { + CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1); + WITH RECURSIVE + cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50) + INSERT INTO x1 SELECT x, 1 FROM cnt; + CREATE TABLE x2(x INTEGER PRIMARY KEY); + INSERT INTO x2 VALUES(1); + } + set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()} + set out1 [db eval $sql] + set out2 [db eval $sql] + set out3 [db eval $sql] + expr {$out1!=$out2 && $out2!=$out3} +} {1} +do_execsql_test where2-2.5 { + -- random() is not optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); +} {/ random/} +do_execsql_test where2-2.5b { + -- random() is not optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random(); +} {/ SorterOpen /} +do_execsql_test where2-2.6 { + -- other constant functions are optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); +} {~/ abs/} +do_execsql_test where2-2.6b { + -- other constant functions are optimized out + EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5); +} {~/ SorterOpen /} + + # Efficient handling of forward and reverse table scans. # From 3852b68edd2d378f9f4a4b2377654ecbb6d423c1 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Feb 2014 13:53:34 +0000 Subject: [PATCH 38/66] In the command-line shell for CSV import, if the lines are \r\n terminated and the last field is blank, make sure an empty string and not a "\r" string is imported. FossilOrigin-Name: 9c2e7612cd137895e13ee872e668ce1216719d85 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 2 +- test/shell5.test | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 1acd1fc253..b398e0004c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\shandling\sof\sconstants\sand\sespecially\sconstant\sfunctions\sin\sthe\nORDER\sBY\sclause\sof\sa\squery.\s\sDo\snot\soptimize\sout\s"ORDER\sBY\srandom()".\nFix\sfor\sticket\s[65bdeb9739605cc2296]. -D 2014-02-26T02:26:09.921 +C In\sthe\scommand-line\sshell\sfor\sCSV\simport,\sif\sthe\slines\sare\s\\r\\n\sterminated\nand\sthe\slast\sfield\sis\sblank,\smake\ssure\san\sempty\sstring\sand\snot\sa\s"\\r"\sstring\nis\simported. +D 2014-02-26T13:53:34.384 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 28bff39f9bc5ec618b0719fe3f7b4be9f88b6f02 -F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 +F src/shell.c ca2b066ab31793532530e0c2fcf79e99628f3b2b F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -804,7 +804,7 @@ F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583 F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9 -F test/shell5.test cee83b4385f842fec1f2a0bec9ea811f35386edf +F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 97a8c9733cba97c78e979dfd5c66610c23e90288 -R a3177866e2afe2abf843086af2a9a3a2 +P dca1945aeb3fb005263f9be00ee8e72b966ae303 +R 4bbcd8ca02f23a972c97ceb5ec0d3c0c U drh -Z c50f86b62c93dcd00c53d2ca75883787 +Z 998297c355a76316139497aa81dafb02 diff --git a/manifest.uuid b/manifest.uuid index 68c025b08a..b18a32bd5f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dca1945aeb3fb005263f9be00ee8e72b966ae303 \ No newline at end of file +9c2e7612cd137895e13ee872e668ce1216719d85 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 266bb8f90f..7bb8da3e0f 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1893,7 +1893,7 @@ static char *csv_read_one_field(CSVReader *p){ } if( c=='\n' ){ p->nLine++; - if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; + if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--; } p->cTerm = c; } diff --git a/test/shell5.test b/test/shell5.test index ce05a303ca..4c38b75e6f 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -285,6 +285,25 @@ do_test shell5-1.10 { db eval {SELECT hex(c) FROM t1 ORDER BY rowid} } {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033} +# Blank last column with \r\n line endings. +do_test shell5-1.11 { + set out [open shell5.csv w] + fconfigure $out -translation binary + puts $out "column1,column2,column3\r" + puts $out "a,b, \r" + puts $out "x,y,\r" + puts $out "p,q,r\r" + close $out + catch {db close} + forcedelete test.db + catchcmd test.db {.mode csv +.import shell5.csv t1 + } + sqlite3 db test.db + db eval {SELECT *, '|' FROM t1} +} {a b { } | x y {} | p q r |} + + db close finish_test From 7e4efaecad8b403574647d08d2f47f0cc60679ef Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 Feb 2014 21:35:31 +0000 Subject: [PATCH 39/66] More efficient removal of duplicates in recursive queries using the UNION compound operator. FossilOrigin-Name: 06c2db875e6cabd81c2a153b2fa4aba03eaed268 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b398e0004c..9c72c3971c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\scommand-line\sshell\sfor\sCSV\simport,\sif\sthe\slines\sare\s\\r\\n\sterminated\nand\sthe\slast\sfield\sis\sblank,\smake\ssure\san\sempty\sstring\sand\snot\sa\s"\\r"\sstring\nis\simported. -D 2014-02-26T13:53:34.384 +C More\sefficient\sremoval\sof\sduplicates\sin\srecursive\squeries\susing\sthe\sUNION\ncompound\soperator. +D 2014-02-26T21:35:31.484 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,7 +216,7 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 28bff39f9bc5ec618b0719fe3f7b4be9f88b6f02 +F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 F src/shell.c ca2b066ab31793532530e0c2fcf79e99628f3b2b F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P dca1945aeb3fb005263f9be00ee8e72b966ae303 -R 4bbcd8ca02f23a972c97ceb5ec0d3c0c +P 9c2e7612cd137895e13ee872e668ce1216719d85 +R 8af1befb78d550449f6afe7ccc2f524b U drh -Z 998297c355a76316139497aa81dafb02 +Z 54acbfe19bff5d9f12c833489ea306bb diff --git a/manifest.uuid b/manifest.uuid index b18a32bd5f..b0059e4d9c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c2e7612cd137895e13ee872e668ce1216719d85 \ No newline at end of file +06c2db875e6cabd81c2a153b2fa4aba03eaed268 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 93947d56b2..a8cb341c65 100644 --- a/src/select.c +++ b/src/select.c @@ -818,14 +818,16 @@ static void selectInnerLoop( r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempRange(pParse, nKey+2); r3 = r2+nKey+1; - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); if( eDest==SRT_DistQueue ){ /* If the destination is DistQueue, then cursor (iParm+1) is open ** on a second ephemeral index that holds all values every previously - ** added to the queue. Only add this new value if it has never before - ** been added */ - addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0); + ** added to the queue. */ + addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, + regResult, nResultCol); VdbeCoverage(v); + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); + if( eDest==SRT_DistQueue ){ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } From c7181907688fa0d2a2bcabff7f392757e6efab96 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Feb 2014 15:04:13 +0000 Subject: [PATCH 40/66] Add #defines to the command-line shell source code (shell.c) so that it can be imported directly into other projects (ex: Fossil) and used without editing. FossilOrigin-Name: a6690400235705ecc0d1a60dacff6ad5fb1f944a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 9c72c3971c..7ec2f4b525 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\sefficient\sremoval\sof\sduplicates\sin\srecursive\squeries\susing\sthe\sUNION\ncompound\soperator. -D 2014-02-26T21:35:31.484 +C Add\s#defines\sto\sthe\scommand-line\sshell\ssource\scode\s(shell.c)\sso\sthat\sit\ncan\sbe\simported\sdirectly\sinto\sother\sprojects\s(ex:\sFossil)\sand\sused\swithout\s\nediting. +D 2014-02-27T15:04:13.436 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 -F src/shell.c ca2b066ab31793532530e0c2fcf79e99628f3b2b +F src/shell.c 720e79facdae4787e7bfa577dae6b37a685244b0 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9c2e7612cd137895e13ee872e668ce1216719d85 -R 8af1befb78d550449f6afe7ccc2f524b +P 06c2db875e6cabd81c2a153b2fa4aba03eaed268 +R b72dc063fb220f3231791c5c73300f82 U drh -Z 54acbfe19bff5d9f12c833489ea306bb +Z d3f85704b6a67858d1c2e6d5e8f9f735 diff --git a/manifest.uuid b/manifest.uuid index b0059e4d9c..03c67c2593 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -06c2db875e6cabd81c2a153b2fa4aba03eaed268 \ No newline at end of file +a6690400235705ecc0d1a60dacff6ad5fb1f944a \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 7bb8da3e0f..3cd7aaf892 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1008,7 +1008,7 @@ static int run_table_dump_query( int nResult; int i; const char *z; - rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0); + rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; @@ -1456,7 +1456,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ zTableInfo = appendText(zTableInfo, zTable, '"'); zTableInfo = appendText(zTableInfo, ");", 0); - rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); + rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); free(zTableInfo); if( rc!=SQLITE_OK || !pTableInfo ){ return 1; @@ -2399,7 +2399,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ return 1; } nByte = strlen30(zSql); - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; @@ -2425,7 +2425,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ xCloser(sCsv.in); return 1; } - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } sqlite3_free(zSql); if( rc ){ @@ -2452,7 +2452,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } zSql[j++] = ')'; zSql[j] = 0; - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); @@ -3548,11 +3548,13 @@ int main(int argc, char **argv){ int rc = 0; int warnInmemoryDb = 0; +#if !defined(USE_SYSTEM_SQLITE) || USE_SYSTEM_SQLITE!=1 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); exit(1); } +#endif Argv0 = argv[0]; main_init(&data); stdin_is_interactive = isatty(0); @@ -3645,6 +3647,11 @@ int main(int argc, char **argv){ #else fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; +#endif +#ifdef SQLITE_SHELL_DBNAME_PROC + { extern void SQLITE_SHELL_DBNAME_PROC(const char**); + SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename); + warnInmemoryDb = 0; } #endif } data.out = stdout; From 69b30abd598ed827cddeede9d133c83e579517c3 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 27 Feb 2014 15:11:52 +0000 Subject: [PATCH 41/66] A better way of handling the USE_SYSTEM_SQLITE #define in shell.c. FossilOrigin-Name: 51ce713c6ee91bdf0126155334dcc800b3daa509 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 7ec2f4b525..6892cecea2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s#defines\sto\sthe\scommand-line\sshell\ssource\scode\s(shell.c)\sso\sthat\sit\ncan\sbe\simported\sdirectly\sinto\sother\sprojects\s(ex:\sFossil)\sand\sused\swithout\s\nediting. -D 2014-02-27T15:04:13.436 +C A\sbetter\sway\sof\shandling\sthe\sUSE_SYSTEM_SQLITE\s#define\sin\sshell.c. +D 2014-02-27T15:11:52.919 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 -F src/shell.c 720e79facdae4787e7bfa577dae6b37a685244b0 +F src/shell.c bf75ce6bea4c8f56c1b46bee201c25acddffb675 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 06c2db875e6cabd81c2a153b2fa4aba03eaed268 -R b72dc063fb220f3231791c5c73300f82 +P a6690400235705ecc0d1a60dacff6ad5fb1f944a +R d9e4cc8c2428822c2a58511d3bd2892d U drh -Z d3f85704b6a67858d1c2e6d5e8f9f735 +Z 2ca6d024109a270000c3879d5e05ce0a diff --git a/manifest.uuid b/manifest.uuid index 03c67c2593..5a0d8578c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a6690400235705ecc0d1a60dacff6ad5fb1f944a \ No newline at end of file +51ce713c6ee91bdf0126155334dcc800b3daa509 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 3cd7aaf892..6815c489e6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3548,7 +3548,7 @@ int main(int argc, char **argv){ int rc = 0; int warnInmemoryDb = 0; -#if !defined(USE_SYSTEM_SQLITE) || USE_SYSTEM_SQLITE!=1 +#if USE_SYSTEM_SQLITE+0!=1 if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); From 3b9330f83ce327bd34acb6e48a910fcc41f2dd92 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 27 Feb 2014 20:44:18 +0000 Subject: [PATCH 42/66] Further changes to sqlite3VdbeRecordCompare(). FossilOrigin-Name: 570893740067a7caa952f259fa078cdf67017d71 --- manifest | 23 +-- manifest.uuid | 2 +- src/btree.c | 13 +- src/sqliteInt.h | 2 + src/vdbe.h | 5 +- src/vdbeaux.c | 495 +++++++++++++++++++++++++++++------------------- src/vdbesort.c | 5 + 7 files changed, 333 insertions(+), 212 deletions(-) diff --git a/manifest b/manifest index 2d70d7d908..e7df2f4996 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Attempt\sto\sspeed\sup\ssqlite3VdbeRecordCompare()\sby\svarious\smeans.\sThis\scode\sis\sin\san\sinterim\sstate. -D 2014-02-25T21:01:25.824 +C Further\schanges\sto\ssqlite3VdbeRecordCompare(). +D 2014-02-27T20:44:18.479 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -163,7 +163,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c f4d85c3e2e189a219965d6d4525330333735fd1d +F src/btree.c 77f175987c80ebec063f8653cb7d300776411413 F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0 @@ -221,7 +221,7 @@ F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 6d868994f476b616ddb1795a51aa83c331ef5a62 +F src/sqliteInt.h 7b42e02c1ca4599b5420d44cb549460b2348139a F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -278,13 +278,13 @@ F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a -F src/vdbe.h 0758eff7f1bf939bcafa377b2fafba4f5be63007 +F src/vdbe.h 6833579fc0fbdc1c933e34519064841abda5b9b3 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 988269c675ebb75a3610479840b65bcb8ea92647 +F src/vdbeaux.c 80e5315957377554c9011858f5afde61afedc181 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 25cc487244bf6ad647105c5adbc3052403dfd143 -F src/vdbesort.c 5144d84bd7d0d2545af1c6322edbbf07f97e3892 +F src/vdbesort.c 72290f12428973c2c6b9d4f95ad0a7c8181e1280 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 @@ -1151,10 +1151,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 23001a85cd334090cf6c70d4d7e722a01f4f6899 -R 04ade79c9b23add6f2d6adf0c34db1e4 -T *branch * experimental -T *sym-experimental * -T -sym-trunk * +P 85206e0bbac29adab52bef795f6d1479f2ae2c0e +R eb22cd7a0c8c7d3bc8c75c472c26dd6a U dan -Z d3f147085a7b8a8eca4578239439871b +Z 91158d7f280c804b2fe508b4511e22e9 diff --git a/manifest.uuid b/manifest.uuid index dd611d410f..927ab5603a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85206e0bbac29adab52bef795f6d1479f2ae2c0e \ No newline at end of file +570893740067a7caa952f259fa078cdf67017d71 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6c5f02403e..c0b04cc08c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4547,7 +4547,7 @@ int sqlite3BtreeMovetoUnpacked( int *pRes /* Write search results here */ ){ int rc; - int (*xRecordCompare)(int, const void*, UnpackedRecord*); + RecordCompare xRecordCompare; assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); @@ -4571,7 +4571,10 @@ int sqlite3BtreeMovetoUnpacked( if( pIdxKey ){ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); - assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1); + assert( pIdxKey->default_rc==1 + || pIdxKey->default_rc==0 + || pIdxKey->default_rc==-1 + ); } rc = moveToRoot(pCur); @@ -4658,14 +4661,14 @@ int sqlite3BtreeMovetoUnpacked( ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[1], pCell[1], 1, pIdxKey); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[2], pCell[2], 1, pIdxKey); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated @@ -4686,7 +4689,7 @@ int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = xRecordCompare(nCell, pCellKey, pIdxKey); + c = xRecordCompare(nCell, pCellKey, ((u8*)pCellKey)[0], 1, pIdxKey); sqlite3_free(pCellKey); } if( c<0 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 76dea413e0..b19a0bd453 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1592,6 +1592,8 @@ struct UnpackedRecord { u16 nField; /* Number of entries in apMem[] */ char default_rc; /* Comparison result if keys are equal */ Mem *aMem; /* Values */ + int r1; + int r2; }; diff --git a/src/vdbe.h b/src/vdbe.h index af07831faa..c08512e7aa 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -214,8 +214,9 @@ void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); -typedef int (*RecordCompare)(int,const void*, UnpackedRecord*); -RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *); +typedef int (*RecordCompare)(int,const void*,int,u32,UnpackedRecord*); +RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); +RecordCompare sqlite3VdbeFindSorterCompare(KeyInfo*); #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e817ccb23f..8ca605ebe6 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3123,90 +3123,102 @@ void sqlite3VdbeRecordUnpack( p->nField = u; } -static int vdbeRecordCompareString( +/* +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero +** or positive integer if key1 is less than, equal to or +** greater than key2. The {nKey1, pKey1} key must be a blob +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. +** +** Key1 and Key2 do not have to contain the same number of fields. +** The key with fewer fields is usually compares less than the +** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set +** and the common prefixes are equal, then key1 is less than key2. +** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are +** equal, then the keys are considered to be equal and +** the parts beyond the common prefix are ignored. +*/ +static int vdbeRecordComparePrev( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - const u8 *aKey1 = (const u8*)pKey1; - int szHdr; - int serial_type; - int res; + u32 d1; /* Offset into aKey[] of next data element */ + u32 idx1; /* Offset into aKey[] of next header element */ + u32 szHdr1; /* Number of bytes in header */ + int i = 0; + int rc = 0; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + KeyInfo *pKeyInfo; + Mem mem1; - szHdr = aKey1[0]; - getVarint32(&aKey1[1], serial_type); + pKeyInfo = pPKey2->pKeyInfo; + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ - if( serial_type<12 ){ - res = -1; /* (pKey1/nKey1) is a number or a null */ - }else if( !(serial_type & 0x01) ){ - res = +1; /* (pKey1/nKey1) is a blob */ - }else{ - int nCmp; - int nStr; - aKey1 = &aKey1[szHdr]; + /* Compilers may complain that mem1.u.i is potentially uninitialized. + ** We could initialize it, as shown here, to silence those complaints. + ** But in fact, mem1.u.i will never actually be used uninitialized, and doing + ** the unnecessary initialization has a measurable negative performance + ** impact, since this routine is a very high runner. And so, we choose + ** to ignore the compiler warnings and leave this variable uninitialized. + */ + /* mem1.u.i = 0; // not needed, here to silence compiler warning */ + + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); + assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->nField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type1; - nStr = (serial_type-12) / 2; - if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ - nCmp = MIN( pPKey2->aMem[0].n, nStr ); - res = memcmp(aKey1, pPKey2->aMem[0].z, nCmp); + /* Read the serial types for the next element in each key. */ + idx1 += getVarint32( aKey1+idx1, serial_type1 ); - if( res==0 ){ - res = nStr - pPKey2->aMem[0].n; - if( res==0 ) res = pPKey2->default_rc; + /* Verify that there is enough key space remaining to avoid + ** a buffer overread. The "d1+serial_type1+2" subexpression will + ** always be greater than or equal to the amount of required key space. + ** Use that approximation to avoid the more expensive call to + ** sqlite3VdbeSerialTypeLen() in the common case. + */ + if( d1+serial_type1+2>(u32)nKey1 + && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 + ){ + break; } - } - assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) - || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) - || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) - ); - return res; -} + /* Extract the values to be compared. + */ + d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); -static int vdbeRecordCompareInt( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - const u8 *aKey1 = (const u8*)pKey1; - int szHdr; - int serial_type; - int res; - - szHdr = aKey1[0]; - getVarint32(&aKey1[1], serial_type); - - if( serial_type==0 ){ - res = -1; /* NULL values are smaller than integers */ - }else if( serial_type>=12 ){ - res = +1; /* text/blob values are greater */ - }else{ - Mem mem; - sqlite3VdbeSerialGet(&aKey1[szHdr], serial_type, &mem); - if( mem.flags & MEM_Int ){ - i64 v = pPKey2->aMem[0].u.i; - if( v>mem.u.i ){ - res = -1; - }else if( vdefault_rc; - } - }else{ - double v = (double)pPKey2->aMem[0].u.i; - if( v>mem.r ){ - res = -1; - }else if( vdefault_rc; + /* Do the comparison + */ + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); + if( rc!=0 ){ + assert( mem1.zMalloc==0 ); /* See comment below */ + if( pKeyInfo->aSortOrder[i] ){ + rc = -rc; /* Invert the result for DESC sort order. */ } + return rc; } - } + i++; + }while( idx1nField ); - assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) - || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) - || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) - ); - return res; + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). + */ + assert( mem1.zMalloc==0 ); + + /* rc==0 here means that one of the keys ran out of fields and + ** all the fields up to that point were equal. Return the the default_rc + ** value. */ + return pPKey2->default_rc; } static int vdbeCompareMemString( @@ -3332,114 +3344,43 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ } -/* -** This function compares the two table rows or index records -** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or -** greater than key2. The {nKey1, pKey1} key must be a blob -** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 -** key must be a parsed key such as obtained from -** sqlite3VdbeParseRecord. -** -** Key1 and Key2 do not have to contain the same number of fields. -** The key with fewer fields is usually compares less than the -** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set -** and the common prefixes are equal, then key1 is less than key2. -** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are -** equal, then the keys are considered to be equal and -** the parts beyond the common prefix are ignored. -*/ -static int vdbeRecordComparePrev( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - u32 d1; /* Offset into aKey[] of next data element */ - u32 idx1; /* Offset into aKey[] of next header element */ - u32 szHdr1; /* Number of bytes in header */ - int i = 0; - int rc = 0; - const unsigned char *aKey1 = (const unsigned char *)pKey1; - KeyInfo *pKeyInfo; - Mem mem1; +static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ + switch( serial_type ){ + case 1: + return (char)aKey[0]; + case 2: + return ((char)aKey[0] << 8) | aKey[1]; + case 3: + return ((char)aKey[0] << 16) | (aKey[1] << 8) | aKey[2]; + case 4: + return ((char)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]; - pKeyInfo = pPKey2->pKeyInfo; - mem1.enc = pKeyInfo->enc; - mem1.db = pKeyInfo->db; - /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ - VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ - - /* Compilers may complain that mem1.u.i is potentially uninitialized. - ** We could initialize it, as shown here, to silence those complaints. - ** But in fact, mem1.u.i will never actually be used uninitialized, and doing - ** the unnecessary initialization has a measurable negative performance - ** impact, since this routine is a very high runner. And so, we choose - ** to ignore the compiler warnings and leave this variable uninitialized. - */ - /* mem1.u.i = 0; // not needed, here to silence compiler warning */ - - idx1 = getVarint32(aKey1, szHdr1); - d1 = szHdr1; - assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); - assert( pKeyInfo->aSortOrder!=0 ); - assert( pKeyInfo->nField>0 ); - assert( idx1<=szHdr1 || CORRUPT_DB ); - do{ - u32 serial_type1; - - /* Read the serial types for the next element in each key. */ - idx1 += getVarint32( aKey1+idx1, serial_type1 ); - - /* Verify that there is enough key space remaining to avoid - ** a buffer overread. The "d1+serial_type1+2" subexpression will - ** always be greater than or equal to the amount of required key space. - ** Use that approximation to avoid the more expensive call to - ** sqlite3VdbeSerialTypeLen() in the common case. - */ - if( d1+serial_type1+2>(u32)nKey1 - && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 - ){ - break; + case 5: { + i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; + u32 lsw = (aKey[4] << 8) | aKey[5]; + return (i64)( msw << 16 | (u64)lsw ); } - /* Extract the values to be compared. - */ - d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - - /* Do the comparison - */ - rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]); - if( rc!=0 ){ - assert( mem1.zMalloc==0 ); /* See comment below */ - if( pKeyInfo->aSortOrder[i] ){ - rc = -rc; /* Invert the result for DESC sort order. */ - } - return rc; + case 6: { + i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; + u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; + return (i64)( msw << 32 | (u64)lsw ); } - i++; - }while( idx1nField ); + } - /* No memory allocation is ever used on mem1. Prove this using - ** the following assert(). If the assert() fails, it indicates a - ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). - */ - assert( mem1.zMalloc==0 ); - - /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. Return the the default_rc - ** value. */ - return pPKey2->default_rc; + return (serial_type - 8); } - -int sqlite3VdbeRecordCompare( +static int vdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ + int szHdr1, /* Size of record header in bytes */ + u32 idx1, /* Offset of first type in header */ + UnpackedRecord *const pPKey2 /* Right key */ ){ - u32 d1; /* Offset into aKey[] of next data element */ - u32 idx1; /* Offset into aKey[] of next header element */ - u32 szHdr1; /* Number of bytes in header */ + u32 d1 = szHdr1; /* Offset into aKey[] of next data element */ int i = 0; int rc = 0; + Mem *pRhs = pPKey2->aMem; KeyInfo *pKeyInfo = pPKey2->pKeyInfo; const unsigned char *aKey1 = (const unsigned char *)pKey1; Mem mem1; @@ -3450,17 +3391,25 @@ int sqlite3VdbeRecordCompare( nCall++; #endif + /* If idx==0, then the caller has already determined that the first two + ** elements in the keys are equal. Fix the various stack variables so + ** that this routine begins comparing at the second field. */ + if( idx1==0 ){ + u32 s1; + assert( sqlite3VarintLen(szHdr1)==1 ); + idx1 = 1 + getVarint32(&aKey1[1], s1); + d1 += sqlite3VdbeSerialTypeLen(s1); + i = 1; + pRhs++; + } + VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ - - idx1 = getVarint32(aKey1, szHdr1); - d1 = szHdr1; assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); assert( pPKey2->pKeyInfo->aSortOrder!=0 ); assert( pPKey2->pKeyInfo->nField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ - Mem *pRhs = &pPKey2->aMem[i]; u32 serial_type; /* RHS is an integer */ @@ -3470,22 +3419,21 @@ int sqlite3VdbeRecordCompare( rc = +1; }else if( serial_type==0 ){ rc = -1; - }else{ + }else if( serial_type==7 ){ + double rhs = (double)pRhs->u.i; sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1); - if( serial_type==7 ){ - double rhs = (double)pRhs->u.i; - if( mem1.rrhs ){ - rc = +1; - } - }else{ - i64 rhs = pRhs->u.i; - if( mem1.u.irhs ){ - rc = +1; - } + if( mem1.rrhs ){ + rc = +1; + } + }else{ + i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]); + i64 rhs = pRhs->u.i; + if( lhsrhs ){ + rc = +1; } } } @@ -3579,6 +3527,7 @@ int sqlite3VdbeRecordCompare( } i++; + pRhs++; d1 += sqlite3VdbeSerialTypeLen(serial_type); idx1 += sqlite3VarintLen(serial_type); }while( idx1nField && d1<=nKey1 ); @@ -3596,20 +3545,184 @@ int sqlite3VdbeRecordCompare( return pPKey2->default_rc; } +static int vdbeRecordCompareInt( + int nKey1, const void *pKey1, /* Left key */ + int szHdr, + u32 idx1, + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey = &((const u8*)pKey1)[szHdr]; + int serial_type = ((const u8*)pKey1)[1]; + int res; + i64 v = pPKey2->aMem[0].u.i; + i64 lhs; + + switch( serial_type ){ + case 1: + lhs = (char)(aKey[0]); + break; + case 2: + lhs = 256*(signed char)aKey[0] + aKey[1]; + break; + case 3: + lhs = 65536*(char)aKey[0] | (aKey[1]<<8) | aKey[2]; + break; + case 4: + lhs = (int)(((u32)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]); + break; + + case 5: { + i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; + u32 lsw = (aKey[4] << 8) | aKey[5]; + lhs = (i64)( msw << 16 | (u64)lsw ); + break; + } + + case 6: { + i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; + u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; + lhs = (i64)( msw << 32 | (u64)lsw ); + break; + } + + case 8: + lhs = 0; + break; + + case 9: + lhs = 1; + break; + + default: + return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2); + } + + if( v>lhs ){ + res = pPKey2->r1; + }else if( vr2; + }else if( pPKey2->nField>1 ){ + res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2); + }else{ + res = pPKey2->default_rc; + } + + assert( (res==0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)>0) + || CORRUPT_DB + ); + return res; +} + +static int vdbeRecordCompareString( + int nKey1, const void *pKey1, /* Left key */ + int szHdr, + u32 idx1, + UnpackedRecord *pPKey2 /* Right key */ +){ + const u8 *aKey1 = (const u8*)pKey1; + int serial_type; + int res; + + getVarint32(&aKey1[1], serial_type); + + if( serial_type<12 ){ + res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ + }else if( !(serial_type & 0x01) ){ + res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ + }else{ + int nCmp; + int nStr; + aKey1 = &aKey1[szHdr]; + + nStr = (serial_type-12) / 2; + if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ + nCmp = MIN( pPKey2->aMem[0].n, nStr ); + res = memcmp(aKey1, pPKey2->aMem[0].z, nCmp); + + if( res==0 ){ + res = nStr - pPKey2->aMem[0].n; + if( res==0 ){ + if( pPKey2->nField>1 ){ + res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2); + }else{ + res = pPKey2->default_rc; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + }else if( res>0 ){ + res = pPKey2->r2; + }else{ + res = pPKey2->r1; + } + } + + assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) + || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) + || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) + || CORRUPT_DB + ); + return res; +} + + +int vdbeRecordCompareLargeHeader( + int nKey1, const void *pKey1, /* Left key */ + int dummy1, u32 dummy2, /* Unused arguments */ + UnpackedRecord *pPKey2 /* Right key */ +){ + int szHdr; + u32 idx1; + idx1 = getVarint32(((u8*)pKey1), szHdr); + return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2); +} + RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ - if( p->nField==1 && p->pKeyInfo->aSortOrder[0]==0 ){ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField) > 10 ){ + return vdbeRecordCompareLargeHeader; + }else{ int flags = p->aMem[0].flags; + if( p->pKeyInfo->aSortOrder[0] ){ + p->r1 = 1; + p->r2 = -1; + }else{ + p->r1 = -1; + p->r2 = 1; + } if( (flags & MEM_Int) ){ return vdbeRecordCompareInt; - }else if( (p->aMem[0].flags&(MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 - && p->pKeyInfo->aColl[0]==0 + } + if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 + && p->pKeyInfo->aColl[0]==0 ){ return vdbeRecordCompareString; } } - return sqlite3VdbeRecordCompare; + + return vdbeRecordCompare; } +RecordCompare sqlite3VdbeFindSorterCompare(KeyInfo *pKeyInfo){ + if( (pKeyInfo->nField + pKeyInfo->nXField) > 10 ){ + return vdbeRecordCompareLargeHeader; + } + return vdbeRecordCompare; +} + +int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *pPKey2 /* Right key */ +){ + int szHdr; + u32 idx1; + + idx1 = getVarint32(((u8*)pKey1), szHdr); + return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2); +} /* ** pCur points at an index entry created using the OP_MakeRecord opcode. diff --git a/src/vdbesort.c b/src/vdbesort.c index c4d15d6872..be5a6064c2 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -105,6 +105,7 @@ struct VdbeSorter { sqlite3_file *pTemp1; /* PMA file 1 */ SorterRecord *pRecord; /* Head of in-memory record list */ UnpackedRecord *pUnpacked; /* Used to unpack keys */ + RecordCompare xRecordCompare; /* Record compare function */ }; /* @@ -412,7 +413,10 @@ static void vdbeSorterCompare( assert( r2->default_rc==0 ); } +#if 0 *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2); +#endif + *pRes = pSorter->xRecordCompare(nKey1, pKey1, *((u8*)pKey1), 1, r2); } /* @@ -488,6 +492,7 @@ int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ if( mxCachemxPmaSize = mxCache * pgsz; } + pSorter->xRecordCompare = sqlite3VdbeFindSorterCompare(pCsr->pKeyInfo); return SQLITE_OK; } From 063d4a041a5f1bf8938c7a01c2c4c656bf9384ce Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 28 Feb 2014 09:48:30 +0000 Subject: [PATCH 43/66] Minor tweak to vdbeRecordCompareInt(). FossilOrigin-Name: 284bde0ee20261737446eb8f5b6b36ad9bc3f355 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index ab9697fb73..3b948c33cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\slatest\strunk\schanges. -D 2014-02-27T20:52:26.303 +C Minor\stweak\sto\svdbeRecordCompareInt(). +D 2014-02-28T09:48:30.694 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a F src/vdbe.h 6833579fc0fbdc1c933e34519064841abda5b9b3 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 80e5315957377554c9011858f5afde61afedc181 +F src/vdbeaux.c fc95358566a454fadcf17858d582ff38c2e55c54 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 25cc487244bf6ad647105c5adbc3052403dfd143 F src/vdbesort.c 72290f12428973c2c6b9d4f95ad0a7c8181e1280 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 570893740067a7caa952f259fa078cdf67017d71 51ce713c6ee91bdf0126155334dcc800b3daa509 -R f4fa5a4e2d9c34dae5f26cd35d7bbdb3 +P 8f30b09518d23c3f6cecd244a66ef918fdb55323 +R c980d8afe2372c0277fee962182b32ac U dan -Z 489718005e4064c97910e87ca8ac5405 +Z 7196a891773623dba164b983a9b4c516 diff --git a/manifest.uuid b/manifest.uuid index ab94dbb62a..52a4739a0c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8f30b09518d23c3f6cecd244a66ef918fdb55323 \ No newline at end of file +284bde0ee20261737446eb8f5b6b36ad9bc3f355 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8ca605ebe6..8468d13b96 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3558,6 +3558,7 @@ static int vdbeRecordCompareInt( i64 lhs; switch( serial_type ){ + case 1: lhs = (char)(aKey[0]); break; @@ -3593,6 +3594,15 @@ static int vdbeRecordCompareInt( lhs = 1; break; + /* This case could be removed without changing the results of running + ** this code. Including it causes gcc to generate a faster switch + ** statement (since the range of switch targets now starts at zero and + ** is contiguous)) but does not cause any duplicate code to be generated + ** (as gcc is clever enough to combine the two like cases). Other + ** compilers might be similar. */ + case 0: case 7: + return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2); + default: return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2); } @@ -3602,8 +3612,12 @@ static int vdbeRecordCompareInt( }else if( vr2; }else if( pPKey2->nField>1 ){ + /* The first fields of the two keys are equal. Compare the trailing + ** fields. */ res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2); }else{ + /* The first fields of the two keys are equal and there are no trailing + ** fields. Return pPKey2->default_rc in this case. */ res = pPKey2->default_rc; } From 597515d70c009a74c54dd8a82acb2bfc66cb2664 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 28 Feb 2014 18:39:51 +0000 Subject: [PATCH 44/66] Update some test cases that deal with corrupt databases. FossilOrigin-Name: 3a09f5605ac7c6e503eb10acfdc607010414d917 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- src/vdbemem.c | 1 - test/analyze9.test | 3 +++ test/corruptG.test | 2 +- test/pragma.test | 15 ++++++++++----- 7 files changed, 26 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 3b948c33cf..f20f7a0353 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\stweak\sto\svdbeRecordCompareInt(). -D 2014-02-28T09:48:30.694 +C Update\ssome\stest\scases\sthat\sdeal\swith\scorrupt\sdatabases. +D 2014-02-28T18:39:51.462 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,9 +281,9 @@ F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a F src/vdbe.h 6833579fc0fbdc1c933e34519064841abda5b9b3 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c fc95358566a454fadcf17858d582ff38c2e55c54 +F src/vdbeaux.c aad5345869c110f45074e2c1ca230e623b1ba182 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 25cc487244bf6ad647105c5adbc3052403dfd143 +F src/vdbemem.c 93fc3f13ebe6809ebaac8d0a17c812ec053ba233 F src/vdbesort.c 72290f12428973c2c6b9d4f95ad0a7c8181e1280 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd @@ -310,7 +310,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test 339e87723cd4dc158dc5e9095acd8df9e87faf79 +F test/analyze9.test e072a5172d55afcba98d6ca6a219ce8878c2f5c9 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b @@ -402,7 +402,7 @@ F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 -F test/corruptG.test c150f156dace653c00a121ad0f5772a0568c41ba +F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039 F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 @@ -735,7 +735,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04 -F test/pragma.test c1bc3a29f664b57d0ae40b498ad31f370de8daa6 +F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 8f30b09518d23c3f6cecd244a66ef918fdb55323 -R c980d8afe2372c0277fee962182b32ac +P 284bde0ee20261737446eb8f5b6b36ad9bc3f355 +R 75b55639e7bdd048d8263d0acfa3cf8a U dan -Z 7196a891773623dba164b983a9b4c516 +Z d116a418c5c97c83b8ebfe7a3e655c3c diff --git a/manifest.uuid b/manifest.uuid index 52a4739a0c..9cb218f1b4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -284bde0ee20261737446eb8f5b6b36ad9bc3f355 \ No newline at end of file +3a09f5605ac7c6e503eb10acfdc607010414d917 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8468d13b96..007f4e650d 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3597,7 +3597,7 @@ static int vdbeRecordCompareInt( /* This case could be removed without changing the results of running ** this code. Including it causes gcc to generate a faster switch ** statement (since the range of switch targets now starts at zero and - ** is contiguous)) but does not cause any duplicate code to be generated + ** is contiguous) but does not cause any duplicate code to be generated ** (as gcc is clever enough to combine the two like cases). Other ** compilers might be similar. */ case 0: case 7: diff --git a/src/vdbemem.c b/src/vdbemem.c index 4936f40016..bc703e8eeb 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -913,7 +913,6 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ if( pRec->pKeyInfo ){ assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); assert( pRec->pKeyInfo->enc==ENC(db) ); - pRec->flags = UNPACKED_PREFIX_MATCH; pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); for(i=0; iaMem[i].flags = MEM_Null; diff --git a/test/analyze9.test b/test/analyze9.test index 0fce55ac4b..820bcdb0e7 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -326,6 +326,7 @@ do_execsql_test 6.2 { reset_db sqlite3_db_config_lookaside db 0 0 0 +database_may_be_corrupt do_execsql_test 7.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); @@ -366,6 +367,8 @@ do_execsql_test 7.5 { SELECT * FROM t1 WHERE a = 5; } {5 5} +database_never_corrupt + #------------------------------------------------------------------------- # reset_db diff --git a/test/corruptG.test b/test/corruptG.test index 11253fd12c..1ec5d6f6a9 100644 --- a/test/corruptG.test +++ b/test/corruptG.test @@ -76,6 +76,6 @@ do_test 2.1 { # incorrect answer from a corrupt database file, that is OK. If the # result below changes, that just means that "undefined behavior" has # changed. -} {0 52} +} {/0 .*/} finish_test diff --git a/test/pragma.test b/test/pragma.test index fcbb1808fa..8f54e695d7 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -1602,11 +1602,16 @@ Multiple uses for byte 672 of page 15} set auxerr {*** in database aux *** Multiple uses for byte 672 of page 15} +set mainerr {/{\*\*\* in database main \*\*\* +Multiple uses for byte 672 of page 15}.*/} +set auxerr {/{\*\*\* in database aux \*\*\* +Multiple uses for byte 672 of page 15}.*/} + do_test 22.2 { catch { db close } sqlite3 db testerr.db execsql { PRAGMA integrity_check } -} [list $mainerr] +} $mainerr do_test 22.3.1 { catch { db close } @@ -1615,13 +1620,13 @@ do_test 22.3.1 { ATTACH 'testerr.db' AS 'aux'; PRAGMA integrity_check; } -} [list $auxerr] +} $auxerr do_test 22.3.2 { execsql { PRAGMA main.integrity_check; } } {ok} do_test 22.3.3 { execsql { PRAGMA aux.integrity_check; } -} [list $auxerr] +} $auxerr do_test 22.4.1 { catch { db close } @@ -1630,10 +1635,10 @@ do_test 22.4.1 { ATTACH 'test.db' AS 'aux'; PRAGMA integrity_check; } -} [list $mainerr] +} $mainerr do_test 22.4.2 { execsql { PRAGMA main.integrity_check; } -} [list $mainerr] +} $mainerr do_test 22.4.3 { execsql { PRAGMA aux.integrity_check; } } {ok} From 07901eb8c3ab341c5fe5119069e39ebf91117b39 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Feb 2014 19:37:45 +0000 Subject: [PATCH 45/66] Provide an #ifdef in shell.c to work around issues when cross-compiling from Ubuntu to windows. FossilOrigin-Name: 0a3579d9b9d2a60bb85a9811bc7936edb88debae --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 6892cecea2..e1c9e01261 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C A\sbetter\sway\sof\shandling\sthe\sUSE_SYSTEM_SQLITE\s#define\sin\sshell.c. -D 2014-02-27T15:11:52.919 +C Provide\san\s#ifdef\sin\sshell.c\sto\swork\saround\sissues\swhen\scross-compiling\nfrom\sUbuntu\sto\swindows. +D 2014-02-28T19:37:45.291 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 -F src/shell.c bf75ce6bea4c8f56c1b46bee201c25acddffb675 +F src/shell.c e6d573326f12901df3801777831b48bd80c11dab F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a6690400235705ecc0d1a60dacff6ad5fb1f944a -R d9e4cc8c2428822c2a58511d3bd2892d +P 51ce713c6ee91bdf0126155334dcc800b3daa509 +R f77dc22964f582c1f952cbee70cf06fb U drh -Z 2ca6d024109a270000c3879d5e05ce0a +Z 5ee6ba31533a91dba4172ad5a5e2ece1 diff --git a/manifest.uuid b/manifest.uuid index 5a0d8578c1..297558a6f1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -51ce713c6ee91bdf0126155334dcc800b3daa509 \ No newline at end of file +0a3579d9b9d2a60bb85a9811bc7936edb88debae \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 6815c489e6..0709f6c41e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -65,7 +65,9 @@ #if defined(_WIN32) || defined(WIN32) # include #define isatty(h) _isatty(h) -#define access(f,m) _access((f),(m)) +#ifndef access +# define access(f,m) _access((f),(m)) +#endif #undef popen #define popen _popen #undef pclose From efbf3b1a1066b541123e065c9a1469462b1bec27 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 28 Feb 2014 20:47:24 +0000 Subject: [PATCH 46/66] In the command-line shell add the (undocumented and unsupported) ".eqp" command and -eqp command-line option, to cause EXPLAIN QUERY PLAN to be run on each SQL statement as it is evaluated. Intended use is for analysis of the query planner. FossilOrigin-Name: e6ecf7337658624d664e1e71ba3fc527fd6578c1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index e1c9e01261..3686379a18 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\san\s#ifdef\sin\sshell.c\sto\swork\saround\sissues\swhen\scross-compiling\nfrom\sUbuntu\sto\swindows. -D 2014-02-28T19:37:45.291 +C In\sthe\scommand-line\sshell\sadd\sthe\s(undocumented\sand\sunsupported)\s".eqp"\ncommand\sand\s-eqp\scommand-line\soption,\sto\scause\sEXPLAIN\sQUERY\sPLAN\sto\sbe\nrun\son\seach\sSQL\sstatement\sas\sit\sis\sevaluated.\s\sIntended\suse\sis\sfor\sanalysis\nof\sthe\squery\splanner. +D 2014-02-28T20:47:24.221 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 -F src/shell.c e6d573326f12901df3801777831b48bd80c11dab +F src/shell.c 7bf07bcacb181ecc3fc3ccacfdfeb4084aee67ed F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 51ce713c6ee91bdf0126155334dcc800b3daa509 -R f77dc22964f582c1f952cbee70cf06fb +P 0a3579d9b9d2a60bb85a9811bc7936edb88debae +R 195e6e751f71ffa9e9cfd28d6f8e532d U drh -Z 5ee6ba31533a91dba4172ad5a5e2ece1 +Z d48791979092ee78fb00c8a21c663b3b diff --git a/manifest.uuid b/manifest.uuid index 297558a6f1..6108cf5bed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a3579d9b9d2a60bb85a9811bc7936edb88debae \ No newline at end of file +e6ecf7337658624d664e1e71ba3fc527fd6578c1 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 0709f6c41e..7ecedfd3c1 100644 --- a/src/shell.c +++ b/src/shell.c @@ -446,6 +446,7 @@ struct previous_mode_data { struct callback_data { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ + int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */ int statsOn; /* True to display memory stats before each finalize */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ @@ -1302,6 +1303,23 @@ static int shell_exec( fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); } + /* Show the EXPLAIN QUERY PLAN if .eqp is on */ + if( pArg && pArg->autoEQP ){ + sqlite3_stmt *pExplain; + char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt)); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ + fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); + fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); + fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); + } + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + } + /* Output TESTCTRL_EXPLAIN text of requested */ if( pArg && pArg->mode==MODE_Explain ){ const char *zExplain = 0; @@ -2301,6 +2319,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ p->echoOn = booleanValue(azArg[1]); }else + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){ + p->autoEQP = booleanValue(azArg[1]); + }else + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); rc = 2; @@ -2873,6 +2895,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){ int i; fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); @@ -3710,6 +3733,8 @@ int main(int argc, char **argv){ data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; + }else if( strcmp(z,"-eqp")==0 ){ + data.autoEQP = 1; }else if( strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( strcmp(z,"-bail")==0 ){ From defbd9dade8a135ebc79c14efafe1a22c0f99c94 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 1 Mar 2014 14:45:18 +0000 Subject: [PATCH 47/66] Add extra assert() statements trying to catch a Mem object in an inconsistent state. FossilOrigin-Name: 4aeb3ae435c78070232fef21a147fde4e1c5cd31 --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- src/vdbe.c | 4 ++++ src/vdbeInt.h | 18 ++++++++++++++++++ src/vdbeaux.c | 1 + src/vdbemem.c | 8 ++------ 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 3686379a18..8fbb26ce51 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\scommand-line\sshell\sadd\sthe\s(undocumented\sand\sunsupported)\s".eqp"\ncommand\sand\s-eqp\scommand-line\soption,\sto\scause\sEXPLAIN\sQUERY\sPLAN\sto\sbe\nrun\son\seach\sSQL\sstatement\sas\sit\sis\sevaluated.\s\sIntended\suse\sis\sfor\sanalysis\nof\sthe\squery\splanner. -D 2014-02-28T20:47:24.221 +C Add\sextra\sassert()\sstatements\strying\sto\scatch\sa\sMem\sobject\sin\san\sinconsistent\nstate. +D 2014-03-01T14:45:18.939 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,13 +277,13 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 6c8f28911e702151c8ef03c568db5a066d3a85d4 +F src/vdbe.c e9eda47b8d8410d35840589daf8f3177efa04478 F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8 -F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 +F src/vdbeInt.h fa0cadb90633d260f0c7d21f68a2ec5b1c6900e2 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 8b8eeb3cd89e4b3d4f40186344915b49b7c1c0f7 +F src/vdbeaux.c 087e7c75643157a903c9794294f4ff45cec28e7e F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda +F src/vdbemem.c 7db453561091f0ed8fc7c96ee635cc612334025f F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd @@ -1152,7 +1152,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 0a3579d9b9d2a60bb85a9811bc7936edb88debae -R 195e6e751f71ffa9e9cfd28d6f8e532d +P e6ecf7337658624d664e1e71ba3fc527fd6578c1 +R ac78e315b388dc3aeb5c2c8983219f64 +T *branch * enhanced-mem-check +T *sym-enhanced-mem-check * +T -sym-trunk * U drh -Z d48791979092ee78fb00c8a21c663b3b +Z 099f8256c2a0fcf00ebef2162229fe0b diff --git a/manifest.uuid b/manifest.uuid index 6108cf5bed..aa3e8c1f3c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e6ecf7337658624d664e1e71ba3fc527fd6578c1 \ No newline at end of file +4aeb3ae435c78070232fef21a147fde4e1c5cd31 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 5ab0127658..cca69092a2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -600,18 +600,21 @@ int sqlite3VdbeExec( assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); + assert( memSanity1(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); + assert( memSanity1(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); + assert( memSanity1(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ @@ -2460,6 +2463,7 @@ case OP_Column: { */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); + assert( memSanity1(pDest) ); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 88c072adec..56ea39ffc3 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -232,6 +232,24 @@ struct Mem { #define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif +/* +** A sanity check on a Mem object and especially the Mem.z field. +** This check says that no more than one of the following may be true: +** (1) Mem.z comes from Mem.zMalloc +** (2) Mem.z has a destructor Mem.xDel +** (3) Mem.z is an ephemeral string +** (4) Mem.z is a static string +** +** Use only inside of an assert() as follows: assert( memSanify(pMem) ); +*/ +#ifdef SQLITE_DEBUG +#define memSanity1(p) \ + ((((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + \ + ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) + \ + (((p)->flags&MEM_Ephem) ? 1 : 0) + \ + (((p)->flags&MEM_Static) ? 1 : 0) <= 1 ) +#endif + /* ** Each auxilliary data pointer stored by a user defined function ** implementation calling sqlite3_set_auxdata() is stored in an instance diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ef70f8ae3f..c22003f461 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1220,6 +1220,7 @@ static void releaseMemArray(Mem *p, int N){ } for(pEnd=&p[N]; pz is discarded. */ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ - assert( 1 >= - ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + - (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + - ((pMem->flags&MEM_Ephem) ? 1 : 0) + - ((pMem->flags&MEM_Static) ? 1 : 0) - ); + assert( memSanity1(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); /* If the bPreserve flag is set to true, then the memory cell must already @@ -292,6 +287,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ ** (Mem.memType==MEM_Str). */ void sqlite3VdbeMemRelease(Mem *p){ + assert( memSanity1(p) ); VdbeMemRelease(p); if( p->zMalloc ){ sqlite3DbFree(p->db, p->zMalloc); From 75fd054201c0ba287252bd53b6fd60067fc2c409 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 1 Mar 2014 16:24:44 +0000 Subject: [PATCH 48/66] Factor the Mem invariant checker into a separate procedure (rather than a macro) so that it can be more easily extended. FossilOrigin-Name: 354699d50e7d251504a7b3d6fbec9e5bcf99557f --- manifest | 21 +++++++++------------ manifest.uuid | 2 +- src/vdbe.c | 8 ++++---- src/vdbeInt.h | 19 +------------------ src/vdbeaux.c | 2 +- src/vdbemem.c | 22 ++++++++++++++++++++-- 6 files changed, 36 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index 8fbb26ce51..75bec54679 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sextra\sassert()\sstatements\strying\sto\scatch\sa\sMem\sobject\sin\san\sinconsistent\nstate. -D 2014-03-01T14:45:18.939 +C Factor\sthe\sMem\sinvariant\schecker\sinto\sa\sseparate\sprocedure\s(rather\sthan\sa\nmacro)\sso\sthat\sit\scan\sbe\smore\seasily\sextended. +D 2014-03-01T16:24:44.768 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,13 +277,13 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c e9eda47b8d8410d35840589daf8f3177efa04478 +F src/vdbe.c 9abaa1ebb8b98e33121ea1aade1022fdc195b464 F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8 -F src/vdbeInt.h fa0cadb90633d260f0c7d21f68a2ec5b1c6900e2 +F src/vdbeInt.h a82d5ab4fd8138bdff7de4a267ea5c04e4cbb370 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 087e7c75643157a903c9794294f4ff45cec28e7e +F src/vdbeaux.c 2f97cd756e2704b06006b398ce468f0bcc006055 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 7db453561091f0ed8fc7c96ee635cc612334025f +F src/vdbemem.c 8c84ec056c7934cef359f4d49fa32b856eeffd88 F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd @@ -1152,10 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e6ecf7337658624d664e1e71ba3fc527fd6578c1 -R ac78e315b388dc3aeb5c2c8983219f64 -T *branch * enhanced-mem-check -T *sym-enhanced-mem-check * -T -sym-trunk * +P 4aeb3ae435c78070232fef21a147fde4e1c5cd31 +R c42d4082e634170a16f76850fb72106d U drh -Z 099f8256c2a0fcf00ebef2162229fe0b +Z e1bae2e998058d57d79a76345aaf3403 diff --git a/manifest.uuid b/manifest.uuid index aa3e8c1f3c..7b0fa50ebd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4aeb3ae435c78070232fef21a147fde4e1c5cd31 \ No newline at end of file +354699d50e7d251504a7b3d6fbec9e5bcf99557f \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index cca69092a2..c8e837b81b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -600,21 +600,21 @@ int sqlite3VdbeExec( assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p1]) ); - assert( memSanity1(&aMem[pOp->p1]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) ); REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); } if( (pOp->opflags & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p2]) ); - assert( memSanity1(&aMem[pOp->p2]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) ); REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); } if( (pOp->opflags & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=(p->nMem-p->nCursor) ); assert( memIsValid(&aMem[pOp->p3]) ); - assert( memSanity1(&aMem[pOp->p3]) ); + assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) ); REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); } if( (pOp->opflags & OPFLG_OUT2)!=0 ){ @@ -2463,7 +2463,7 @@ case OP_Column: { */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); - assert( memSanity1(pDest) ); + assert( sqlite3VdbeCheckMemInvariants(pDest) ); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 56ea39ffc3..047a4f2697 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -232,24 +232,6 @@ struct Mem { #define memIsValid(M) ((M)->flags & MEM_Undefined)==0 #endif -/* -** A sanity check on a Mem object and especially the Mem.z field. -** This check says that no more than one of the following may be true: -** (1) Mem.z comes from Mem.zMalloc -** (2) Mem.z has a destructor Mem.xDel -** (3) Mem.z is an ephemeral string -** (4) Mem.z is a static string -** -** Use only inside of an assert() as follows: assert( memSanify(pMem) ); -*/ -#ifdef SQLITE_DEBUG -#define memSanity1(p) \ - ((((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + \ - ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) + \ - (((p)->flags&MEM_Ephem) ? 1 : 0) + \ - (((p)->flags&MEM_Static) ? 1 : 0) <= 1 ) -#endif - /* ** Each auxilliary data pointer stored by a user defined function ** implementation calling sqlite3_set_auxdata() is stored in an instance @@ -474,6 +456,7 @@ int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); #ifdef SQLITE_DEBUG void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*); +int sqlite3VdbeCheckMemInvariants(Mem*); #endif #ifndef SQLITE_OMIT_FOREIGN_KEY diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c22003f461..4a541e0d48 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1220,7 +1220,7 @@ static void releaseMemArray(Mem *p, int N){ } for(pEnd=&p[N]; pzMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + + ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) + + (((p)->flags&MEM_Ephem) ? 1 : 0) + + (((p)->flags&MEM_Static) ? 1 : 0) <= 1 ); + return 1; +} +#endif + + /* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is @@ -67,7 +85,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ ** in pMem->z is discarded. */ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ - assert( memSanity1(pMem) ); + assert( sqlite3VdbeCheckMemInvariants(pMem) ); assert( (pMem->flags&MEM_RowSet)==0 ); /* If the bPreserve flag is set to true, then the memory cell must already @@ -287,7 +305,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ ** (Mem.memType==MEM_Str). */ void sqlite3VdbeMemRelease(Mem *p){ - assert( memSanity1(p) ); + assert( sqlite3VdbeCheckMemInvariants(p) ); VdbeMemRelease(p); if( p->zMalloc ){ sqlite3DbFree(p->db, p->zMalloc); From c91b2fd310e4138b1a36c3f3c418a21a6c2ae895 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 1 Mar 2014 18:13:23 +0000 Subject: [PATCH 49/66] Change the MEM_Dyn flag so that it means that Mem.xDel exists and must be used to free the string or blob. Add tighter invariant checks on Mem. FossilOrigin-Name: 44e1c33767cae3bf2cbd2238831fe67197009b43 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/utf.c | 3 +-- src/vdbe.c | 23 ++++++++++++----------- src/vdbeInt.h | 2 +- src/vdbeaux.c | 6 +++--- src/vdbemem.c | 43 +++++++++++++++++++++++++++++++------------ 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/manifest b/manifest index 75bec54679..5a221fb21d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Factor\sthe\sMem\sinvariant\schecker\sinto\sa\sseparate\sprocedure\s(rather\sthan\sa\nmacro)\sso\sthat\sit\scan\sbe\smore\seasily\sextended. -D 2014-03-01T16:24:44.768 +C Change\sthe\sMEM_Dyn\sflag\sso\sthat\sit\smeans\sthat\sMem.xDel\sexists\sand\smust\sbe\nused\sto\sfree\sthe\sstring\sor\sblob.\s\sAdd\stighter\sinvariant\schecks\son\sMem. +D 2014-03-01T18:13:23.744 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -274,16 +274,16 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 -F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 +F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 9abaa1ebb8b98e33121ea1aade1022fdc195b464 +F src/vdbe.c cbed4957185bfee7e585dce208d8ec4cd87179c2 F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8 -F src/vdbeInt.h a82d5ab4fd8138bdff7de4a267ea5c04e4cbb370 +F src/vdbeInt.h d55cab859abb2c6656911497ae74eba9dcf34e28 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 2f97cd756e2704b06006b398ce468f0bcc006055 +F src/vdbeaux.c 89a0ad3b2ecdbe71cf827a1f99d0ae51eccd6cce F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 8c84ec056c7934cef359f4d49fa32b856eeffd88 +F src/vdbemem.c 868a498a670c08344a594a9d5903a3ff330916a7 F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 4aeb3ae435c78070232fef21a147fde4e1c5cd31 -R c42d4082e634170a16f76850fb72106d +P 354699d50e7d251504a7b3d6fbec9e5bcf99557f +R 0950c7cf1a1151e6071aa7a5599d1f4e U drh -Z e1bae2e998058d57d79a76345aaf3403 +Z c9678592d0817ad1269cd44af9e6bf96 diff --git a/manifest.uuid b/manifest.uuid index 7b0fa50ebd..764bf41b7a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -354699d50e7d251504a7b3d6fbec9e5bcf99557f \ No newline at end of file +44e1c33767cae3bf2cbd2238831fe67197009b43 \ No newline at end of file diff --git a/src/utf.c b/src/utf.c index ecb3ea03b8..96b679fff4 100644 --- a/src/utf.c +++ b/src/utf.c @@ -317,7 +317,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ sqlite3VdbeMemRelease(pMem); pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); pMem->enc = desiredEnc; - pMem->flags |= (MEM_Term|MEM_Dyn); + pMem->flags |= (MEM_Term); pMem->z = (char*)zOut; pMem->zMalloc = pMem->z; @@ -445,7 +445,6 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){ } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); - assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed ); assert( m.z || db->mallocFailed ); return m.z; } diff --git a/src/vdbe.c b/src/vdbe.c index c8e837b81b..8e5a3da00f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -152,7 +152,7 @@ int sqlite3_found_count = 0; ** ** This routine converts an ephemeral string into a dynamically allocated ** string that the register itself controls. In other words, it -** converts an MEM_Ephem string into an MEM_Dyn string. +** converts an MEM_Ephem string into a string with P.z==P.zMalloc. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ @@ -716,7 +716,7 @@ check_for_interrupt: case OP_Gosub: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) ); pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = pc; @@ -789,7 +789,7 @@ case OP_EndCoroutine: { /* in1 */ case OP_Yield: { /* in1, jump */ int pcDest; pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); + assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; pIn1->u.i = pc; @@ -962,10 +962,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ if( rc==SQLITE_TOOBIG ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->zMalloc==pOut->z ); - assert( pOut->flags & MEM_Dyn ); + assert( VdbeMemDynamic(pOut)==0 ); pOut->zMalloc = 0; pOut->flags |= MEM_Static; - pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3DbFree(db, pOp->p4.z); } @@ -1101,14 +1100,16 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); + VdbeMemRelease(pOut); zMalloc = pOut->zMalloc; - pOut->zMalloc = 0; - sqlite3VdbeMemMove(pOut, pIn1); + memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ pOut->pScopyFrom += p1 - pOp->p2; } #endif + pIn1->flags = MEM_Undefined; + pIn1->xDel = 0; pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; @@ -1285,10 +1286,10 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - MemSetTypeFlag(pOut, MEM_Str); if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ goto no_mem; } + MemSetTypeFlag(pOut, MEM_Str); if( pOut!=pIn2 ){ memcpy(pOut->z, pIn2->z, pIn2->n); } @@ -2501,8 +2502,8 @@ case OP_Column: { ** This prevents a memory copy. */ if( sMem.zMalloc ){ assert( sMem.z==sMem.zMalloc ); - assert( !(pDest->flags & MEM_Dyn) ); - assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z ); + assert( VdbeMemDynamic(pDest)==0 ); + assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z ); pDest->flags &= ~(MEM_Ephem|MEM_Static); pDest->flags |= MEM_Term; pDest->z = sMem.z; @@ -2685,7 +2686,7 @@ case OP_MakeRecord: { assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut->n = (int)nByte; - pOut->flags = MEM_Blob | MEM_Dyn; + pOut->flags = MEM_Blob; pOut->xDel = 0; if( nZero ){ pOut->u.nZero = nZero; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 047a4f2697..c16baff685 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -208,7 +208,7 @@ struct Mem { ** string is \000 or \u0000 terminated */ #define MEM_Term 0x0200 /* String rep is nul terminated */ -#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */ +#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ #define MEM_Static 0x0800 /* Mem.z points to a static string */ #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 4a541e0d48..39be964093 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1414,7 +1414,7 @@ int sqlite3VdbeList( assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; zP4 = displayP4(pOp, pMem->z, 32); if( zP4!=pMem->z ){ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); @@ -1431,7 +1431,7 @@ int sqlite3VdbeList( assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; pMem->n = 2; sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ pMem->memType = MEM_Str; @@ -1443,7 +1443,7 @@ int sqlite3VdbeList( assert( p->db->mallocFailed ); return SQLITE_ERROR; } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->flags = MEM_Str|MEM_Term; pMem->n = displayComment(pOp, zP4, pMem->z, 500); pMem->memType = MEM_Str; pMem->enc = SQLITE_UTF8; diff --git a/src/vdbemem.c b/src/vdbemem.c index 532cd58d9e..3c9412a700 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -26,11 +26,29 @@ ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); */ int sqlite3VdbeCheckMemInvariants(Mem *p){ - assert( - (((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) + - ((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) + - (((p)->flags&MEM_Ephem) ? 1 : 0) + - (((p)->flags&MEM_Static) ? 1 : 0) <= 1 ); + /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor + ** function for Mem.z + */ + assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); + assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 ); + + /* If p holds a string or blob, the Mem.z must point to exactly + ** one of the following: + ** + ** (1) Memory in Mem.zMalloc and managed by the Mem object + ** (2) Memory to be freed using Mem.xDel + ** (3) An ephermal string or blob + ** (4) A static string or blob + */ + if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){ + assert( + ((p->z==p->zMalloc)? 1 : 0) + + ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + + ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1 + ); + } + return 1; } #endif @@ -103,7 +121,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } if( pMem->zMalloc==0 ){ - sqlite3VdbeMemRelease(pMem); + VdbeMemRelease(pMem); pMem->flags = MEM_Null; return SQLITE_NOMEM; } @@ -112,13 +130,13 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } - if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){ - assert( pMem->xDel!=SQLITE_DYNAMIC ); + if( (pMem->flags&MEM_Dyn)!=0 ){ + assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC ); pMem->xDel((void *)(pMem->z)); } pMem->z = pMem->zMalloc; - pMem->flags &= ~(MEM_Ephem|MEM_Static); + pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static); pMem->xDel = 0; return SQLITE_OK; } @@ -287,9 +305,9 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); - }else if( p->flags&MEM_Dyn && p->xDel ){ + }else if( p->flags&MEM_Dyn ){ assert( (p->flags&MEM_RowSet)==0 ); - assert( p->xDel!=SQLITE_DYNAMIC ); + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); p->xDel((void *)p->z); p->xDel = 0; }else if( p->flags&MEM_RowSet ){ @@ -643,6 +661,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ VdbeMemRelease(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; + pTo->xDel = 0; if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ @@ -922,7 +941,7 @@ int sqlite3VdbeMemFromBtree( pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ - pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; + pMem->flags = MEM_Blob|MEM_Term; pMem->enc = 0; pMem->memType = MEM_Blob; if( key ){ From 3833e934d3b219dfb05d9a38333d1c8d7bfe4f82 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 1 Mar 2014 19:44:56 +0000 Subject: [PATCH 50/66] Remove the vdbeRecordCompareLargeHeader function. Fix some other details. FossilOrigin-Name: 3861e853105cb8da344c7eebd2e455622b26395e --- manifest | 22 ++--- manifest.uuid | 2 +- src/btree.c | 6 +- src/sqliteInt.h | 7 +- src/vdbe.h | 5 +- src/vdbeaux.c | 226 ++++++++++++++++++++++++------------------------ src/vdbesort.c | 7 +- src/where.c | 8 +- 8 files changed, 142 insertions(+), 141 deletions(-) diff --git a/manifest b/manifest index f20f7a0353..08b453f312 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\ssome\stest\scases\sthat\sdeal\swith\scorrupt\sdatabases. -D 2014-02-28T18:39:51.462 +C Remove\sthe\svdbeRecordCompareLargeHeader\sfunction.\sFix\ssome\sother\sdetails. +D 2014-03-01T19:44:56.574 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -163,7 +163,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 77f175987c80ebec063f8653cb7d300776411413 +F src/btree.c d288e668614449571ec269535dc4aaf216a23db2 F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0 @@ -221,7 +221,7 @@ F src/shell.c bf75ce6bea4c8f56c1b46bee201c25acddffb675 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 843e23d43ee2ab9369e68eb778815ba02835da59 +F src/sqliteInt.h b06500d391d4b7bf4c69fc110e37dd45719b760c F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -278,19 +278,19 @@ F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a -F src/vdbe.h 6833579fc0fbdc1c933e34519064841abda5b9b3 +F src/vdbe.h c6dc01f85cf3bdcc992d244aeff952c033fd5ad0 F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c aad5345869c110f45074e2c1ca230e623b1ba182 +F src/vdbeaux.c da0979ce81ecdf3d018be9ee1e8998110181fb12 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 93fc3f13ebe6809ebaac8d0a17c812ec053ba233 -F src/vdbesort.c 72290f12428973c2c6b9d4f95ad0a7c8181e1280 +F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 6042e1a377cf7dc72c10493269ed75e276275cd8 +F src/where.c 36ef94b653a10944b39e34938ee4c758f3f42879 F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 284bde0ee20261737446eb8f5b6b36ad9bc3f355 -R 75b55639e7bdd048d8263d0acfa3cf8a +P 3a09f5605ac7c6e503eb10acfdc607010414d917 +R b23b5e438c1d698174ad52d7cfba370e U dan -Z d116a418c5c97c83b8ebfe7a3e655c3c +Z 35d9cecacf0cc917a2c2ed9a75b36eab diff --git a/manifest.uuid b/manifest.uuid index 9cb218f1b4..54a81caa10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3a09f5605ac7c6e503eb10acfdc607010414d917 \ No newline at end of file +3861e853105cb8da344c7eebd2e455622b26395e \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index c0b04cc08c..4d42969be8 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4661,14 +4661,14 @@ int sqlite3BtreeMovetoUnpacked( ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[1], pCell[1], 1, pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); - c = xRecordCompare(nCell, (void*)&pCell[2], pCell[2], 1, pIdxKey); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated @@ -4689,7 +4689,7 @@ int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = xRecordCompare(nCell, pCellKey, ((u8*)pCellKey)[0], 1, pIdxKey); + c = xRecordCompare(nCell, pCellKey, pIdxKey, 0); sqlite3_free(pCellKey); } if( c<0 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index eece50f7a1..a368b96c63 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1586,14 +1586,17 @@ struct KeyInfo { ** ** This structure holds a record that has already been disassembled ** into its constituent fields. +** +** The r1 and r2 member variables are only used by the optimized comparison +** functions vdbeRecordCompareInt() and vdbeRecordCompareString(). */ struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ char default_rc; /* Comparison result if keys are equal */ Mem *aMem; /* Values */ - int r1; - int r2; + int r1; /* Value to return if (lhs > rhs) */ + int r2; /* Value to return if (rhs < lhs) */ }; diff --git a/src/vdbe.h b/src/vdbe.h index c08512e7aa..389c1d5ffb 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -211,12 +211,11 @@ void sqlite3VdbeSetVarmask(Vdbe*, int); #endif void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); -typedef int (*RecordCompare)(int,const void*,int,u32,UnpackedRecord*); +typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int); RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); -RecordCompare sqlite3VdbeFindSorterCompare(KeyInfo*); #ifndef SQLITE_OMIT_TRIGGER void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 007f4e650d..f15f5e95be 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3123,24 +3123,16 @@ void sqlite3VdbeRecordUnpack( p->nField = u; } +#if SQLITE_DEBUG /* -** This function compares the two table rows or index records -** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or -** greater than key2. The {nKey1, pKey1} key must be a blob -** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 -** key must be a parsed key such as obtained from -** sqlite3VdbeParseRecord. -** -** Key1 and Key2 do not have to contain the same number of fields. -** The key with fewer fields is usually compares less than the -** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set -** and the common prefixes are equal, then key1 is less than key2. -** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are -** equal, then the keys are considered to be equal and -** the parts beyond the common prefix are ignored. +** This function compares two index or table record keys in the same way +** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), +** this function deserializes and compares values using the +** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used +** in assert() statements to ensure that the optimized code in +** sqlite3VdbeRecordCompare() returns results with these two primitives. */ -static int vdbeRecordComparePrev( +static int vdbeRecordCompareDebug( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ @@ -3220,10 +3212,17 @@ static int vdbeRecordComparePrev( ** value. */ return pPKey2->default_rc; } +#endif +/* +** Both *pMem1 and *pMem2 contain string values. Compare the two values +** using the collation sequence pColl. As usual, return a negative , zero +** or positive value if *pMem1 is less than, equal to or greater than +** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". +*/ static int vdbeCompareMemString( - const Mem *pMem1, - const Mem *pMem2, + const Mem *pMem1, + const Mem *pMem2, const CollSeq *pColl ){ if( pMem1->enc==pColl->enc ){ @@ -3344,8 +3343,17 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ } +/* +** The first argument passed to this function is a serial-type that +** corresponds to an integer - all values between 1 and 9 inclusive +** except 7. The second points to a buffer containing an integer value +** serialized according to serial_type. This function deserializes +** and returns the value. +*/ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ + assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); switch( serial_type ){ + case 0: case 1: return (char)aKey[0]; case 2: @@ -3354,13 +3362,11 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ return ((char)aKey[0] << 16) | (aKey[1] << 8) | aKey[2]; case 4: return ((char)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]; - case 5: { i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; u32 lsw = (aKey[4] << 8) | aKey[5]; return (i64)( msw << 16 | (u64)lsw ); } - case 6: { i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; @@ -3371,36 +3377,51 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ return (serial_type - 8); } -static int vdbeRecordCompare( - int nKey1, const void *pKey1, /* Left key */ - int szHdr1, /* Size of record header in bytes */ - u32 idx1, /* Offset of first type in header */ - UnpackedRecord *const pPKey2 /* Right key */ +/* +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero +** or positive integer if key1 is less than, equal to or +** greater than key2. The {nKey1, pKey1} key must be a blob +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. +** +** If argument bSkip is non-zero, it is assumed that the caller has already +** determined that the first fields of the keys are equal. +** +** Key1 and Key2 do not have to contain the same number of fields. If all +** fields that appear in both keys are equal, then pPKey2->default_rc is +** returned. +*/ +int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, /* Left key */ + UnpackedRecord *const pPKey2, /* Right key */ + int bSkip /* If true, skip the first field */ ){ - u32 d1 = szHdr1; /* Offset into aKey[] of next data element */ - int i = 0; - int rc = 0; - Mem *pRhs = pPKey2->aMem; + u32 d1; /* Offset into aKey[] of next data element */ + int i; /* Index of next field to compare */ + int szHdr1; /* Size of record header in bytes */ + u32 idx1; /* Offset of first type in header */ + int rc = 0; /* Return value */ + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ KeyInfo *pKeyInfo = pPKey2->pKeyInfo; const unsigned char *aKey1 = (const unsigned char *)pKey1; Mem mem1; -#ifdef SQLITE_DEBUG - int expected = vdbeRecordComparePrev(nKey1, pKey1, pPKey2); - static int nCall = 0; - nCall++; -#endif - - /* If idx==0, then the caller has already determined that the first two - ** elements in the keys are equal. Fix the various stack variables so + /* If bSkip is true, then the caller has already determined that the first + ** two elements in the keys are equal. Fix the various stack variables so ** that this routine begins comparing at the second field. */ - if( idx1==0 ){ + if( bSkip ){ u32 s1; - assert( sqlite3VarintLen(szHdr1)==1 ); idx1 = 1 + getVarint32(&aKey1[1], s1); - d1 += sqlite3VdbeSerialTypeLen(s1); + szHdr1 = aKey1[0]; + d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); i = 1; pRhs++; + }else{ + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + i = 0; } VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ @@ -3511,18 +3532,14 @@ static int vdbeRecordCompare( } if( rc!=0 ){ - assert( mem1.zMalloc==0 ); /* See comment below */ if( pKeyInfo->aSortOrder[i] ){ rc = -rc; -#if 0 - assert( (rc>0 && (rc^(int)0x80000000)<0) - || (rc<0 && (rc^(int)0x80000000)>0) ); - assert( sizeof(int)==4 ); - rc ^= (int)0x80000000; /* similar in spirit to: "rc = -rc;" */ - assert( rc!=0 ); -#endif } - assert( (rc<0 && expected<0) || (rc>0 && expected>0) || CORRUPT_DB ); + assert( CORRUPT_DB + || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) + ); + assert( mem1.zMalloc==0 ); /* See comment below */ return rc; } @@ -3534,31 +3551,38 @@ static int vdbeRecordCompare( /* No memory allocation is ever used on mem1. Prove this using ** the following assert(). If the assert() fails, it indicates a - ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). - */ + ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */ assert( mem1.zMalloc==0 ); /* rc==0 here means that one or both of the keys ran out of fields and ** all the fields up to that point were equal. Return the the default_rc ** value. */ - assert( pPKey2->default_rc==expected ); + assert( CORRUPT_DB + || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2) + ); return pPKey2->default_rc; } +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is an integer, and (b) the +** size-of-header varint at the start of (pKey1/nKey1) fits in a single +** byte (i.e. is less than 128). +*/ static int vdbeRecordCompareInt( int nKey1, const void *pKey1, /* Left key */ - int szHdr, - u32 idx1, - UnpackedRecord *pPKey2 /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ + int bSkip /* Ignored */ ){ - const u8 *aKey = &((const u8*)pKey1)[szHdr]; + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1]; int serial_type = ((const u8*)pKey1)[1]; int res; i64 v = pPKey2->aMem[0].u.i; i64 lhs; - switch( serial_type ){ + assert( bSkip==0 ); + switch( serial_type ){ case 1: lhs = (char)(aKey[0]); break; @@ -3571,25 +3595,21 @@ static int vdbeRecordCompareInt( case 4: lhs = (int)(((u32)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]); break; - case 5: { i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; u32 lsw = (aKey[4] << 8) | aKey[5]; lhs = (i64)( msw << 16 | (u64)lsw ); break; } - case 6: { i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; lhs = (i64)( msw << 32 | (u64)lsw ); break; } - case 8: lhs = 0; break; - case 9: lhs = 1; break; @@ -3601,10 +3621,10 @@ static int vdbeRecordCompareInt( ** (as gcc is clever enough to combine the two like cases). Other ** compilers might be similar. */ case 0: case 7: - return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2); + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); default: - return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2); + return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0); } if( v>lhs ){ @@ -3614,31 +3634,37 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2); + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ res = pPKey2->default_rc; } - assert( (res==0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)==0) - || (res<0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)<0) - || (res>0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)>0) + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) || CORRUPT_DB ); return res; } +/* +** This function is an optimized version of sqlite3VdbeRecordCompare() +** that (a) the first field of pPKey2 is a string, that (b) the first field +** uses the collation sequence BINARY and (c) that the size-of-header varint +** at the start of (pKey1/nKey1) fits in a single byte. +*/ static int vdbeRecordCompareString( int nKey1, const void *pKey1, /* Left key */ - int szHdr, - u32 idx1, - UnpackedRecord *pPKey2 /* Right key */ + UnpackedRecord *pPKey2, /* Right key */ + int bSkip ){ const u8 *aKey1 = (const u8*)pKey1; int serial_type; int res; + assert( bSkip==0 ); getVarint32(&aKey1[1], serial_type); if( serial_type<12 ){ @@ -3648,18 +3674,18 @@ static int vdbeRecordCompareString( }else{ int nCmp; int nStr; - aKey1 = &aKey1[szHdr]; + int szHdr = aKey1[0]; nStr = (serial_type-12) / 2; if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ nCmp = MIN( pPKey2->aMem[0].n, nStr ); - res = memcmp(aKey1, pPKey2->aMem[0].z, nCmp); + res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); if( res==0 ){ res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2); + res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; } @@ -3675,30 +3701,26 @@ static int vdbeRecordCompareString( } } - assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0) - || (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0) - || (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0) + assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0) + || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0) + || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0) || CORRUPT_DB ); return res; } - -int vdbeRecordCompareLargeHeader( - int nKey1, const void *pKey1, /* Left key */ - int dummy1, u32 dummy2, /* Unused arguments */ - UnpackedRecord *pPKey2 /* Right key */ -){ - int szHdr; - u32 idx1; - idx1 = getVarint32(((u8*)pKey1), szHdr); - return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2); -} - +/* +** Return a pointer to an sqlite3VdbeRecordCompare() compatible function +** suitable for comparing serialized records to the unpacked record passed +** as the only argument. +*/ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ - if( (p->pKeyInfo->nField + p->pKeyInfo->nXField) > 10 ){ - return vdbeRecordCompareLargeHeader; - }else{ + /* As the varints that make up a record header are all 5 bytes in size + ** or less, if the binary keys being compared have 25 or fewer fields + ** then it is guaranteed that the varint at the start of every record + ** (the record-header size in bytes) fits in a single byte. If this + ** is not the case, then sqlite3VdbeRecordCompare() must be used. */ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=25 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortOrder[0] ){ p->r1 = 1; @@ -3717,25 +3739,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ } } - return vdbeRecordCompare; -} - -RecordCompare sqlite3VdbeFindSorterCompare(KeyInfo *pKeyInfo){ - if( (pKeyInfo->nField + pKeyInfo->nXField) > 10 ){ - return vdbeRecordCompareLargeHeader; - } - return vdbeRecordCompare; -} - -int sqlite3VdbeRecordCompare( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - int szHdr; - u32 idx1; - - idx1 = getVarint32(((u8*)pKey1), szHdr); - return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2); + return sqlite3VdbeRecordCompare; } /* @@ -3850,7 +3854,7 @@ int sqlite3VdbeIdxKeyCompare( if( rc ){ return rc; } - *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); + *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0); sqlite3VdbeMemRelease(&m); return SQLITE_OK; } diff --git a/src/vdbesort.c b/src/vdbesort.c index be5a6064c2..b9ed97e8b3 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -105,7 +105,6 @@ struct VdbeSorter { sqlite3_file *pTemp1; /* PMA file 1 */ SorterRecord *pRecord; /* Head of in-memory record list */ UnpackedRecord *pUnpacked; /* Used to unpack keys */ - RecordCompare xRecordCompare; /* Record compare function */ }; /* @@ -413,10 +412,7 @@ static void vdbeSorterCompare( assert( r2->default_rc==0 ); } -#if 0 - *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2); -#endif - *pRes = pSorter->xRecordCompare(nKey1, pKey1, *((u8*)pKey1), 1, r2); + *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0); } /* @@ -492,7 +488,6 @@ int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ if( mxCachemxPmaSize = mxCache * pgsz; } - pSorter->xRecordCompare = sqlite3VdbeFindSorterCompare(pCsr->pKeyInfo); return SQLITE_OK; } diff --git a/src/where.c b/src/where.c index a5dd7b59e7..4ce0cb7ded 100644 --- a/src/where.c +++ b/src/where.c @@ -1913,7 +1913,7 @@ static void whereKeyStats( assert( pRec->nField>0 && iColnSampleCol ); do{ iTest = (iMin+i)/2; - res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec); + res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0); if( res<0 ){ iMin = iTest+1; }else{ @@ -1928,16 +1928,16 @@ static void whereKeyStats( if( res==0 ){ /* If (res==0) is true, then sample $i must be equal to pRec */ assert( inSample ); - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0) || pParse->db->mallocFailed ); }else{ /* Otherwise, pRec must be smaller than sample $i and larger than ** sample ($i-1). */ assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0 || pParse->db->mallocFailed ); assert( i==0 - || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 + || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0 || pParse->db->mallocFailed ); } #endif /* ifdef SQLITE_DEBUG */ From fbf0f0e1f636718d7c6541b5e2d88a4710bc98fc Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 3 Mar 2014 14:20:30 +0000 Subject: [PATCH 51/66] Fix a segfault that can occur following an OOM error. FossilOrigin-Name: 7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/where.c | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e3e4bab9d6..86c4f75cc8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sMEM_Dyn\sflag\sso\sthat\sit\smeans\sthat\sMem.xDel\sexists\sand\smust\s\nbe\sused\sto\sfree\sthe\sstring\sor\sblob.\sAdd\stighter\sinvariant\schecks\son\sMem. -D 2014-03-03T00:12:39.825 +C Fix\sa\ssegfault\sthat\scan\soccur\sfollowing\san\sOOM\serror. +D 2014-03-03T14:20:30.542 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 6042e1a377cf7dc72c10493269ed75e276275cd8 +F src/where.c e4b57d81d2a5fece518c1419f047f0803483f90c F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1152,8 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e6ecf7337658624d664e1e71ba3fc527fd6578c1 44e1c33767cae3bf2cbd2238831fe67197009b43 -R 0950c7cf1a1151e6071aa7a5599d1f4e -T +closed 44e1c33767cae3bf2cbd2238831fe67197009b43 -U drh -Z 4d8fd5c0a86772bcec65a15ca628db9f +P e3f6c61e0333d4d237dcd2ba2e404f0a91ee5069 +R eaec45cec313455580b422d7721ccfeb +U dan +Z 0f4ad0e1bfa9fac79dc39c1726a86e9b diff --git a/manifest.uuid b/manifest.uuid index eadf23b042..e37ef738a9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3f6c61e0333d4d237dcd2ba2e404f0a91ee5069 \ No newline at end of file +7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 \ No newline at end of file diff --git a/src/where.c b/src/where.c index a5dd7b59e7..f13d2b5044 100644 --- a/src/where.c +++ b/src/where.c @@ -5870,7 +5870,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ ** the co-routine into OP_SCopy of result contained in a register. ** OP_Rowid becomes OP_Null. */ - if( pTabItem->viaCoroutine ){ + if( pTabItem->viaCoroutine && !db->mallocFailed ){ last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); From fcb44a89f226010a40265101128cc13c4fae5dfa Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Mar 2014 15:13:27 +0000 Subject: [PATCH 52/66] Fix a harmless compiler warning. FossilOrigin-Name: d7f6837e6997a4d5c0fd2d08b52887d691dd6f97 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2b023bb25c..956052609f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges. -D 2014-03-03T14:45:06.920 +C Fix\sa\sharmless\scompiler\swarning. +D 2014-03-03T15:13:27.429 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h c6dc01f85cf3bdcc992d244aeff952c033fd5ad0 F src/vdbeInt.h d55cab859abb2c6656911497ae74eba9dcf34e28 F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c f0532f7ce4fc3f4d9811d0bc29c6ce56d448596e +F src/vdbeaux.c e4a0f89d15097debae8117ba17e4a640a0d3116f F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9c1747b5ded995e77fdab2fa9d334ec3c17c7c14 7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 -R 4cede51faff0bb760b6f55494711c674 -U dan -Z 2c68a923f498f2b3622ae1d55f13bc1f +P e00ed717fbe456010ec6c746490d7c3e9d94ec5a +R 8e3a8f60ae350e66db9c9ecb1f09657d +U drh +Z 6dbc33a5cff12ba0585c075afb66f191 diff --git a/manifest.uuid b/manifest.uuid index b161fe627f..206d58eaa6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e00ed717fbe456010ec6c746490d7c3e9d94ec5a \ No newline at end of file +d7f6837e6997a4d5c0fd2d08b52887d691dd6f97 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d13049a1a9..10623ecbc0 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3499,7 +3499,7 @@ int sqlite3VdbeRecordCompare( mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; mem1.flags = MEM_Str; - mem1.z = &aKey1[d1]; + mem1.z = (char*)&aKey1[d1]; rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]); }else{ int nCmp = MIN(mem1.n, pRhs->n); From dea63f24e183ef65702bfb86dccc82fd7cb95d7b Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 3 Mar 2014 16:48:47 +0000 Subject: [PATCH 53/66] Change the "explain_i" tcl test command so that xterm color codes are only added if the output is actually a terminal. FossilOrigin-Name: 559835e54e0715f2b4d207d056199a8268af739e --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tester.tcl | 15 +++++++++++---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 86c4f75cc8..edfa442779 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\ssegfault\sthat\scan\soccur\sfollowing\san\sOOM\serror. -D 2014-03-03T14:20:30.542 +C Change\sthe\s"explain_i"\stcl\stest\scommand\sso\sthat\sxterm\scolor\scodes\sare\sonly\sadded\sif\sthe\soutput\sis\sactually\sa\sterminal. +D 2014-03-03T16:48:47.992 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -841,7 +841,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl 9bd04481b8b0ef1f2049ad01f28e175ee9a14f7b +F test/tester.tcl f31bea1483ea1d39620f982130026e76f872d744 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e3f6c61e0333d4d237dcd2ba2e404f0a91ee5069 -R eaec45cec313455580b422d7721ccfeb +P 7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 +R d76d9cf70a7a6abc4c8a0d1e487a1b2f U dan -Z 0f4ad0e1bfa9fac79dc39c1726a86e9b +Z 3cca059248ddd2dc717b9671dde6b1cc diff --git a/manifest.uuid b/manifest.uuid index e37ef738a9..0198683302 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 \ No newline at end of file +559835e54e0715f2b4d207d056199a8268af739e \ No newline at end of file diff --git a/test/tester.tcl b/test/tester.tcl index fefd5e8a8f..1c4e93937c 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -1062,10 +1062,17 @@ proc explain_i {sql {db db}} { # Blue: Opcodes that reposition or seek a cursor. # Green: The ResultRow opcode. # - set R "\033\[31;1m" ;# Red fg - set G "\033\[32;1m" ;# Green fg - set B "\033\[34;1m" ;# Red fg - set D "\033\[39;0m" ;# Default fg + if { [catch {fconfigure stdout -mode}]==0 } { + set R "\033\[31;1m" ;# Red fg + set G "\033\[32;1m" ;# Green fg + set B "\033\[34;1m" ;# Red fg + set D "\033\[39;0m" ;# Default fg + } else { + set R "" + set G "" + set B "" + set D "" + } foreach opcode { Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind NoConflict Next Prev VNext VPrev VFilter From 6295524e3ddfbcb77bd7a4eed20702c5443464d3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Mar 2014 17:36:39 +0000 Subject: [PATCH 54/66] Change an OP_SCopy into an OP_Copy in a case where the destination might be used after the source has changed. FossilOrigin-Name: c0fa0c0e2de50d7eda19ab8862496b18eff93538 --- manifest | 15 ++++++++------- manifest.uuid | 2 +- src/select.c | 2 +- test/selectF.test | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 test/selectF.test diff --git a/manifest b/manifest index edfa442779..4cca5ef21a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\s"explain_i"\stcl\stest\scommand\sso\sthat\sxterm\scolor\scodes\sare\sonly\sadded\sif\sthe\soutput\sis\sactually\sa\sterminal. -D 2014-03-03T16:48:47.992 +C Change\san\sOP_SCopy\sinto\san\sOP_Copy\sin\sa\scase\swhere\sthe\sdestination\smight\sbe\nused\safter\sthe\ssource\shas\schanged. +D 2014-03-03T17:36:39.940 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,7 +216,7 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 35b07a47fdee9a98e03c4ffb3801026c72114cb7 +F src/select.c 780bbf39e401091845ba745a38326eabe5d44293 F src/shell.c 7bf07bcacb181ecc3fc3ccacfdfeb4084aee67ed F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -788,6 +788,7 @@ F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25 F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977 F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7 +F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 @@ -1152,7 +1153,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 7fdd378d54754a3ffdc01c6c0a66cf6d5899a495 -R d76d9cf70a7a6abc4c8a0d1e487a1b2f -U dan -Z 3cca059248ddd2dc717b9671dde6b1cc +P 559835e54e0715f2b4d207d056199a8268af739e +R 0f407d04c62b2be5f5455aa20c5e914d +U drh +Z c144dcb8dd86ca2b393613351986e190 diff --git a/manifest.uuid b/manifest.uuid index 0198683302..097e35067a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -559835e54e0715f2b4d207d056199a8268af739e \ No newline at end of file +c0fa0c0e2de50d7eda19ab8862496b18eff93538 \ No newline at end of file diff --git a/src/select.c b/src/select.c index a8cb341c65..9430888c4a 100644 --- a/src/select.c +++ b/src/select.c @@ -609,7 +609,7 @@ static void selectInnerLoop( ** values returned by the SELECT are not required. */ sqlite3ExprCodeExprList(pParse, pEList, regResult, - (eDest==SRT_Output)?SQLITE_ECEL_DUP:0); + (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0); } /* If the DISTINCT keyword was present on the SELECT statement diff --git a/test/selectF.test b/test/selectF.test new file mode 100644 index 0000000000..3fb226e012 --- /dev/null +++ b/test/selectF.test @@ -0,0 +1,49 @@ +# 2014-03-03 +# +# 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 verifies that an OP_Copy operation is used instead of OP_SCopy +# in a compound select in a case where the source register might be changed +# before the copy is used. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix selectF + +do_execsql_test 1 { + BEGIN TRANSACTION; + CREATE TABLE t1(a, b, c); + INSERT INTO "t1" VALUES(1,'one','I'); + CREATE TABLE t2(d, e, f); + INSERT INTO "t2" VALUES(5,'ten','XX'); + INSERT INTO "t2" VALUES(6,NULL,NULL); + + CREATE INDEX i1 ON t1(b, a); + COMMIT; +} + +#explain_i { +# SELECT * FROM t2 +# UNION ALL +# SELECT * FROM t1 WHERE a<5 +# ORDER BY 2, 1 +#} + +do_execsql_test 2 { + SELECT * FROM t2 + UNION ALL + SELECT * FROM t1 WHERE a<5 + ORDER BY 2, 1 +} {6 {} {} 1 one I 5 ten XX} + + + +finish_test From 295aedf097e947c5975cc1a79e16f779e7992f31 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Mar 2014 18:25:24 +0000 Subject: [PATCH 55/66] Fix compiler warnings. FossilOrigin-Name: ba8993727e5752cbc92c7d78437e9e0510c899f7 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/vdbe.h | 4 ++-- src/vdbeInt.h | 2 +- src/vdbeaux.c | 24 +++++++++++++----------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 15339f6098..d6d61e95b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges. -D 2014-03-03T17:48:03.279 +C Fix\scompiler\swarnings. +D 2014-03-03T18:25:24.475 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -278,10 +278,10 @@ F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 -F src/vdbe.h c6dc01f85cf3bdcc992d244aeff952c033fd5ad0 -F src/vdbeInt.h d55cab859abb2c6656911497ae74eba9dcf34e28 +F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 +F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c e4a0f89d15097debae8117ba17e4a640a0d3116f +F src/vdbeaux.c f6d49b824fb9b4025098d73ba63a579bceab46c1 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1153,7 +1153,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d7f6837e6997a4d5c0fd2d08b52887d691dd6f97 c0fa0c0e2de50d7eda19ab8862496b18eff93538 -R 9a9d986bbf5df1b40c16a7d9f71c4a7c -U dan -Z 5c6a6f0f42fa42f03fa0c54709a35c4c +P 1d60356462f111ed147aa865dd17a13511db6ab7 +R 21f5b7d1de45908a8d9a08e2efe5ba51 +U drh +Z bf94921d4ecf2467a56de90bb29e8bf1 diff --git a/manifest.uuid b/manifest.uuid index a61bcd33e6..19e8b9d202 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d60356462f111ed147aa865dd17a13511db6ab7 \ No newline at end of file +ba8993727e5752cbc92c7d78437e9e0510c899f7 \ No newline at end of file diff --git a/src/vdbe.h b/src/vdbe.h index 389c1d5ffb..66ca602ab7 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -211,10 +211,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int); #endif void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); -int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int); +int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); -typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int); +typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int); RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER diff --git a/src/vdbeInt.h b/src/vdbeInt.h index c16baff685..33c06142f6 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -391,7 +391,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); +int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeExec(Vdbe*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 10623ecbc0..0a2f11ab2b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3135,7 +3135,7 @@ void sqlite3VdbeRecordUnpack( */ static int vdbeRecordCompareDebug( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ + const UnpackedRecord *pPKey2 /* Right key */ ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ @@ -3396,7 +3396,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ */ int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *const pPKey2, /* Right key */ + const UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ ){ u32 d1; /* Offset into aKey[] of next data element */ @@ -3474,7 +3474,7 @@ int sqlite3VdbeRecordCompare( if( serial_type==7 ){ lhs = mem1.r; }else{ - lhs = mem1.u.i; + lhs = (double)mem1.u.i; } if( lhs nKey1 ){ + if( (d1+mem1.n) > (unsigned)nKey1 ){ rc = 1; /* Corruption */ }else if( pKeyInfo->aColl[i] ){ mem1.enc = pKeyInfo->enc; @@ -3516,7 +3516,7 @@ int sqlite3VdbeRecordCompare( rc = -1; }else{ int nStr = (serial_type - 12) / 2; - if( (d1+nStr) > nKey1 ){ + if( (d1+nStr) > (unsigned)nKey1 ){ rc = 1; /* Corruption */ }else{ int nCmp = MIN(nStr, pRhs->n); @@ -3548,7 +3548,7 @@ int sqlite3VdbeRecordCompare( pRhs++; d1 += sqlite3VdbeSerialTypeLen(serial_type); idx1 += sqlite3VarintLen(serial_type); - }while( idx1nField && d1<=nKey1 ); + }while( idx1<(unsigned)szHdr1 && inField && d1<=(unsigned)nKey1 ); /* No memory allocation is ever used on mem1. Prove this using ** the following assert(). If the assert() fails, it indicates a @@ -3572,7 +3572,7 @@ int sqlite3VdbeRecordCompare( */ static int vdbeRecordCompareInt( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2, /* Right key */ + const UnpackedRecord *pPKey2, /* Right key */ int bSkip /* Ignored */ ){ const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1]; @@ -3580,6 +3580,7 @@ static int vdbeRecordCompareInt( int res; i64 v = pPKey2->aMem[0].u.i; i64 lhs; + UNUSED_PARAMETER(bSkip); assert( bSkip==0 ); @@ -3658,12 +3659,13 @@ static int vdbeRecordCompareInt( */ static int vdbeRecordCompareString( int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2, /* Right key */ + const UnpackedRecord *pPKey2, /* Right key */ int bSkip ){ const u8 *aKey1 = (const u8*)pKey1; int serial_type; int res; + UNUSED_PARAMETER(bSkip); assert( bSkip==0 ); getVarint32(&aKey1[1], serial_type); @@ -3832,9 +3834,9 @@ idx_rowid_corruption: ** of the keys prior to the final rowid, not the entire key. */ int sqlite3VdbeIdxKeyCompare( - VdbeCursor *pC, /* The cursor to compare against */ - UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */ - int *res /* Write the comparison result here */ + VdbeCursor *pC, /* The cursor to compare against */ + const UnpackedRecord *pUnpacked, /* Unpacked version of key */ + int *res /* Write the comparison result here */ ){ i64 nCellKey = 0; int rc; From 5668969a69c34859d6c670218c9cebb52f6d7f55 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Mar 2014 19:29:28 +0000 Subject: [PATCH 56/66] Fix a typo in a comment. No changes to code. FossilOrigin-Name: 1f4991ab1676bf85599fc32068ceeddeb05f648c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d6d61e95b6..4302dac32e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings. -D 2014-03-03T18:25:24.475 +C Fix\sa\stypo\sin\sa\scomment.\s\sNo\schanges\sto\scode. +D 2014-03-03T19:29:28.807 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c f6d49b824fb9b4025098d73ba63a579bceab46c1 +F src/vdbeaux.c b817480055ea37f04cbda6524cbcda56d8620c78 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1153,7 +1153,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1d60356462f111ed147aa865dd17a13511db6ab7 -R 21f5b7d1de45908a8d9a08e2efe5ba51 +P ba8993727e5752cbc92c7d78437e9e0510c899f7 +R 84a57b7d3530d77238186688acf2fb15 U drh -Z bf94921d4ecf2467a56de90bb29e8bf1 +Z 743719e98998c2037f212aec24c916c8 diff --git a/manifest.uuid b/manifest.uuid index 19e8b9d202..2f5a48fd68 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ba8993727e5752cbc92c7d78437e9e0510c899f7 \ No newline at end of file +1f4991ab1676bf85599fc32068ceeddeb05f648c \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 0a2f11ab2b..47a3f0899b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3846,7 +3846,7 @@ int sqlite3VdbeIdxKeyCompare( assert( sqlite3BtreeCursorIsValid(pCur) ); VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ - /* nCellKey will always be between 0 and 0xffffffff because of the say + /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; From 9b8afef260c0ed02cc0d1a195fa697844eb1c02e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 3 Mar 2014 20:48:50 +0000 Subject: [PATCH 57/66] Avoid a buffer overread in vdbeCompareRecordInt() that might occur if the database is corrupt. FossilOrigin-Name: 7c0b4381f0e6f33cb13299a915851d9431bf3850 --- manifest | 15 ++++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 24 +++++++++++++++-------- test/corruptI.test | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 test/corruptI.test diff --git a/manifest b/manifest index 4302dac32e..1f36291c28 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sa\scomment.\s\sNo\schanges\sto\scode. -D 2014-03-03T19:29:28.807 +C Avoid\sa\sbuffer\soverread\sin\svdbeCompareRecordInt()\sthat\smight\soccur\sif\sthe\sdatabase\sis\scorrupt. +D 2014-03-03T20:48:50.982 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c b817480055ea37f04cbda6524cbcda56d8620c78 +F src/vdbeaux.c 687165bd405b33553c9aaf5da74c249cea083d24 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -404,6 +404,7 @@ F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039 +F test/corruptI.test d9eca60cb373215d97e0994bf104f9a37e1ac0fc F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f @@ -1153,7 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ba8993727e5752cbc92c7d78437e9e0510c899f7 -R 84a57b7d3530d77238186688acf2fb15 -U drh -Z 743719e98998c2037f212aec24c916c8 +P 1f4991ab1676bf85599fc32068ceeddeb05f648c +R 112194c4c042293d2f5fc41663c08a7a +U dan +Z e0c8dc8360525071b6a4931f6b50a318 diff --git a/manifest.uuid b/manifest.uuid index 2f5a48fd68..f96d8cdcc1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f4991ab1676bf85599fc32068ceeddeb05f648c \ No newline at end of file +7c0b4381f0e6f33cb13299a915851d9431bf3850 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 47a3f0899b..dd724cc39e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3575,7 +3575,8 @@ static int vdbeRecordCompareInt( const UnpackedRecord *pPKey2, /* Right key */ int bSkip /* Ignored */ ){ - const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1]; + int szHdr = *(const u8*)pKey1; + const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; int serial_type = ((const u8*)pKey1)[1]; int res; i64 v = pPKey2->aMem[0].u.i; @@ -3583,7 +3584,6 @@ static int vdbeRecordCompareInt( UNUSED_PARAMETER(bSkip); assert( bSkip==0 ); - switch( serial_type ){ case 1: lhs = (char)(aKey[0]); @@ -3718,12 +3718,20 @@ static int vdbeRecordCompareString( ** as the only argument. */ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ - /* As the varints that make up a record header are all 5 bytes in size - ** or less, if the binary keys being compared have 25 or fewer fields - ** then it is guaranteed that the varint at the start of every record - ** (the record-header size in bytes) fits in a single byte. If this - ** is not the case, then sqlite3VdbeRecordCompare() must be used. */ - if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=25 ){ + /* varintRecordCompareInt() and varintRecordCompareString() both assume + ** that the size-of-header varint that occurs at the start of each record + ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt() + ** also assumes that it is safe to overread a buffer by at least the + ** maximum possible legal header size plus 8 bytes. Because there is + ** guaranteed to be at least 74 (but not 136) bytes of padding following each + ** buffer passed to varintRecordCompareInt() this makes it convenient to + ** limit the size of the header to 64 bytes in cases where the first field + ** is an integer. + ** + ** The easiest way to enforce this limit is to consider only records with + ** 13 fields or less. If the first field is an integer, the maximum legal + ** header size is (12*5 + 1 + 1) bytes. */ + if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortOrder[0] ){ p->r1 = 1; diff --git a/test/corruptI.test b/test/corruptI.test new file mode 100644 index 0000000000..9c9a19310b --- /dev/null +++ b/test/corruptI.test @@ -0,0 +1,47 @@ +# 2014-01-20 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix corruptI + +# Do not use a codec for tests in this file, as the database file is +# manipulated directly using tcl scripts (using the [hexio_write] command). +# +do_not_use_codec +database_may_be_corrupt + +# Initialize the database. +# +do_execsql_test 1.1 { + PRAGMA page_size=1024; + PRAGMA auto_vacuum=0; + CREATE TABLE t1(a); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES('a'); +} {} +db close + +do_test 1.2 { + set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] + set off [expr 2*1024 + $offset + 1] + hexio_write test.db $off FF06 + + breakpoint + + sqlite3 db test.db + catchsql { SELECT * FROM t1 WHERE a = 10 } +} {1 {database disk image is malformed}} + + +finish_test + From 13a747e5e4ef5a8ab69169ad9d2dec2653d3490b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Mar 2014 21:46:55 +0000 Subject: [PATCH 58/66] Fix a couple of harmless compiler warnings. FossilOrigin-Name: fcf480cc630976b619aabd5f7fb7b09601a178fb --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 2 ++ src/vdbeaux.c | 1 - 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1f36291c28..52a206ae83 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sa\sbuffer\soverread\sin\svdbeCompareRecordInt()\sthat\smight\soccur\sif\sthe\sdatabase\sis\scorrupt. -D 2014-03-03T20:48:50.982 +C Fix\sa\scouple\sof\sharmless\scompiler\swarnings. +D 2014-03-03T21:46:55.799 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -163,7 +163,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c d288e668614449571ec269535dc4aaf216a23db2 +F src/btree.c 7a81c2c6b5c0bf6334b4247e709c639c573fbcc1 F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 687165bd405b33553c9aaf5da74c249cea083d24 +F src/vdbeaux.c 5adf67ef9cdaa57b393c0a8bf0a29eadbd6f9158 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1154,7 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1f4991ab1676bf85599fc32068ceeddeb05f648c -R 112194c4c042293d2f5fc41663c08a7a -U dan -Z e0c8dc8360525071b6a4931f6b50a318 +P 7c0b4381f0e6f33cb13299a915851d9431bf3850 +R 4042a62ac4c0618104f381105ba13add +U drh +Z 0037dd9417989b6d6f935caf436e0a2a diff --git a/manifest.uuid b/manifest.uuid index f96d8cdcc1..aaa189ba4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c0b4381f0e6f33cb13299a915851d9431bf3850 \ No newline at end of file +fcf480cc630976b619aabd5f7fb7b09601a178fb \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4d42969be8..ce35afbd58 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4575,6 +4575,8 @@ int sqlite3BtreeMovetoUnpacked( || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1 ); + }else{ + xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */ } rc = moveToRoot(pCur); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index dd724cc39e..2526d6fc50 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3575,7 +3575,6 @@ static int vdbeRecordCompareInt( const UnpackedRecord *pPKey2, /* Right key */ int bSkip /* Ignored */ ){ - int szHdr = *(const u8*)pKey1; const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; int serial_type = ((const u8*)pKey1)[1]; int res; From a9e0aeb552811d8aecedd872a32cd79af404dcc6 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 4 Mar 2014 00:15:16 +0000 Subject: [PATCH 59/66] Do not assume that 'char' is signed. Make it explicit. FossilOrigin-Name: 979da752e6f8767a61a8efed824ffad9605d0f4c --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/sqliteInt.h | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 36f6559f55..eea0f83b79 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refactor\sthe\ssqlite3VdbeRecordCompare()\sroutine\sused\sto\scompare\sbtree\srecords.\nCreate\sa\scouple\sof\sfast-track\sroutines\sto\shandle\sthe\scommon\scases\sof\sa\sstring\nwith\sBINARY\scollation\sor\sinteger\svalues\sas\sthe\sleft-most\scolumn.\s\sThis\sgives\na\ssignificant\sperformance\sboost\sin\scommon\suse. -D 2014-03-03T21:59:33.388 +C Do\snot\sassume\sthat\s'char'\sis\ssigned.\s\sMake\sit\sexplicit. +D 2014-03-04T00:15:16.875 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,7 +221,7 @@ F src/shell.c 7bf07bcacb181ecc3fc3ccacfdfeb4084aee67ed F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h b06500d391d4b7bf4c69fc110e37dd45719b760c +F src/sqliteInt.h bf529055591dd81ec92a84d35dba0854642f6cc2 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1154,8 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c0fa0c0e2de50d7eda19ab8862496b18eff93538 fcf480cc630976b619aabd5f7fb7b09601a178fb -R 4042a62ac4c0618104f381105ba13add -T +closed fcf480cc630976b619aabd5f7fb7b09601a178fb +P aec5473a750e412eb1e11e17bbafd760db086c86 +R 3fc76904aa4a71ad8f46b000aee0d4b3 U drh -Z f2b997d224dae00836e71263e0e4d70e +Z f6bc4780db4acc20db7127296b21d314 diff --git a/manifest.uuid b/manifest.uuid index 93e0969edd..0b0b678799 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aec5473a750e412eb1e11e17bbafd760db086c86 \ No newline at end of file +979da752e6f8767a61a8efed824ffad9605d0f4c \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a368b96c63..90e83206ad 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1593,7 +1593,7 @@ struct KeyInfo { struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ u16 nField; /* Number of entries in apMem[] */ - char default_rc; /* Comparison result if keys are equal */ + i8 default_rc; /* Comparison result if keys are equal */ Mem *aMem; /* Values */ int r1; /* Value to return if (lhs > rhs) */ int r2; /* Value to return if (rhs < lhs) */ From f926d1ea47939fe1c60d04bcf269b4ad6c1f50a1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 4 Mar 2014 04:04:33 +0000 Subject: [PATCH 60/66] Fix more instances of assuming 'char' is signed. And, make sure to never shift a signed integer. FossilOrigin-Name: f10130ede433a19b3945753f23962871c8d2dcf3 --- manifest | 12 +++---- manifest.uuid | 2 +- src/vdbeaux.c | 96 ++++++++++++++++++++++++++++----------------------- 3 files changed, 59 insertions(+), 51 deletions(-) diff --git a/manifest b/manifest index eea0f83b79..61023f47d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sassume\sthat\s'char'\sis\ssigned.\s\sMake\sit\sexplicit. -D 2014-03-04T00:15:16.875 +C Fix\smore\sinstances\sof\sassuming\s'char'\sis\ssigned.\s\sAnd,\smake\ssure\sto\snever\sshift\na\ssigned\sinteger. +D 2014-03-04T04:04:33.269 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c 5adf67ef9cdaa57b393c0a8bf0a29eadbd6f9158 +F src/vdbeaux.c b3bd75b2dfe314fb411c967034314b5316342820 F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1154,7 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P aec5473a750e412eb1e11e17bbafd760db086c86 -R 3fc76904aa4a71ad8f46b000aee0d4b3 +P 979da752e6f8767a61a8efed824ffad9605d0f4c +R 76afae803c9615945e7c1ed11c396a45 U drh -Z f6bc4780db4acc20db7127296b21d314 +Z 4679453e8217252329a19e88ce1ddc0d diff --git a/manifest.uuid b/manifest.uuid index 0b0b678799..b38b734ab9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -979da752e6f8767a61a8efed824ffad9605d0f4c \ No newline at end of file +f10130ede433a19b3945753f23962871c8d2dcf3 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 2526d6fc50..776821d398 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2942,6 +2942,14 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ return 0; } +/* Input "x" is a sequence of unsigned characters that represent a +** big-endian integer. Return the equivalent native integer +*/ +#define ONE_BYTE_INT(x) ((i8)(x)[0]) +#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) +#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) +#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) + /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. @@ -2953,7 +2961,6 @@ u32 sqlite3VdbeSerialGet( ){ u64 x; u32 y; - int i; switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ @@ -2962,33 +2969,28 @@ u32 sqlite3VdbeSerialGet( break; } case 1: { /* 1-byte signed integer */ - pMem->u.i = (signed char)buf[0]; + pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; return 1; } case 2: { /* 2-byte signed integer */ - i = 256*(signed char)buf[0] | buf[1]; - pMem->u.i = (i64)i; + pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; return 2; } case 3: { /* 3-byte signed integer */ - i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2]; - pMem->u.i = (i64)i; + pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; return 3; } case 4: { /* 4-byte signed integer */ - y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; + y = FOUR_BYTE_UINT(buf); pMem->u.i = (i64)*(int*)&y; pMem->flags = MEM_Int; return 4; } case 5: { /* 6-byte signed integer */ - x = 256*(signed char)buf[0] + buf[1]; - y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; - x = (x<<32) | y; - pMem->u.i = *(i64*)&x; + pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; return 6; } @@ -3006,8 +3008,8 @@ u32 sqlite3VdbeSerialGet( swapMixedEndianFloat(t2); assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); #endif - x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; - y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; + x = FOUR_BYTE_UINT(buf); + y = FOUR_BYTE_UINT(buf+4); x = (x<<32) | y; if( serial_type==6 ){ pMem->u.i = *(i64*)&x; @@ -3352,26 +3354,27 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ ** and returns the value. */ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ + u32 y; assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); switch( serial_type ){ case 0: case 1: - return (char)aKey[0]; + return ONE_BYTE_INT(aKey); case 2: - return ((char)aKey[0] << 8) | aKey[1]; + return TWO_BYTE_INT(aKey); case 3: - return ((char)aKey[0] << 16) | (aKey[1] << 8) | aKey[2]; - case 4: - return ((char)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]; + return THREE_BYTE_INT(aKey); + case 4: { + y = FOUR_BYTE_UINT(aKey); + return (i64)*(int*)&y; + } case 5: { - i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; - u32 lsw = (aKey[4] << 8) | aKey[5]; - return (i64)( msw << 16 | (u64)lsw ); + return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); } case 6: { - i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; - u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; - return (i64)( msw << 32 | (u64)lsw ); + u64 x = FOUR_BYTE_UINT(aKey); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + return (i64)*(i64*)&x; } } @@ -3578,34 +3581,39 @@ static int vdbeRecordCompareInt( const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; int serial_type = ((const u8*)pKey1)[1]; int res; + u32 y; + u64 x; i64 v = pPKey2->aMem[0].u.i; i64 lhs; UNUSED_PARAMETER(bSkip); assert( bSkip==0 ); switch( serial_type ){ - case 1: - lhs = (char)(aKey[0]); - break; - case 2: - lhs = 256*(signed char)aKey[0] + aKey[1]; - break; - case 3: - lhs = 65536*(char)aKey[0] | (aKey[1]<<8) | aKey[2]; - break; - case 4: - lhs = (int)(((u32)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]); - break; - case 5: { - i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; - u32 lsw = (aKey[4] << 8) | aKey[5]; - lhs = (i64)( msw << 16 | (u64)lsw ); + case 1: { /* 1-byte signed integer */ + lhs = ONE_BYTE_INT(aKey); break; } - case 6: { - i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3]; - u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7]; - lhs = (i64)( msw << 32 | (u64)lsw ); + case 2: { /* 2-byte signed integer */ + lhs = TWO_BYTE_INT(aKey); + break; + } + case 3: { /* 3-byte signed integer */ + lhs = THREE_BYTE_INT(aKey); + break; + } + case 4: { /* 4-byte signed integer */ + y = FOUR_BYTE_UINT(aKey); + lhs = (i64)*(int*)&y; + break; + } + case 5: { /* 6-byte signed integer */ + lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + break; + } + case 6: { /* 8-byte signed integer */ + x = FOUR_BYTE_UINT(aKey); + x = (x<<32) | FOUR_BYTE_UINT(aKey+4); + lhs = *(i64*)&x; break; } case 8: From ffe6bc2b93fe2d02f166e1e18f383ac0b8fae0c3 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 4 Mar 2014 11:16:20 +0000 Subject: [PATCH 61/66] Fix harmless compiler warning. FossilOrigin-Name: 8d18a803bdeab290a6e9ff26911897f5f8683876 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 6590df8169..2850e252c6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Refactor\sthe\ssqlite3VdbeRecordCompare()\sroutine\sused\sto\scompare\sbtree\srecords.\nCreate\sfast-track\sspecial\scase\sroutines\sto\shandle\sthe\scommon\scases\smore\nquickly.\s\sThis\sgives\sa\ssignificant\sperformance\sboost. -D 2014-03-04T04:12:56.404 +C Fix\sharmless\scompiler\swarning. +D 2014-03-04T11:16:20.925 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2 F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21 F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 -F src/vdbeaux.c b3bd75b2dfe314fb411c967034314b5316342820 +F src/vdbeaux.c 636a7e2eaaa48c3e3585b28b9b1673df78fc0fad F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 @@ -1154,8 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c0fa0c0e2de50d7eda19ab8862496b18eff93538 f10130ede433a19b3945753f23962871c8d2dcf3 -R 76afae803c9615945e7c1ed11c396a45 -T +closed f10130ede433a19b3945753f23962871c8d2dcf3 -U drh -Z ac0c95f2ad16dfe0178099b125074c2f +P 3325ad5bdc2f81f63b556d6f4d0589d89b142b2b +R cb72f483f7d75c1651c42a378d8bb016 +U mistachkin +Z 266049d6eb1d68d04ea732570e934710 diff --git a/manifest.uuid b/manifest.uuid index 3c00b464cf..2600f64d40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3325ad5bdc2f81f63b556d6f4d0589d89b142b2b \ No newline at end of file +8d18a803bdeab290a6e9ff26911897f5f8683876 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 776821d398..90cc415342 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3404,7 +3404,7 @@ int sqlite3VdbeRecordCompare( ){ u32 d1; /* Offset into aKey[] of next data element */ int i; /* Index of next field to compare */ - int szHdr1; /* Size of record header in bytes */ + u32 szHdr1; /* Size of record header in bytes */ u32 idx1; /* Offset of first type in header */ int rc = 0; /* Return value */ Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ From 9d42cc994cd2c06b504f8eba50a49acfda76a050 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 4 Mar 2014 11:29:42 +0000 Subject: [PATCH 62/66] Fix name resolution problem in sub-selects within triggers, ticket [4ef7e3cfca]. FossilOrigin-Name: 5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/resolve.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 2850e252c6..515845694f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning. -D 2014-03-04T11:16:20.925 +C Fix\sname\sresolution\sproblem\sin\ssub-selects\swithin\striggers,\sticket\s[4ef7e3cfca]. +D 2014-03-04T11:29:42.399 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/pragma.c a46ee83671f5c95f53d2ceeb5e1a818d7b1df99a F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece -F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e +F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 780bbf39e401091845ba745a38326eabe5d44293 F src/shell.c 7bf07bcacb181ecc3fc3ccacfdfeb4084aee67ed @@ -1154,7 +1154,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3325ad5bdc2f81f63b556d6f4d0589d89b142b2b -R cb72f483f7d75c1651c42a378d8bb016 +P 8d18a803bdeab290a6e9ff26911897f5f8683876 +R a0a3e47c5907244e634e0e73af124fa7 U mistachkin -Z 266049d6eb1d68d04ea732570e934710 +Z 20401020b81859c6f4c872d433156214 diff --git a/manifest.uuid b/manifest.uuid index 2600f64d40..d8e1e43d94 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8d18a803bdeab290a6e9ff26911897f5f8683876 \ No newline at end of file +5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 07e0e919a5..86169c51c1 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -337,6 +337,8 @@ static int lookupName( }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ pExpr->iTable = 0; pTab = pParse->pTriggerTab; + }else{ + pTab = 0; } if( pTab ){ From 5810d0315b21a821a2882801d7676f35451fa3ea Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 4 Mar 2014 11:35:20 +0000 Subject: [PATCH 63/66] Add tests to verify the fix for bug [4ef7e3cfca]. FossilOrigin-Name: 62410bb8a7b33efcd13bce8fd75b83523922adb8 --- manifest | 13 ++++---- manifest.uuid | 2 +- test/tkt-4ef7e3cfca.test | 71 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 test/tkt-4ef7e3cfca.test diff --git a/manifest b/manifest index 515845694f..59749ee867 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sname\sresolution\sproblem\sin\ssub-selects\swithin\striggers,\sticket\s[4ef7e3cfca]. -D 2014-03-04T11:29:42.399 +C Add\stests\sto\sverify\sthe\sfix\sfor\sbug\s[4ef7e3cfca]. +D 2014-03-04T11:35:20.387 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -870,6 +870,7 @@ F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70 F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0 F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407 +F test/tkt-4ef7e3cfca.test 9d7ac520e022c62ac69aea55df58f06ae2fdb86c F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894 F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84 @@ -1154,7 +1155,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 8d18a803bdeab290a6e9ff26911897f5f8683876 -R a0a3e47c5907244e634e0e73af124fa7 -U mistachkin -Z 20401020b81859c6f4c872d433156214 +P 5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2 +R ada57a884b5a4f5da4f1cf238fd54717 +U dan +Z 0e893b0948d9d4cf092e0210eb113968 diff --git a/manifest.uuid b/manifest.uuid index d8e1e43d94..5f64e27616 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2 \ No newline at end of file +62410bb8a7b33efcd13bce8fd75b83523922adb8 \ No newline at end of file diff --git a/test/tkt-4ef7e3cfca.test b/test/tkt-4ef7e3cfca.test new file mode 100644 index 0000000000..94143c029d --- /dev/null +++ b/test/tkt-4ef7e3cfca.test @@ -0,0 +1,71 @@ +# 2013-10-30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file implements regression tests for SQLite library. The +# focus of this file is testing WITHOUT ROWID tables. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tkt-4ef7e3cfca.test + +do_catchsql_test 1.1 { + CREATE TABLE x(a); + CREATE TRIGGER t AFTER INSERT ON x BEGIN + SELECT * FROM x WHERE abc.a = 1; + END; + INSERT INTO x VALUES('assert'); +} {1 {no such column: abc.a}} + +reset_db +do_execsql_test 2.1 { + CREATE TABLE w(a); + CREATE TABLE x(a); + CREATE TABLE y(a); + CREATE TABLE z(a); + + INSERT INTO x(a) VALUES(5); + INSERT INTO y(a) VALUES(10); + + CREATE TRIGGER t AFTER INSERT ON w BEGIN + INSERT INTO z + SELECT (SELECT x.a + y.a FROM y) FROM x; + END; + INSERT INTO w VALUES('incorrect'); +} +do_execsql_test 2.2 { + SELECT * FROM z; +} {15} + +reset_db +do_execsql_test 3.1 { + CREATE TABLE w(a); + CREATE TABLE x(b); + CREATE TABLE y(a); + CREATE TABLE z(a); + + INSERT INTO x(b) VALUES(5); + INSERT INTO y(a) VALUES(10); + + CREATE TRIGGER t AFTER INSERT ON w BEGIN + INSERT INTO z + SELECT (SELECT x.b + y.a FROM y) FROM x; + END; + INSERT INTO w VALUES('assert'); +} +do_execsql_test 3.2 { + SELECT * FROM z; +} {15} + + +finish_test + + From ad4b262545245926a57dd4c148da757c24ba1c6e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 4 Mar 2014 11:54:35 +0000 Subject: [PATCH 64/66] Fix minor typos in the new test file. FossilOrigin-Name: 3cbb9b1b4f8c5c2735799e84dc80614586222cd2 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/tkt-4ef7e3cfca.test | 7 ++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 59749ee867..fcfd86e17a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\sverify\sthe\sfix\sfor\sbug\s[4ef7e3cfca]. -D 2014-03-04T11:35:20.387 +C Fix\sminor\stypos\sin\sthe\snew\stest\sfile. +D 2014-03-04T11:54:35.173 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -870,7 +870,7 @@ F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70 F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0 F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407 -F test/tkt-4ef7e3cfca.test 9d7ac520e022c62ac69aea55df58f06ae2fdb86c +F test/tkt-4ef7e3cfca.test 24aaa0a94a39dbed9032de6628910f694ee55f57 F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894 F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84 @@ -1155,7 +1155,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2 -R ada57a884b5a4f5da4f1cf238fd54717 -U dan -Z 0e893b0948d9d4cf092e0210eb113968 +P 62410bb8a7b33efcd13bce8fd75b83523922adb8 +R 21629d5246fd4554d222f50cf7c4ec60 +U mistachkin +Z 1848296ec199a8f8ef5d71969502e9a2 diff --git a/manifest.uuid b/manifest.uuid index 5f64e27616..a88b46658b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -62410bb8a7b33efcd13bce8fd75b83523922adb8 \ No newline at end of file +3cbb9b1b4f8c5c2735799e84dc80614586222cd2 \ No newline at end of file diff --git a/test/tkt-4ef7e3cfca.test b/test/tkt-4ef7e3cfca.test index 94143c029d..7a8f3b6a12 100644 --- a/test/tkt-4ef7e3cfca.test +++ b/test/tkt-4ef7e3cfca.test @@ -1,4 +1,4 @@ -# 2013-10-30 +# 2014-03-04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -15,7 +15,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -set testprefix tkt-4ef7e3cfca.test +set testprefix tkt-4ef7e3cfca do_catchsql_test 1.1 { CREATE TABLE x(a); @@ -65,7 +65,4 @@ do_execsql_test 3.2 { SELECT * FROM z; } {15} - finish_test - - From b64fa0adf7d3a8f0354aa90f06926fd8ef2b0a77 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Tue, 4 Mar 2014 12:07:24 +0000 Subject: [PATCH 65/66] Fix comment in test. FossilOrigin-Name: 1e57f67b20a1c01ede36d684be628e9270bf109a --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/tkt-4ef7e3cfca.test | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fcfd86e17a..9e2889a80a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sminor\stypos\sin\sthe\snew\stest\sfile. -D 2014-03-04T11:54:35.173 +C Fix\scomment\sin\stest. +D 2014-03-04T12:07:24.678 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -870,7 +870,7 @@ F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70 F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0 F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407 -F test/tkt-4ef7e3cfca.test 24aaa0a94a39dbed9032de6628910f694ee55f57 +F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1 F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894 F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84 @@ -1155,7 +1155,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 62410bb8a7b33efcd13bce8fd75b83523922adb8 -R 21629d5246fd4554d222f50cf7c4ec60 +P 3cbb9b1b4f8c5c2735799e84dc80614586222cd2 +R 6bc642348ddf6f33974f36f3d8fd1bd7 U mistachkin -Z 1848296ec199a8f8ef5d71969502e9a2 +Z 8b1594ffbd0318ed08d8afbfa1da0977 diff --git a/manifest.uuid b/manifest.uuid index a88b46658b..414d8215f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3cbb9b1b4f8c5c2735799e84dc80614586222cd2 \ No newline at end of file +1e57f67b20a1c01ede36d684be628e9270bf109a \ No newline at end of file diff --git a/test/tkt-4ef7e3cfca.test b/test/tkt-4ef7e3cfca.test index 7a8f3b6a12..fc1efdef66 100644 --- a/test/tkt-4ef7e3cfca.test +++ b/test/tkt-4ef7e3cfca.test @@ -9,8 +9,8 @@ # #*********************************************************************** # -# This file implements regression tests for SQLite library. The -# focus of this file is testing WITHOUT ROWID tables. +# This file implements tests to verify that ticket [4ef7e3cfca] has been +# fixed. # set testdir [file dirname $argv0] From 5f1d536b537429454262a5907ec734444e32f075 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 4 Mar 2014 13:18:23 +0000 Subject: [PATCH 66/66] Improve clarity of presentation in the sqlite3VdbeMemFromBtree() routine. FossilOrigin-Name: 9830c343bc954b828f6ca752f8ae63e2c0a980c1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbemem.c | 15 ++++++++------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 9e2889a80a..c0ec8eeea1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomment\sin\stest. -D 2014-03-04T12:07:24.678 +C Improve\sclarity\sof\spresentation\sin\sthe\ssqlite3VdbeMemFromBtree()\sroutine. +D 2014-03-04T13:18:23.018 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -283,7 +283,7 @@ F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820 F src/vdbeaux.c 636a7e2eaaa48c3e3585b28b9b1673df78fc0fad F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50 -F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28 +F src/vdbemem.c 10b250f09a3843ee2bcabcadf50ca21fc3ff1f87 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd @@ -1155,7 +1155,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3cbb9b1b4f8c5c2735799e84dc80614586222cd2 -R 6bc642348ddf6f33974f36f3d8fd1bd7 -U mistachkin -Z 8b1594ffbd0318ed08d8afbfa1da0977 +P 1e57f67b20a1c01ede36d684be628e9270bf109a +R a19a15248ea3d7c53bb59593fa01c33d +U drh +Z e6c94fb8a2515aaa56cdd644b73247d7 diff --git a/manifest.uuid b/manifest.uuid index 414d8215f6..0ddf6b66df 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e57f67b20a1c01ede36d684be628e9270bf109a \ No newline at end of file +9830c343bc954b828f6ca752f8ae63e2c0a980c1 \ No newline at end of file diff --git a/src/vdbemem.c b/src/vdbemem.c index d782696149..378de2deb7 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -827,22 +827,23 @@ int sqlite3VdbeMemFromBtree( sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; + pMem->n = (int)amt; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ - pMem->flags = MEM_Blob|MEM_Term; - pMem->enc = 0; - pMem->memType = MEM_Blob; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } - pMem->z[amt] = 0; - pMem->z[amt+1] = 0; - if( rc!=SQLITE_OK ){ + if( rc==SQLITE_OK ){ + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + pMem->flags = MEM_Blob|MEM_Term; + pMem->memType = MEM_Blob; + pMem->n = (int)amt; + }else{ sqlite3VdbeMemRelease(pMem); } } - pMem->n = (int)amt; return rc; }