From d10d18da5f65a36ed76c09289e33ed13432d0ca3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 7 Feb 2015 15:16:35 +0000 Subject: [PATCH 1/9] Fix potential 32-bit integer overflow problems on the offset and length parameters to sqlite3_blob_read() and sqlite3_blob_write(). For sqlite3_blob_open(), make sure the *ppBlob return parameter is zeroed if the interface fails with SQLITE_MISUSE. FossilOrigin-Name: 5df02f50f8348dfde4fc15126abc7b7ef7803e69 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeblob.c | 11 ++++++++--- test/incrblob2.test | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b31e5b6454..033c8ecf04 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\s".info"\sto\s".dbinfo"\sand\sadd\san\soptional\ssecond\sargument\nwhich\sis\sthe\sATTACH-ed\sDB\sabout\swhich\sinformation\sis\sprovided.\s\sProvide\n".indexes"\sas\san\salternative\sname\sto\sthe\slegacy\s".indices"\scommand. -D 2015-02-06T14:51:13.355 +C Fix\spotential\s32-bit\sinteger\soverflow\sproblems\son\sthe\soffset\sand\slength\nparameters\sto\ssqlite3_blob_read()\sand\ssqlite3_blob_write().\s\sFor\nsqlite3_blob_open(),\smake\ssure\sthe\s*ppBlob\sreturn\sparameter\sis\szeroed\sif\nthe\sinterface\sfails\swith\sSQLITE_MISUSE. +D 2015-02-07T15:16:35.893 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -298,7 +298,7 @@ F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78 F src/vdbeapi.c 4bc511a46b9839392ae0e90844a71dc96d9dbd71 F src/vdbeaux.c 97911edb61074b871ec4aa2d6bb779071643dee5 -F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778 +F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 @@ -638,7 +638,7 @@ F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554 F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328 -F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600 +F test/incrblob2.test 0d8821730a84f90af78a9dd547fe7a2480a06240 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0a3100a7f264ffce6078c35e341f2f0af6c09fbb -R a582dddcff23f4b3aa0ab625ed7ba566 +P 0f65a7e2e09f801b66897479d501607caeae4abf +R a72e608518946b8cddba99b1913bccc8 U drh -Z 91c27780af6a4d5e0c7b8a8aa90c189d +Z 826c67b7d3493617a37693ae1605b2c3 diff --git a/manifest.uuid b/manifest.uuid index 408d77792f..c363eec9d9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0f65a7e2e09f801b66897479d501607caeae4abf \ No newline at end of file +5df02f50f8348dfde4fc15126abc7b7ef7803e69 \ No newline at end of file diff --git a/src/vdbeblob.c b/src/vdbeblob.c index cf1eb59054..ea01f5ce80 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -154,12 +154,17 @@ int sqlite3_blob_open( Incrblob *pBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || ppBlob==0 || zTable==0 ){ + if( ppBlob==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + *ppBlob = 0; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif flags = !!flags; /* flags = (flags ? 1 : 0); */ - *ppBlob = 0; sqlite3_mutex_enter(db->mutex); @@ -373,7 +378,7 @@ static int blobReadWrite( sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; - if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ + if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; }else if( v==0 ){ diff --git a/test/incrblob2.test b/test/incrblob2.test index a8f40f09dc..1a235f7d22 100644 --- a/test/incrblob2.test +++ b/test/incrblob2.test @@ -324,12 +324,34 @@ do_test incrblob2-6.2 { sqlite3_blob_read $rdHandle 0 2 } {AB} +do_test incrblob2-6.2b { + set rc [catch { + # Prior to 2015-02-07, the following caused a segfault due to + # integer overflow. + sqlite3_blob_read $rdHandle 2147483647 2147483647 + } errmsg] + lappend rc $errmsg +} {1 SQLITE_ERROR} + do_test incrblob2-6.3 { set wrHandle [db incrblob t1 data 1] sqlite3_blob_write $wrHandle 0 ZZZZZZZZZZ sqlite3_blob_read $rdHandle 2 4 } {ZZZZ} +do_test incrblob2-6.3b { + set rc [catch { + # Prior to 2015-02-07, the following caused a segfault due to + # integer overflow. + sqlite3_blob_write $wrHandle 2147483647 YYYYYYYYYYYYYYYYYY + } errmsg] + lappend rc $errmsg +} {1 SQLITE_ERROR} +do_test incrblob2-6.3c { + sqlite3_blob_read $rdHandle 2 4 +} {ZZZZ} + + do_test incrblob2-6.4 { close $wrHandle close $rdHandle From 31e7147dfa40c6278722d1ac30b74b77a0c5a970 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 10:20:19 +0000 Subject: [PATCH 2/9] Fix over-length source code lines in resolver.c. No logic changes. FossilOrigin-Name: c12edb85076d0832e3a0abbbba4d07f3cb5d7f0e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/resolve.c | 41 ++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 033c8ecf04..ecfb3a4eab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\spotential\s32-bit\sinteger\soverflow\sproblems\son\sthe\soffset\sand\slength\nparameters\sto\ssqlite3_blob_read()\sand\ssqlite3_blob_write().\s\sFor\nsqlite3_blob_open(),\smake\ssure\sthe\s*ppBlob\sreturn\sparameter\sis\szeroed\sif\nthe\sinterface\sfails\swith\sSQLITE_MISUSE. -D 2015-02-07T15:16:35.893 +C Fix\sover-length\ssource\scode\slines\sin\sresolver.c.\s\sNo\slogic\schanges. +D 2015-02-09T10:20:19.068 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9 F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada +F src/resolve.c 4ebd1064bded2556a8856c6f00fe2b9642f6efc3 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0f65a7e2e09f801b66897479d501607caeae4abf -R a72e608518946b8cddba99b1913bccc8 +P 5df02f50f8348dfde4fc15126abc7b7ef7803e69 +R a6e72909415716c47fbdc8c9892a4441 U drh -Z 826c67b7d3493617a37693ae1605b2c3 +Z da26ece2df8d0d323ede5e0a841cad93 diff --git a/manifest.uuid b/manifest.uuid index c363eec9d9..86b84ce37d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5df02f50f8348dfde4fc15126abc7b7ef7803e69 \ No newline at end of file +c12edb85076d0832e3a0abbbba4d07f3cb5d7f0e \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index d4bd548c93..3cca168325 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -247,9 +247,10 @@ static int lookupName( testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IsCheck ); if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ - /* Silently ignore database qualifiers inside CHECK constraints and partial - ** indices. Do not raise errors because that might break legacy and - ** because it does not hurt anything to just ignore the database name. */ + /* Silently ignore database qualifiers inside CHECK constraints and + ** partial indices. Do not raise errors because that might break + ** legacy and because it does not hurt anything to just ignore the + ** database name. */ zDb = 0; }else{ for(i=0; inDb; i++){ @@ -320,7 +321,8 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; - assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->jointype & JT_RIGHT)==0 ); if( (pMatch->jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } @@ -641,7 +643,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->affinity = SQLITE_AFF_INTEGER; break; } -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + && !defined(SQLITE_OMIT_SUBQUERY) */ /* A lone identifier is the name of a column. */ @@ -706,19 +709,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + sqlite3ErrorMsg(pParse, + "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ - /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to - ** likelihood(X, 0.0625). - ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for - ** likelihood(X,0.0625). - ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for - ** likelihood(X,0.9375). - ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to - ** likelihood(X,0.9375). */ + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is + ** equivalent to likelihood(X, 0.0625). + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is + ** short-hand for likelihood(X,0.0625). + ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand + ** for likelihood(X,0.9375). + ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent + ** to likelihood(X,0.9375). */ /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; } @@ -735,7 +739,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } #endif - if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant); + if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ + ExprSetProperty(pExpr,EP_Constant); + } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); @@ -1046,7 +1052,8 @@ int sqlite3ResolveOrderGroupBy( resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0); + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, + zType,0); } } return 0; From 0e86a1ac087e4e97be51cfa8e175da4a90a85f23 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 11:54:41 +0000 Subject: [PATCH 3/9] In selecttrace mode 0x100, show a complete parse-tree both before and after query flattening. This is a change to debugging code only. FossilOrigin-Name: b3c6b8a3c1075d2a87cef68f061d6a0098e6d8d0 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 7 +++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index ecfb3a4eab..b716294ece 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sover-length\ssource\scode\slines\sin\sresolver.c.\s\sNo\slogic\schanges. -D 2015-02-09T10:20:19.068 +C In\sselecttrace\smode\s0x100,\sshow\sa\scomplete\sparse-tree\sboth\sbefore\sand\safter\nquery\sflattening.\s\sThis\sis\sa\schange\sto\sdebugging\scode\sonly. +D 2015-02-09T11:54:41.074 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 4ebd1064bded2556a8856c6f00fe2b9642f6efc3 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc +F src/select.c 6ea3518b8863ec631c0481ba03dc283ea9140747 F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5df02f50f8348dfde4fc15126abc7b7ef7803e69 -R a6e72909415716c47fbdc8c9892a4441 +P c12edb85076d0832e3a0abbbba4d07f3cb5d7f0e +R 592949bfa9cc2e6e32d5144cda2bc252 U drh -Z da26ece2df8d0d323ede5e0a841cad93 +Z 15610b55190883b540f12ad788effd4f diff --git a/manifest.uuid b/manifest.uuid index 86b84ce37d..86de97c36c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c12edb85076d0832e3a0abbbba4d07f3cb5d7f0e \ No newline at end of file +b3c6b8a3c1075d2a87cef68f061d6a0098e6d8d0 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 8fbd4bb261..8563ec1006 100644 --- a/src/select.c +++ b/src/select.c @@ -3444,6 +3444,13 @@ static int flattenSubquery( /***** If we reach this point, flattening is permitted. *****/ SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", pSub->zSelName, pSub, iFrom)); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + sqlite3DebugPrintf("Befor flattening:\n"); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; From 17645f5eecb950205481179bb0dee1e5332a2e8e Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 13:42:59 +0000 Subject: [PATCH 4/9] In selecttrace 0x100 mode, show the parse tree after name resolution instead of before flattening, so that it is always seen even if flattening does not occur. Also: add the hex pointer value to the top of each SELECT tree. FossilOrigin-Name: aa093fef2d2a7e26d987b46654963e4d7e66d444 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index b716294ece..aac267bbad 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sselecttrace\smode\s0x100,\sshow\sa\scomplete\sparse-tree\sboth\sbefore\sand\safter\nquery\sflattening.\s\sThis\sis\sa\schange\sto\sdebugging\scode\sonly. -D 2015-02-09T11:54:41.074 +C In\sselecttrace\s0x100\smode,\sshow\sthe\sparse\stree\safter\sname\sresolution\sinstead\nof\sbefore\sflattening,\sso\sthat\sit\sis\salways\sseen\seven\sif\sflattening\sdoes\snot\noccur.\s\sAlso:\sadd\sthe\shex\spointer\svalue\sto\sthe\stop\sof\seach\sSELECT\stree. +D 2015-02-09T13:42:59.910 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -230,7 +230,7 @@ F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 4ebd1064bded2556a8856c6f00fe2b9642f6efc3 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 6ea3518b8863ec631c0481ba03dc283ea9140747 +F src/select.c edcf8ba8163526f2340f10f19b0a71547c6f97ba F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c12edb85076d0832e3a0abbbba4d07f3cb5d7f0e -R 592949bfa9cc2e6e32d5144cda2bc252 +P b3c6b8a3c1075d2a87cef68f061d6a0098e6d8d0 +R d021c59225e931bc74b845a3c2d5b904 U drh -Z 15610b55190883b540f12ad788effd4f +Z ece5ae1a696e0ba02ef3e8bf97d71c38 diff --git a/manifest.uuid b/manifest.uuid index 86de97c36c..036d4651a7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b3c6b8a3c1075d2a87cef68f061d6a0098e6d8d0 \ No newline at end of file +aa093fef2d2a7e26d987b46654963e4d7e66d444 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 8563ec1006..058bf3d577 100644 --- a/src/select.c +++ b/src/select.c @@ -3444,13 +3444,6 @@ static int flattenSubquery( /***** If we reach this point, flattening is permitted. *****/ SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", pSub->zSelName, pSub, iFrom)); -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ - sqlite3DebugPrintf("Befor flattening:\n"); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; @@ -4759,6 +4752,13 @@ int sqlite3Select( } isAgg = (p->selFlags & SF_Aggregate)!=0; assert( pEList!=0 ); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + /* Begin generating code. */ @@ -5504,9 +5504,9 @@ select_end: void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); - sqlite3TreeViewLine(pView, "SELECT%s%s", + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : "") + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p ); if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pWhere ) n++; From 63f845734e7de67fb04ad1e8990c41850547ce07 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 14:07:07 +0000 Subject: [PATCH 5/9] Rename the internal "EP_Constant" bitmask to a less misleading "EP_ConstFunc". FossilOrigin-Name: 4ef7ceced2b0000d21f7f8014384c04a0e4661d3 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 2 +- src/resolve.c | 2 +- src/sqliteInt.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index aac267bbad..10002ebccf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sselecttrace\s0x100\smode,\sshow\sthe\sparse\stree\safter\sname\sresolution\sinstead\nof\sbefore\sflattening,\sso\sthat\sit\sis\salways\sseen\seven\sif\sflattening\sdoes\snot\noccur.\s\sAlso:\sadd\sthe\shex\spointer\svalue\sto\sthe\stop\sof\seach\sSELECT\stree. -D 2015-02-09T13:42:59.910 +C Rename\sthe\sinternal\s"EP_Constant"\sbitmask\sto\sa\sless\smisleading\s"EP_ConstFunc". +D 2015-02-09T14:07:07.358 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef -F src/expr.c abe930897ccafae3819fd2855cbc1b00c262fd12 +F src/expr.c d66424535d3155eca7f2d8820d26b96870dfcb2d F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12 F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430 @@ -228,14 +228,14 @@ F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9 F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c 4ebd1064bded2556a8856c6f00fe2b9642f6efc3 +F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c edcf8ba8163526f2340f10f19b0a71547c6f97ba F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h c4e05f7489cd300f856e2283d5e61302ce826471 +F src/sqliteInt.h 436c02d0877b9b9a1c3351717c2c93bd248000e9 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b3c6b8a3c1075d2a87cef68f061d6a0098e6d8d0 -R d021c59225e931bc74b845a3c2d5b904 +P aa093fef2d2a7e26d987b46654963e4d7e66d444 +R f51c0a3a4046c27eeedc2e4a71b172ba U drh -Z ece5ae1a696e0ba02ef3e8bf97d71c38 +Z 4b79838e5fc774abeed8438ce319eb67 diff --git a/manifest.uuid b/manifest.uuid index 036d4651a7..c03c5df094 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aa093fef2d2a7e26d987b46654963e4d7e66d444 \ No newline at end of file +4ef7ceced2b0000d21f7f8014384c04a0e4661d3 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 25bd958ceb..2f0fe4a581 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1249,7 +1249,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ ** and either pWalker->eCode==4 or 5 or the function has the ** SQLITE_FUNC_CONST flag. */ case TK_FUNCTION: - if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){ + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ return WRC_Continue; }else{ pWalker->eCode = 0; diff --git a/src/resolve.c b/src/resolve.c index 3cca168325..47df7243f8 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -740,7 +740,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } #endif if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ - ExprSetProperty(pExpr,EP_Constant); + ExprSetProperty(pExpr,EP_ConstFunc); } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0bc6f679dd..f5892db4bc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2044,7 +2044,7 @@ struct Expr { #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_Constant 0x080000 /* Node is a constant */ +#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ /* From 885a5b030ee3717b78bfb82d61e6ee38ef0892ea Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 15:21:36 +0000 Subject: [PATCH 6/9] Disable the query flattener for aggregate subqueries if the parent query uses other subqueries in its result set or WHERE clause or ORDER BY clause. Preliminary fix for ticket [2f7170d73bf9abf8]. However it still contains a defect similar to the COLLATE problem of [ca0d20b6cddd]. FossilOrigin-Name: 0b7d65e3fda676d193347cb782854c28a48252af --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- src/expr.c | 17 +++++++++++++++-- src/parse.y | 8 ++++---- src/select.c | 18 +++++++++++++++--- src/sqliteInt.h | 7 +++++++ 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 10002ebccf..fffe5424f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sthe\sinternal\s"EP_Constant"\sbitmask\sto\sa\sless\smisleading\s"EP_ConstFunc". -D 2015-02-09T14:07:07.358 +C Disable\sthe\squery\sflattener\sfor\saggregate\ssubqueries\sif\sthe\sparent\squery\nuses\sother\ssubqueries\sin\sits\sresult\sset\sor\sWHERE\sclause\sor\sORDER\sBY\sclause.\nPreliminary\sfix\sfor\sticket\s[2f7170d73bf9abf8].\s\sHowever\sit\sstill\scontains\na\sdefect\ssimilar\sto\sthe\sCOLLATE\sproblem\sof\s[ca0d20b6cddd]. +D 2015-02-09T15:21:36.228 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef -F src/expr.c d66424535d3155eca7f2d8820d26b96870dfcb2d +F src/expr.c 3fbe5a2a0be67b337b4947adde81694b4d48a84d F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12 F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430 @@ -219,7 +219,7 @@ F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 -F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086 +F src/parse.y d6507371513e94c03e61f7ec097d7b7e90a66665 F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf @@ -230,12 +230,12 @@ F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c edcf8ba8163526f2340f10f19b0a71547c6f97ba +F src/select.c 15490b9da27a688a9fa09f943ebf4e6c749dc33b F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h 436c02d0877b9b9a1c3351717c2c93bd248000e9 +F src/sqliteInt.h b7b14a15f2c60e15f99145e9f5a90f5280e98582 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -1239,7 +1239,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aa093fef2d2a7e26d987b46654963e4d7e66d444 -R f51c0a3a4046c27eeedc2e4a71b172ba +P 4ef7ceced2b0000d21f7f8014384c04a0e4661d3 +R b512281a09e1b31cff93e7ca5bacbcdc +T *branch * tkt-2f7170d7 +T *sym-tkt-2f7170d7 * +T -sym-trunk * U drh -Z 4b79838e5fc774abeed8438ce319eb67 +Z f683ca0757ba5ade9ef6c768a943d35e diff --git a/manifest.uuid b/manifest.uuid index c03c5df094..1553ada2f8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ef7ceced2b0000d21f7f8014384c04a0e4661d3 \ No newline at end of file +0b7d65e3fda676d193347cb782854c28a48252af \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 2f0fe4a581..2def950f23 100644 --- a/src/expr.c +++ b/src/expr.c @@ -490,11 +490,11 @@ void sqlite3ExprAttachSubtrees( }else{ if( pRight ){ pRoot->pRight = pRight; - pRoot->flags |= EP_Collate & pRight->flags; + pRoot->flags |= EP_Propagate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; - pRoot->flags |= EP_Collate & pLeft->flags; + pRoot->flags |= EP_Propagate & pLeft->flags; } exprSetHeight(pRoot); } @@ -1209,6 +1209,19 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ sqlite3DbFree(db, pList); } +/* +** Return TRUE if any expression in ExprList has any of the EP_* +** properties given by "m" +*/ +int sqlite3AnyExprListHasProperty(const ExprList *pList, u32 m){ + int i; + if( pList==0 ) return 0; + for(i=0; inExpr; i++){ + if( ExprHasProperty(pList->a[i].pExpr, m) ) return 1; + } + return 0; +} + /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The diff --git a/src/parse.y b/src/parse.y index 544888a228..6730312d7c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1091,7 +1091,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = X; - ExprSetProperty(A.pExpr, EP_xIsSelect); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, X); @@ -1103,7 +1103,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = Y; - ExprSetProperty(A.pExpr, EP_xIsSelect); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); @@ -1117,7 +1117,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(A.pExpr, EP_xIsSelect); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); @@ -1130,7 +1130,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = Y; - ExprSetProperty(p, EP_xIsSelect); + ExprSetProperty(p, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeight(pParse, p); }else{ sqlite3SelectDelete(pParse->db, Y); diff --git a/src/select.c b/src/select.c index 058bf3d577..2c4c9e41f9 100644 --- a/src/select.c +++ b/src/select.c @@ -3194,7 +3194,10 @@ static void substSelect( ** ** (1) The subquery and the outer query do not both use aggregates. ** -** (2) The subquery is not an aggregate or the outer query is not a join. +** (2) The subquery is not an aggregate or (2a) the outer query is not a join +** and (2b) the outer query does not use subqueries other than the one +** FROM-clause subquery that is a candidate for flattening. (2b is +** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ** ** (3) The subquery is not the right operand of a left outer join ** (Originally ticket #306. Strengthened by ticket #3300) @@ -3331,8 +3334,17 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + if( subqueryIsAgg ){ + if( isAgg ) return 0; /* Restriction (1) */ + if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ + if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) + || sqlite3AnyExprListHasProperty(p->pEList,EP_Subquery) + || sqlite3AnyExprListHasProperty(p->pOrderBy,EP_Subquery) + ){ + return 0; /* Restriction (2b) */ + } + } + pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f5892db4bc..e07ee4a5bd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2046,6 +2046,12 @@ struct Expr { #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + +/* +** Combinations of two or more EP_* flags +*/ +#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ /* ** These macros can be used to test, set, or clear bits in the @@ -3153,6 +3159,7 @@ ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListDelete(sqlite3*, ExprList*); +int sqlite3AnyExprListHasProperty(const ExprList*,u32); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); From 2308ed385462208621ce052e5736b317fa81068f Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 16:09:34 +0000 Subject: [PATCH 7/9] Propagate the COLLATE operator upward through function calls. Initial fix for ticket [ca0d20b6cdddec5e8]. FossilOrigin-Name: c053448a55f9d030e8ffe88cf4fc14ada7f6ec19 --- manifest | 25 +++++++++------------ manifest.uuid | 2 +- src/delete.c | 2 +- src/expr.c | 56 ++++++++++++++++++++++++++++++++++------------ src/parse.y | 12 +++++----- src/select.c | 4 ++-- src/sqliteInt.h | 5 ++--- test/collate8.test | 34 +++++++++++++++++++++++++++- 8 files changed, 98 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index fffe5424f6..30d2176730 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\squery\sflattener\sfor\saggregate\ssubqueries\sif\sthe\sparent\squery\nuses\sother\ssubqueries\sin\sits\sresult\sset\sor\sWHERE\sclause\sor\sORDER\sBY\sclause.\nPreliminary\sfix\sfor\sticket\s[2f7170d73bf9abf8].\s\sHowever\sit\sstill\scontains\na\sdefect\ssimilar\sto\sthe\sCOLLATE\sproblem\sof\s[ca0d20b6cddd]. -D 2015-02-09T15:21:36.228 +C Propagate\sthe\sCOLLATE\soperator\supward\sthrough\sfunction\scalls.\nInitial\sfix\sfor\sticket\s[ca0d20b6cdddec5e8]. +D 2015-02-09T16:09:34.923 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -181,8 +181,8 @@ F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac -F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef -F src/expr.c 3fbe5a2a0be67b337b4947adde81694b4d48a84d +F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e +F src/expr.c f40082f5d31a76ea53302e202899a4959555b009 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12 F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430 @@ -219,7 +219,7 @@ F src/os_win.c 8223e7db5b7c4a81d8b161098ac3959400434cdb F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 -F src/parse.y d6507371513e94c03e61f7ec097d7b7e90a66665 +F src/parse.y 0f8e7d60f0ab3cb53d270adef69259ac307d83a8 F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf @@ -230,12 +230,12 @@ F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f4d79e31ffa5820c2e3d1740baa5e9b190425f2b F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 15490b9da27a688a9fa09f943ebf4e6c749dc33b +F src/select.c e46cef4c224549b439384c88fc7f57ba064dad54 F src/shell.c 82c25508dac802b32198af6f5256ca1597c6a1af F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h b7b14a15f2c60e15f99145e9f5a90f5280e98582 +F src/sqliteInt.h 57a405ae6d2ed10fff52de376d18f21e04d96609 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -403,7 +403,7 @@ F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177 F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907 F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868 -F test/collate8.test df26649cfcbddf109c04122b340301616d3a88f6 +F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334 F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 @@ -1239,10 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4ef7ceced2b0000d21f7f8014384c04a0e4661d3 -R b512281a09e1b31cff93e7ca5bacbcdc -T *branch * tkt-2f7170d7 -T *sym-tkt-2f7170d7 * -T -sym-trunk * +P 0b7d65e3fda676d193347cb782854c28a48252af +R 0fcf0b67c1cdaee9bbc7c2fe09760751 U drh -Z f683ca0757ba5ade9ef6c768a943d35e +Z d2e1dd3a2a5ed2929029c668f1fd20a5 diff --git a/manifest.uuid b/manifest.uuid index 1553ada2f8..35da9caa79 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b7d65e3fda676d193347cb782854c28a48252af \ No newline at end of file +c053448a55f9d030e8ffe88cf4fc14ada7f6ec19 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 011fb80dee..ef6aace1c8 100644 --- a/src/delete.c +++ b/src/delete.c @@ -189,7 +189,7 @@ Expr *sqlite3LimitWhere( pInClause->x.pSelect = pSelect; pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeight(pParse, pInClause); + sqlite3ExprSetHeightAndFlags(pParse, pInClause); return pInClause; /* something went wrong. clean up anything allocated. */ diff --git a/src/expr.c b/src/expr.c index 2def950f23..496c7a3176 100644 --- a/src/expr.c +++ b/src/expr.c @@ -146,10 +146,20 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } if( p->flags & EP_Collate ){ - if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - p = p->pRight; + Expr *pNext = p->pRight; + if( p->x.pList!=0 && !ExprHasProperty(p, EP_xIsSelect) ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; + } + } + } + p = pNext; } }else{ break; @@ -355,6 +365,9 @@ static void heightOfSelect(Select *p, int *pnHeight){ ** Expr.pSelect member has a height of 1. Any other expression ** has a height equal to the maximum height of any other ** referenced Expr plus one. +** +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, +** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; @@ -362,8 +375,9 @@ static void exprSetHeight(Expr *p){ heightOfExpr(p->pRight, &nHeight); if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); - }else{ + }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } p->nHeight = nHeight + 1; } @@ -372,8 +386,11 @@ static void exprSetHeight(Expr *p){ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. +** +** Also propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. */ -void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -387,8 +404,17 @@ int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#else - #define exprSetHeight(y) +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ +/* +** Propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } +} +#define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* @@ -594,7 +620,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ } pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeight(pParse, pNew); + sqlite3ExprSetHeightAndFlags(pParse, pNew); return pNew; } @@ -1210,16 +1236,18 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ } /* -** Return TRUE if any expression in ExprList has any of the EP_* -** properties given by "m" +** Return the bitwise-OR of all Expr.flags fields in the given +** ExprList. */ -int sqlite3AnyExprListHasProperty(const ExprList *pList, u32 m){ +u32 sqlite3ExprListFlags(const ExprList *pList){ int i; - if( pList==0 ) return 0; - for(i=0; inExpr; i++){ - if( ExprHasProperty(pList->a[i].pExpr, m) ) return 1; + u32 m = 0; + if( pList ){ + for(i=0; inExpr; i++){ + m |= pList->a[i].pExpr->flags; + } } - return 0; + return m; } /* diff --git a/src/parse.y b/src/parse.y index 6730312d7c..78e79cd361 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1078,7 +1078,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } @@ -1092,7 +1092,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = X; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, X); } @@ -1104,7 +1104,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = Y; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1118,7 +1118,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } @@ -1131,7 +1131,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( p ){ p->x.pSelect = Y; ExprSetProperty(p, EP_xIsSelect|EP_Subquery); - sqlite3ExprSetHeight(pParse, p); + sqlite3ExprSetHeightAndFlags(pParse, p); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1145,7 +1145,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); diff --git a/src/select.c b/src/select.c index 2c4c9e41f9..91b3d4345f 100644 --- a/src/select.c +++ b/src/select.c @@ -3338,8 +3338,8 @@ static int flattenSubquery( if( isAgg ) return 0; /* Restriction (1) */ if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) - || sqlite3AnyExprListHasProperty(p->pEList,EP_Subquery) - || sqlite3AnyExprListHasProperty(p->pOrderBy,EP_Subquery) + || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 + || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 ){ return 0; /* Restriction (2b) */ } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e07ee4a5bd..3f9a3a7cc7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3159,7 +3159,7 @@ ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListDelete(sqlite3*, ExprList*); -int sqlite3AnyExprListHasProperty(const ExprList*,u32); +u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -3743,12 +3743,11 @@ void sqlite3MemJournalOpen(sqlite3_file *); int sqlite3MemJournalSize(void); int sqlite3IsMemJournal(sqlite3_file *); +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 - void sqlite3ExprSetHeight(Parse *pParse, Expr *p); int sqlite3SelectExprHeight(Select *); int sqlite3ExprCheckHeight(Parse*, int); #else - #define sqlite3ExprSetHeight(x,y) #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif diff --git a/test/collate8.test b/test/collate8.test index 60a89162dd..b06c87d2f8 100644 --- a/test/collate8.test +++ b/test/collate8.test @@ -13,7 +13,9 @@ # focus of this script is making sure collations pass through the # unary + operator. # -# $Id: collate8.test,v 1.2 2008/08/25 12:14:09 drh Exp $ +# 2015-02-09: Added tests to make sure COLLATE passes through function +# calls. Ticket [ca0d20b6cdddec5e81b8d66f89c46a5583b5f6f6]. +# set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -122,4 +124,34 @@ do_test collate8-2.8 { } } {abc} +# Make sure the COLLATE operator perculates up through function calls +# and other Expr structures that use the Expr.x.pList field. +# +do_execsql_test collate8-3.1 { + SELECT 'abc'==('ABC'||'') COLLATE nocase; + SELECT 'abc'==('ABC'||'' COLLATE nocase); + SELECT 'abc'==('ABC'||('' COLLATE nocase)); + SELECT 'abc'==('ABC'||upper('' COLLATE nocase)); +} {1 1 1 1} +do_execsql_test collate8-3.2 { + SELECT 'abc'==('ABC'||max('' COLLATE nocase,'' COLLATE binary)); +} {1} + +# The COLLATE binary is on the left and so takes precedence +do_execsql_test collate8-3.3 { + SELECT 'abc'==('ABC'||max('' COLLATE binary,'' COLLATE nocase)); +} {0} + +do_execsql_test collate8-3.4 { + SELECT 'abc'==('ABC'||CASE WHEN 1-1=2 THEN '' COLLATE nocase + ELSE '' COLLATE binary END); + SELECT 'abc'==('ABC'||CASE WHEN 1+1=2 THEN '' COLLATE nocase + ELSE '' COLLATE binary END); +} {1 1} +do_execsql_test collate8-3.5 { + SELECT 'abc'==('ABC'||CASE WHEN 1=2 THEN '' COLLATE binary + ELSE '' COLLATE nocase END); +} {0} + + finish_test From 2c5e9b56721f110016d99b4ba32ccb111e39971c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Feb 2015 16:34:33 +0000 Subject: [PATCH 8/9] Add test cases for the query flattener fix for ticket [2f7170d73bf9abf8]. FossilOrigin-Name: dd8f7f7511639a1baa41a6ff2e359dc6f1e66943 --- manifest | 12 +++++----- manifest.uuid | 2 +- test/select6.test | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 30d2176730..3dc1515cc4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Propagate\sthe\sCOLLATE\soperator\supward\sthrough\sfunction\scalls.\nInitial\sfix\sfor\sticket\s[ca0d20b6cdddec5e8]. -D 2015-02-09T16:09:34.923 +C Add\stest\scases\sfor\sthe\squery\sflattener\sfix\sfor\nticket\s[2f7170d73bf9abf8]. +D 2015-02-09T16:34:33.249 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -834,7 +834,7 @@ F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 F test/select4.test 8c5a60d439e2df824aed56223566877a883c5c84 F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 -F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2 +F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0b7d65e3fda676d193347cb782854c28a48252af -R 0fcf0b67c1cdaee9bbc7c2fe09760751 +P c053448a55f9d030e8ffe88cf4fc14ada7f6ec19 +R 2d5172d7784b0dfa3e9c983c86806f6a U drh -Z d2e1dd3a2a5ed2929029c668f1fd20a5 +Z 7fd9b7cb5d6f8f4f67ff4b5b0cf25a38 diff --git a/manifest.uuid b/manifest.uuid index 35da9caa79..9cc0e5086e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c053448a55f9d030e8ffe88cf4fc14ada7f6ec19 \ No newline at end of file +dd8f7f7511639a1baa41a6ff2e359dc6f1e66943 \ No newline at end of file diff --git a/test/select6.test b/test/select6.test index 64a8519d89..590512a6b0 100644 --- a/test/select6.test +++ b/test/select6.test @@ -557,5 +557,61 @@ do_catchsql_test 10.8 { ) } $err +# 2015-02-09 Ticket [2f7170d73bf9abf80339187aa3677dce3dbcd5ca] +# "misuse of aggregate" error if aggregate column from FROM +# subquery is used in correlated subquery +# +do_execsql_test 11.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(w INT, x INT); + INSERT INTO t1(w,x) + VALUES(1,10),(2,20),(3,30), + (2,21),(3,31), + (3,32); + CREATE INDEX t1wx ON t1(w,x); + + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(w INT, y VARCHAR(8)); + INSERT INTO t2(w,y) VALUES(1,'one'),(2,'two'),(3,'three'),(4,'four'); + CREATE INDEX t2wy ON t2(w,y); + + SELECT cnt, xyz, (SELECT y FROM t2 WHERE w=cnt), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.2 { + SELECT cnt, xyz, lower((SELECT y FROM t2 WHERE w=cnt)), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.3 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + WHERE (SELECT y FROM t2 WHERE w=cnt)!='two' + ORDER BY cnt, xyz; +} {1 1 | 3 3 |} +do_execsql_test 11.4 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY lower((SELECT y FROM t2 WHERE w=cnt)); +} {1 1 | 3 3 | 2 2 |} +do_execsql_test 11.5 { + SELECT cnt, xyz, + CASE WHEN (SELECT y FROM t2 WHERE w=cnt)=='two' + THEN 'aaa' ELSE 'bbb' + END, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY +cnt; +} {1 1 bbb | 2 2 aaa | 3 3 bbb |} + +do_execsql_test 11.100 { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(x); + CREATE TABLE t2(y, z); + SELECT ( SELECT y FROM t2 WHERE z = cnt ) + FROM ( SELECT count(*) AS cnt FROM t1 ); +} {{}} + finish_test From 9fab5ed01f7b1cdb4f56ee1c3a2bc9de67c5c36c Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 9 Feb 2015 17:46:11 +0000 Subject: [PATCH 9/9] Fix WITHOUT ROWID table handing in sqlite3_analyzer. FossilOrigin-Name: 937e0fe7008c0f76b6a584180df9a9457166a0b1 --- manifest | 14 +++++++------- manifest.uuid | 2 +- tool/spaceanal.tcl | 35 +++++++++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 10002ebccf..13b7009965 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sthe\sinternal\s"EP_Constant"\sbitmask\sto\sa\sless\smisleading\s"EP_ConstFunc". -D 2015-02-09T14:07:07.358 +C Fix\sWITHOUT\sROWID\stable\shanding\sin\ssqlite3_analyzer. +D 2015-02-09T17:46:11.315 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1222,7 +1222,7 @@ F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b -F tool/spaceanal.tcl 8e50b217c56a6a086a1b47eac9d09c5cd65b996f +F tool/spaceanal.tcl d5a09620c66a6c144576cb9d2bdfa9a6fbe362a5 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff @@ -1239,7 +1239,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P aa093fef2d2a7e26d987b46654963e4d7e66d444 -R f51c0a3a4046c27eeedc2e4a71b172ba -U drh -Z 4b79838e5fc774abeed8438ce319eb67 +P 4ef7ceced2b0000d21f7f8014384c04a0e4661d3 +R 3dfd2d57b7936b7d1030a6a9083d3a68 +U dan +Z 936b36142dcc1fcccff0b983a2ef7c1f diff --git a/manifest.uuid b/manifest.uuid index c03c5df094..dd3e606fa8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ef7ceced2b0000d21f7f8014384c04a0e4661d3 \ No newline at end of file +937e0fe7008c0f76b6a584180df9a9457166a0b1 \ No newline at end of file diff --git a/tool/spaceanal.tcl b/tool/spaceanal.tcl index a227b85243..516d282445 100644 --- a/tool/spaceanal.tcl +++ b/tool/spaceanal.tcl @@ -4,6 +4,24 @@ # if {[catch { + +# Argument $tname is the name of a table within the database opened by +# database handle [db]. Return true if it is a WITHOUT ROWID table, or +# false otherwise. +# +proc is_without_rowid {tname} { + set t [string map {' ''} $tname] + db eval "PRAGMA index_list = '$t'" o { + if {$o(origin) == "pk"} { + set n $o(name) + if {0==[db one { SELECT count(*) FROM sqlite_master WHERE name=$n }]} { + return 1 + } + } + } + return 0 +} + # Get the name of the database to analyze # proc usage {} { @@ -167,20 +185,21 @@ set sql { SELECT name, tbl_name FROM sqlite_master WHERE rootpage>0 } foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] { set is_index [expr {$name!=$tblname}] + set idx_btree [expr {$is_index || [is_without_rowid $name]}] db eval { SELECT sum(ncell) AS nentry, - sum(isleaf(pagetype, $is_index) * ncell) AS leaf_entries, + sum(isleaf(pagetype, $idx_btree) * ncell) AS leaf_entries, sum(payload) AS payload, - sum(isoverflow(pagetype, $is_index) * payload) AS ovfl_payload, + sum(isoverflow(pagetype, $idx_btree) * payload) AS ovfl_payload, sum(path LIKE '%+000000') AS ovfl_cnt, max(mx_payload) AS mx_payload, - sum(isinternal(pagetype, $is_index)) AS int_pages, - sum(isleaf(pagetype, $is_index)) AS leaf_pages, - sum(isoverflow(pagetype, $is_index)) AS ovfl_pages, - sum(isinternal(pagetype, $is_index) * unused) AS int_unused, - sum(isleaf(pagetype, $is_index) * unused) AS leaf_unused, - sum(isoverflow(pagetype, $is_index) * unused) AS ovfl_unused, + sum(isinternal(pagetype, $idx_btree)) AS int_pages, + sum(isleaf(pagetype, $idx_btree)) AS leaf_pages, + sum(isoverflow(pagetype, $idx_btree)) AS ovfl_pages, + sum(isinternal(pagetype, $idx_btree) * unused) AS int_unused, + sum(isleaf(pagetype, $idx_btree) * unused) AS leaf_unused, + sum(isoverflow(pagetype, $idx_btree) * unused) AS ovfl_unused, sum(pgsize) AS compressed_size FROM temp.dbstat WHERE name = $name } break