From 5fb52caadfe3930efc91d2f04a3adb805732b442 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 31 Mar 2012 02:34:35 +0000 Subject: [PATCH 01/32] Do more aggressive optimization of the AND operator where one side or the other is always false. FossilOrigin-Name: f9a7e179cbbeeab5e57bbf392bef89750215546b --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/expr.c | 36 ++++++++++++++++++++++++++++++++++-- test/in.test | 14 +++++++++++++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 17608576f1..5e66a79aee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\susing\sthe\sOVERLAPPED\sstruct\son\sWinCE. -D 2012-03-30T16:44:33.303 +C Do\smore\saggressive\soptimization\sof\sthe\sAND\soperator\swhere\sone\sside\sor\sthe\nother\sis\salways\sfalse. +D 2012-03-31T02:34:35.585 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -135,7 +135,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e -F src/expr.c 7e40ea9f6899e31134be3c1b88b8347cf9ec40d7 +F src/expr.c ebb0e2b21379d4ec0c5c2c7c952784cb300c8436 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6 @@ -515,7 +515,7 @@ F test/fuzzer1.test 69cf1036b92fd3b8e1fd65bef4d7ee3f085c28fb F test/fuzzerfault.test ff2282c81797b6a355f0748d8b54c7287c5d2b25 F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 -F test/in.test a7b8a0f43da81cd08645b7a710099ffe9ad1126b +F test/in.test 5941096407d8c133b9eff15bd3e666624b6cbde3 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617 @@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P b34491869c4fb31d2fdd14c94a7db2e1c0e572ba -R 7c7c91e4f03aba786b8f3e6627280744 -U mistachkin -Z 7d31e5badb9fd33ec4e58af382112a75 +P 196ca3a8b007b9f792e969893d981f6c5aa2fccc +R d4cee1bded14d0c2a35aac2c2a8ea01d +U drh +Z c8013359e2c16f7dbb75906fb62e335f diff --git a/manifest.uuid b/manifest.uuid index aa0af4ede5..360fef573d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -196ca3a8b007b9f792e969893d981f6c5aa2fccc \ No newline at end of file +f9a7e179cbbeeab5e57bbf392bef89750215546b \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 5e3f1204a1..4751ec91bd 100644 --- a/src/expr.c +++ b/src/expr.c @@ -484,23 +484,55 @@ Expr *sqlite3PExpr( Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ - Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); - sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); + Expr *p; + if( op==TK_AND && pLeft && pRight ){ + /* Take advantage of short-circuit false optimization for AND */ + p = sqlite3ExprAnd(pParse->db, pLeft, pRight); + }else{ + p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); + } if( p ) { sqlite3ExprCheckHeight(pParse, p->nHeight); } return p; } +/* +** Return 1 if an expression must be FALSE in all cases and 0 if the +** expression might be true. This is an optimization. If is OK to +** return 0 here even if the expression really is always false (a +** false negative). But it is a bug to return 1 if the expression +** might be true in some rare circumstances (a false positive.) +** +** Note that if the expression is part of conditional for a +** LEFT JOIN, then we cannot determine at compile-time whether or not +** is it true or false, so always return 0. +*/ +static int exprAlwaysFalse(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v==0; +} + /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. +** +** If one side or the other of the AND is known to be false, then instead +** of returning an AND expression, just return a constant expression with +** a value of false. */ Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; + }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); }else{ Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); diff --git a/test/in.test b/test/in.test index 108f35589c..3b23f04bbf 100644 --- a/test/in.test +++ b/test/in.test @@ -258,17 +258,29 @@ do_test in-7.5 { SELECT a FROM t1 WHERE a IN (5) AND b NOT IN (); } } {5} -do_test in-7.6 { +do_test in-7.6.1 { execsql { SELECT a FROM ta WHERE a IN (); } } {} +do_test in-7.6.2 { + db status step +} {0} do_test in-7.7 { execsql { SELECT a FROM ta WHERE a NOT IN (); } } {1 2 3 4 6 8 10} +do_test in-7.8.1 { + execsql { + SELECT * FROM ta LEFT JOIN tb ON (ta.b=tb.b) WHERE ta.a IN (); + } +} {} +do_test in-7.8.2 { + db status step +} {0} + do_test in-8.1 { execsql { SELECT b FROM t1 WHERE a IN ('hello','there') From 2b9ee77fd69a1cd1456bee195ebbab5dc3a0dbce Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 31 Mar 2012 09:59:44 +0000 Subject: [PATCH 02/32] Fix a bug in the EXPLAIN code for listing trigger programs that was causing an out-of-bounds read. FossilOrigin-Name: c9342ca58105499a5eb61c3e6d016559b6072c95 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbeaux.c | 2 +- src/vdbemem.c | 12 ++++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 5e66a79aee..0042119b0d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\smore\saggressive\soptimization\sof\sthe\sAND\soperator\swhere\sone\sside\sor\sthe\nother\sis\salways\sfalse. -D 2012-03-31T02:34:35.585 +C Fix\sa\sbug\sin\sthe\sEXPLAIN\scode\sfor\slisting\strigger\sprograms\sthat\swas\scausing\san\sout-of-bounds\sread. +D 2012-03-31T09:59:44.574 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -245,9 +245,9 @@ F src/vdbe.c 8913926230bfc9d183fcd44e3d023c6d393b6548 F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82 F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91 -F src/vdbeaux.c 79cf42b70e211a52d664fc4d585ee2da0a64deac +F src/vdbeaux.c d52c8a424fdd4b1d5cf1ac93cc7cd20da023ec5c F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb -F src/vdbemem.c fb0ac964ccbcd94f595eb993c05bfd9c52468a4a +F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74 F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9 F src/vdbetrace.c d6e50e04e1ec498150e519058f617d91b8f5c843 F src/vtab.c ab90fb600a3f5e4b7c48d22a4cdb2d6b23239847 @@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 196ca3a8b007b9f792e969893d981f6c5aa2fccc -R d4cee1bded14d0c2a35aac2c2a8ea01d -U drh -Z c8013359e2c16f7dbb75906fb62e335f +P f9a7e179cbbeeab5e57bbf392bef89750215546b +R ab995d275ca5429ef68a8cbbd55bb89c +U dan +Z cbd6b70420ae30df5a5f82de3e30da3c diff --git a/manifest.uuid b/manifest.uuid index 360fef573d..8123f23dcb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f9a7e179cbbeeab5e57bbf392bef89750215546b \ No newline at end of file +c9342ca58105499a5eb61c3e6d016559b6072c95 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ef339d1e13..caa2bf6700 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1239,7 +1239,7 @@ int sqlite3VdbeList( for(j=0; jp4.pProgram ) break; } - if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){ + if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ apSub = (SubProgram **)pSub->z; apSub[nSub++] = pOp->p4.pProgram; pSub->flags |= MEM_Blob; diff --git a/src/vdbemem.c b/src/vdbemem.c index 088d3d64a4..fd964de2e9 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -59,10 +59,10 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ ** Make sure pMem->z points to a writable allocation of at least ** n bytes. ** -** If the memory cell currently contains string or blob data -** and the third argument passed to this function is true, the -** current content of the cell is preserved. Otherwise, it may -** be discarded. +** If the third argument passed to this function is true, then memory +** cell pMem must contain a string or blob. In this case the content is +** preserved. Otherwise, if the third parameter to this function is false, +** any current string or blob value may be discarded. ** ** This function sets the MEM_Dyn flag and clears any xDel callback. ** It also clears MEM_Ephem and MEM_Static. If the preserve flag is @@ -77,6 +77,10 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ ); assert( (pMem->flags&MEM_RowSet)==0 ); + /* If the preserve flag is set to true, then the memory cell must already + ** contain a valid string or blob value. */ + assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + if( n<32 ) n = 32; if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ From a25a42cfe773c71c1b92ceb6f65fb72d3aa79652 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 31 Mar 2012 11:58:23 +0000 Subject: [PATCH 03/32] Change the ICU tokenizer so that it does not attempt to call strlen(NULL). FossilOrigin-Name: 04298f1ac42c40cb2a48092b415acf96a08954b7 --- ext/fts3/fts3_icu.c | 5 ++++- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fts3defer.test | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/ext/fts3/fts3_icu.c b/ext/fts3/fts3_icu.c index a10a55d67b..5e9c900b09 100644 --- a/ext/fts3/fts3_icu.c +++ b/ext/fts3/fts3_icu.c @@ -110,7 +110,10 @@ static int icuOpen( *ppCursor = 0; - if( nInput<0 ){ + if( zInput==0 ){ + nInput = 0; + zInput = ""; + }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; diff --git a/manifest b/manifest index 0042119b0d..94e4cca145 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\sEXPLAIN\scode\sfor\slisting\strigger\sprograms\sthat\swas\scausing\san\sout-of-bounds\sread. -D 2012-03-31T09:59:44.574 +C Change\sthe\sICU\stokenizer\sso\sthat\sit\sdoes\snot\sattempt\sto\scall\sstrlen(NULL). +D 2012-03-31T11:58:23.752 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -70,7 +70,7 @@ F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551 F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914 F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec -F ext/fts3/fts3_icu.c 6c8f395cdf9e1e3afa7fadb7e523dbbf381c6dfa +F ext/fts3/fts3_icu.c 62ec177c55f6a5c6e994dd3e5fd3194b4045c347 F ext/fts3/fts3_porter.c a465b49fcb8249a755792f87516eff182efa42b3 F ext/fts3/fts3_snippet.c 51a3a34c217e24678a133782c1dfb6f2f70fe559 F ext/fts3/fts3_term.c 41e82ad335213d1c24356cf310dca1d3c13e7366 @@ -477,7 +477,7 @@ F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32 F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a -F test/fts3defer.test 2ea3fa028f8d9523f9c33dd8acc4555d567ea4ac +F test/fts3defer.test 6c2707be1b05b9790ba8ff91d3391d5fb425269e F test/fts3defer2.test 35867d33ba6db03f6c73bd6f5fc333ae14f68c81 F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 @@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P f9a7e179cbbeeab5e57bbf392bef89750215546b -R ab995d275ca5429ef68a8cbbd55bb89c +P c9342ca58105499a5eb61c3e6d016559b6072c95 +R e0716dc6380f52d6136a7e11cf5bb377 U dan -Z cbd6b70420ae30df5a5f82de3e30da3c +Z be3c953a1198ae2a4c78c4ed2dd05529 diff --git a/manifest.uuid b/manifest.uuid index 8123f23dcb..de3255bc98 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9342ca58105499a5eb61c3e6d016559b6072c95 \ No newline at end of file +04298f1ac42c40cb2a48092b415acf96a08954b7 \ No newline at end of file diff --git a/test/fts3defer.test b/test/fts3defer.test index bc50874e4a..4c8213d7f7 100644 --- a/test/fts3defer.test +++ b/test/fts3defer.test @@ -489,5 +489,39 @@ do_execsql_test 4.2 { SELECT * FROM x2 WHERE x2 MATCH 'a b c d e f g h i j k l m n o p q r s'; } {{a b c d e f g h i j k l m n o p q r s t u v w x y m}} +set tokenizers {1 simple} +ifcapable icu { lappend tokenizers 2 {icu en_US} } +foreach {tn tokenizer} $tokenizers { + do_execsql_test 5.$tn.1 " + CREATE VIRTUAL TABLE x3 USING FTS4(a, b, TOKENIZE $tokenizer) + " + do_execsql_test 5.$tn.2 { + BEGIN; + INSERT INTO x3 VALUES('b b b b b b b b b b b', 'b b b b b b b b b b b b b'); + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 SELECT * FROM x3; + INSERT INTO x3 VALUES('a b c', NULL); + INSERT INTO x3 VALUES('a x c', NULL); + COMMIT; + + SELECT * FROM x3 WHERE x3 MATCH 'a b'; + } {{a b c} {}} + + do_execsql_test 5.$tn.3 { DROP TABLE x3 } +} finish_test From 8c2e0f02ba3612e4838eed00ab7ab30eec321acc Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 31 Mar 2012 15:08:56 +0000 Subject: [PATCH 04/32] Modify selectColumnsFromExprList() to avoid ever incorrectly returning SQLITE_NOMEM. FossilOrigin-Name: e7cb6b73ac079d0751b3f9429d0f6a35ca8ec853 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 14 +++++++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 94e4cca145..8360172a45 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sICU\stokenizer\sso\sthat\sit\sdoes\snot\sattempt\sto\scall\sstrlen(NULL). -D 2012-03-31T11:58:23.752 +C Modify\sselectColumnsFromExprList()\sto\savoid\sever\sincorrectly\sreturning\sSQLITE_NOMEM. +D 2012-03-31T15:08:56.437 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -181,7 +181,7 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c f6f141cb1ea13f1e6564d3e162700e4937baa2a1 +F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 F src/shell.c abf18d6ee54f2631860a98fdd7ab1327f470db67 F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 @@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P c9342ca58105499a5eb61c3e6d016559b6072c95 -R e0716dc6380f52d6136a7e11cf5bb377 +P 04298f1ac42c40cb2a48092b415acf96a08954b7 +R 0f878dd95f65af523296a3016003b93f U dan -Z be3c953a1198ae2a4c78c4ed2dd05529 +Z 97900e673e834268c29dd651e4b74076 diff --git a/manifest.uuid b/manifest.uuid index de3255bc98..bd4af99639 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -04298f1ac42c40cb2a48092b415acf96a08954b7 \ No newline at end of file +e7cb6b73ac079d0751b3f9429d0f6a35ca8ec853 \ No newline at end of file diff --git a/src/select.c b/src/select.c index c225013672..b44220ebcf 100644 --- a/src/select.c +++ b/src/select.c @@ -1258,9 +1258,17 @@ static int selectColumnsFromExprList( char *zName; /* Column name */ int nName; /* Size of name in zName[] */ - *pnCol = nCol = pEList ? pEList->nExpr : 0; - aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); - if( aCol==0 ) return SQLITE_NOMEM; + if( pEList ){ + nCol = pEList->nExpr; + aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); + testcase( aCol==0 ); + }else{ + nCol = 0; + aCol = 0; + } + *pnCol = nCol; + *paCol = aCol; + for(i=0, pCol=aCol; i Date: Sat, 31 Mar 2012 17:17:26 +0000 Subject: [PATCH 05/32] Do not abort pending queries on a RELEASE of a nested SAVEPOINT. This is a candidate fix for ticket [27ca74af3c083f787]. FossilOrigin-Name: 79a4a3a84f0b367d54da5e69e64ffca474264717 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 8360172a45..9fe3bcb49c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sselectColumnsFromExprList()\sto\savoid\sever\sincorrectly\sreturning\sSQLITE_NOMEM. -D 2012-03-31T15:08:56.437 +C Do\snot\sabort\spending\squeries\son\sa\sRELEASE\sof\sa\snested\sSAVEPOINT.\nThis\sis\sa\scandidate\sfix\sfor\sticket\s[27ca74af3c083f787]. +D 2012-03-31T17:17:26.610 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -241,7 +241,7 @@ F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3 F src/vacuum.c bfd53f9bd20a8fdb70b0fa8e77182b866875c0d8 -F src/vdbe.c 8913926230bfc9d183fcd44e3d023c6d393b6548 +F src/vdbe.c e1d26b98288889c22f00cf4851ec351ee67ad8b9 F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82 F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91 @@ -999,7 +999,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 04298f1ac42c40cb2a48092b415acf96a08954b7 -R 0f878dd95f65af523296a3016003b93f -U dan -Z 97900e673e834268c29dd651e4b74076 +P e7cb6b73ac079d0751b3f9429d0f6a35ca8ec853 +R f0ffd709c4ab4135fdb232e59d421d85 +U drh +Z 3d7ccacc940dee0121ee183657c9b6bd diff --git a/manifest.uuid b/manifest.uuid index bd4af99639..f764472fbc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e7cb6b73ac079d0751b3f9429d0f6a35ca8ec853 \ No newline at end of file +79a4a3a84f0b367d54da5e69e64ffca474264717 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 9daa9cbff6..fa5180c9a4 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2734,8 +2734,10 @@ case OP_Savepoint: { rc = p->rc; }else{ iSavepoint = db->nSavepoint - iSavepoint - 1; - for(ii=0; iinDb; ii++){ - sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); + if( p1==SAVEPOINT_ROLLBACK ){ + for(ii=0; iinDb; ii++){ + sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); + } } for(ii=0; iinDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); From e77593fc5089e69f51e130d0a0436dd96f5148dd Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 31 Mar 2012 17:50:12 +0000 Subject: [PATCH 06/32] Test cases for RELEASE and ROLLBACK TO of a nested savepoint while queries are pending. FossilOrigin-Name: d2bf0efa7da59448a62f5be795403be4e5b7fb7f --- manifest | 11 ++--- manifest.uuid | 2 +- test/savepoint7.test | 96 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 test/savepoint7.test diff --git a/manifest b/manifest index 9fe3bcb49c..f35d43372f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sabort\spending\squeries\son\sa\sRELEASE\sof\sa\snested\sSAVEPOINT.\nThis\sis\sa\scandidate\sfix\sfor\sticket\s[27ca74af3c083f787]. -D 2012-03-31T17:17:26.610 +C Test\scases\sfor\sRELEASE\sand\sROLLBACK\sTO\sof\sa\snested\ssavepoint\swhile\squeries\nare\spending. +D 2012-03-31T17:50:12.845 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -669,6 +669,7 @@ F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 +F test/savepoint7.test fbf319a7b2dda089ec5be30a424a0e95f121d423 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38 @@ -999,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P e7cb6b73ac079d0751b3f9429d0f6a35ca8ec853 -R f0ffd709c4ab4135fdb232e59d421d85 +P 79a4a3a84f0b367d54da5e69e64ffca474264717 +R 5586a2611754af43053579b114e3a967 U drh -Z 3d7ccacc940dee0121ee183657c9b6bd +Z a414f1804c098ddade6c474c97e8199c diff --git a/manifest.uuid b/manifest.uuid index f764472fbc..e165259200 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79a4a3a84f0b367d54da5e69e64ffca474264717 \ No newline at end of file +d2bf0efa7da59448a62f5be795403be4e5b7fb7f \ No newline at end of file diff --git a/test/savepoint7.test b/test/savepoint7.test new file mode 100644 index 0000000000..bc99187d27 --- /dev/null +++ b/test/savepoint7.test @@ -0,0 +1,96 @@ +# 2012 March 31 +# +# 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. +# +#*********************************************************************** +# +# Focus on the interaction between RELEASE and ROLLBACK TO with +# pending query aborts. See ticket [27ca74af3c083f787a1c44b11fbb7c53bdbbcf1e]. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# The RELEASE of an inner savepoint should not effect pending queries. +# +do_test savepoint7-1.1 { + db eval { + CREATE TABLE t1(a,b,c); + CREATE TABLE t2(x,y,z); + INSERT INTO t1 VALUES(1,2,3); + INSERT INTO t1 VALUES(4,5,6); + INSERT INTO t1 VALUES(7,8,9); + SAVEPOINT x1; + } + db eval {SELECT * FROM t1} { + db eval { + SAVEPOINT x2; + INSERT INTO t2 VALUES($a,$b,$c); + RELEASE x2; + } + } + db eval {SELECT * FROM t2; RELEASE x1} +} {1 2 3 4 5 6 7 8 9} + +do_test savepoint7-1.2 { + db eval {DELETE FROM t2;} + db eval {SELECT * FROM t1} { + db eval { + SAVEPOINT x2; + INSERT INTO t2 VALUES($a,$b,$c); + RELEASE x2; + } + } + db eval {SELECT * FROM t2} +} {1 2 3 4 5 6 7 8 9} + +do_test savepoint7-1.3 { + db eval {DELETE FROM t2; BEGIN;} + db eval {SELECT * FROM t1} { + db eval { + SAVEPOINT x2; + INSERT INTO t2 VALUES($a,$b,$c); + RELEASE x2; + } + } + db eval {SELECT * FROM t2; ROLLBACK;} +} {1 2 3 4 5 6 7 8 9} + +# However, a ROLLBACK of an inner savepoint will abort all queries, including +# queries in outer contexts. +# +do_test savepoint7-2.1 { + db eval {DELETE FROM t2; SAVEPOINT x1;} + set rc [catch { + db eval {SELECT * FROM t1} { + db eval { + SAVEPOINT x2; + INSERT INTO t2 VALUES($a,$b,$c); + ROLLBACK TO x2; + } + } + } msg] + db eval {RELEASE x1} + list $rc $msg [db eval {SELECT * FROM t2}] +} {1 {callback requested query abort} {}} + +do_test savepoint7-2.2 { + db eval {DELETE FROM t2;} + set rc [catch { + db eval {SELECT * FROM t1} { + db eval { + SAVEPOINT x2; + INSERT INTO t2 VALUES($a,$b,$c); + ROLLBACK TO x2; + } + } + } msg] + list $rc $msg [db eval {SELECT * FROM t2}] +} {1 {callback requested query abort} {}} + +finish_test From a477a8670fd33953b3d1af916c57819559bd851f Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 31 Mar 2012 19:12:23 +0000 Subject: [PATCH 07/32] Fix a compiler warning by removing a redundant variable. FossilOrigin-Name: af602d87736b52802a4e760ffeeaa28112b99d9a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/insert.c | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index f35d43372f..e874247636 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scases\sfor\sRELEASE\sand\sROLLBACK\sTO\sof\sa\snested\ssavepoint\swhile\squeries\nare\spending. -D 2012-03-31T17:50:12.845 +C Fix\sa\scompiler\swarning\sby\sremoving\sa\sredundant\svariable. +D 2012-03-31T19:12:23.626 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -143,7 +143,7 @@ F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 93eb9542ae1376d9317a7c8335d7e379f010aa76 +F src/insert.c 0bbffe75c254c62a5686ab5e7f88e29235e16174 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 79a4a3a84f0b367d54da5e69e64ffca474264717 -R 5586a2611754af43053579b114e3a967 +P d2bf0efa7da59448a62f5be795403be4e5b7fb7f +R eb9cf6d41e33e7a95085e4fba3205ff0 U drh -Z a414f1804c098ddade6c474c97e8199c +Z 4e3dd4b5d13ad4c124b7a657b2e6b48c diff --git a/manifest.uuid b/manifest.uuid index e165259200..bb3edf477e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2bf0efa7da59448a62f5be795403be4e5b7fb7f \ No newline at end of file +af602d87736b52802a4e760ffeeaa28112b99d9a \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index ccf7ed0482..a589c8aef6 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1218,7 +1218,6 @@ void sqlite3GenerateConstraintChecks( #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; - int i; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; inExpr; i++){ From 3b06a2a0564a74c251f1d2505869f4c09bbf6488 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 2 Apr 2012 17:18:23 +0000 Subject: [PATCH 08/32] Add #ifdefs to allow a test build to succeed even if SQLITE_ENABLE_FTS3 is not defined. FossilOrigin-Name: fb121980e48af368353431fd04924e414b65c852 --- ext/fts3/fts3_test.c | 4 +++- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c index 0fe63c1c75..2244c9f736 100644 --- a/ext/fts3/fts3_test.c +++ b/ext/fts3/fts3_test.c @@ -22,7 +22,8 @@ #include #include -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) +#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) /* Required so that the "ifdef SQLITE_ENABLE_FTS3" below works */ #include "fts3Int.h" @@ -530,4 +531,5 @@ int Sqlitetestfts3_Init(Tcl_Interp *interp){ ); return TCL_OK; } +#endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */ #endif /* ifdef SQLITE_TEST */ diff --git a/manifest b/manifest index e874247636..d8e545b9dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompiler\swarning\sby\sremoving\sa\sredundant\svariable. -D 2012-03-31T19:12:23.626 +C Add\s#ifdefs\sto\sallow\sa\stest\sbuild\sto\ssucceed\seven\sif\sSQLITE_ENABLE_FTS3\sis\nnot\sdefined. +D 2012-04-02T17:18:23.248 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -74,7 +74,7 @@ F ext/fts3/fts3_icu.c 62ec177c55f6a5c6e994dd3e5fd3194b4045c347 F ext/fts3/fts3_porter.c a465b49fcb8249a755792f87516eff182efa42b3 F ext/fts3/fts3_snippet.c 51a3a34c217e24678a133782c1dfb6f2f70fe559 F ext/fts3/fts3_term.c 41e82ad335213d1c24356cf310dca1d3c13e7366 -F ext/fts3/fts3_test.c f3ef8ae1b802383c4d24fd70774cb87d52841d5f +F ext/fts3/fts3_test.c f153a121c763993e3d94cc99c012ee68d13231ae F ext/fts3/fts3_tokenizer.c 3da7254a9881f7e270ab28e2004e0d22b3212bce F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P d2bf0efa7da59448a62f5be795403be4e5b7fb7f -R eb9cf6d41e33e7a95085e4fba3205ff0 +P af602d87736b52802a4e760ffeeaa28112b99d9a +R 1de8fb5482810a4710e15863a31ff0ee U drh -Z 4e3dd4b5d13ad4c124b7a657b2e6b48c +Z 057914300e7aa29e2f4f5068087794b4 diff --git a/manifest.uuid b/manifest.uuid index bb3edf477e..a74c90f45f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -af602d87736b52802a4e760ffeeaa28112b99d9a \ No newline at end of file +fb121980e48af368353431fd04924e414b65c852 \ No newline at end of file From f439fbdab56a0db179c15e224e346136ff8cacd3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 2 Apr 2012 21:35:42 +0000 Subject: [PATCH 09/32] The SQLITE_RTREE_INT_ONLY compile-time option causes the RTree extension to use only integer math and store only integer coordinates. FossilOrigin-Name: 02b7640f5118e0a635b68f65765191bb3171b7bd --- ext/rtree/rtree.c | 246 +++++++++++++++++++++++---------------- ext/rtree/rtree1.test | 88 ++++++++------ ext/rtree/rtree4.test | 43 ++++--- ext/rtree/rtree5.test | 8 +- ext/rtree/rtree6.test | 2 +- ext/rtree/rtree7.test | 28 +++-- ext/rtree/rtree9.test | 1 + ext/rtree/rtreeB.test | 37 ++++-- ext/rtree/sqlite3rtree.h | 6 +- manifest | 32 ++--- manifest.uuid | 2 +- src/test_config.c | 6 + src/test_rtree.c | 10 +- 13 files changed, 313 insertions(+), 196 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index ce76e61f08..d6cdde9fc4 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -182,6 +182,19 @@ struct Rtree { #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 +/* +** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will +** only deal with integer coordinates. No floating point operations +** will be done. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ + typedef int RtreeValue; /* Low accuracy coordinate */ +#else + typedef double RtreeDValue; /* High accuracy coordinate */ + typedef float RtreeValue; /* Low accuracy coordinate */ +#endif + /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: @@ -217,20 +230,25 @@ struct RtreeCursor { }; union RtreeCoord { - float f; + RtreeValue f; int i; }; /* ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord -** formatted as a double. This macro assumes that local variable pRtree points -** to the Rtree structure associated with the RtreeCoord. +** formatted as a RtreeDValue (double or int64). This macro assumes that local +** variable pRtree points to the Rtree structure associated with the +** RtreeCoord. */ -#define DCOORD(coord) ( \ - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ - ((double)coord.f) : \ - ((double)coord.i) \ -) +#ifdef SQLITE_RTREE_INT_ONLY +# define DCOORD(coord) ((RtreeDValue)coord.i) +#else +# define DCOORD(coord) ( \ + (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ + ((double)coord.f) : \ + ((double)coord.i) \ + ) +#endif /* ** A search constraint. @@ -238,8 +256,8 @@ union RtreeCoord { struct RtreeConstraint { int iCoord; /* Index of constrained coordinate */ int op; /* Constraining operation */ - double rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + RtreeDValue rValue; /* Constraint value. */ + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ }; @@ -287,10 +305,10 @@ struct RtreeCell { */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); void *pContext; int nParam; - double aParam[1]; + RtreeDValue aParam[1]; }; /* @@ -302,7 +320,7 @@ struct RtreeMatchArg { ** the geometry callback function). */ struct RtreeGeomCallback { - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); void *pContext; }; @@ -868,7 +886,7 @@ static int testRtreeGeom( int *pbRes /* OUT: Test result */ ){ int i; - double aCoord[RTREE_MAX_DIMENSIONS*2]; + RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; int nCoord = pRtree->nDim*2; assert( pConstraint->op==RTREE_MATCH ); @@ -898,8 +916,8 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; bRes==0 && iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); - double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); + RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); + RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -951,7 +969,7 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double coord = DCOORD(cell.aCoord[p->iCoord]); + RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); int res; assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -1149,9 +1167,12 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ }else{ RtreeCoord c; nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); - }else{ + }else +#endif + { assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } @@ -1198,7 +1219,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<(int)sizeof(RtreeMatchArg) - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 ){ return SQLITE_ERROR; } @@ -1212,7 +1233,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) + || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) ){ sqlite3_free(pGeom); return SQLITE_ERROR; @@ -1284,7 +1305,11 @@ static int rtreeFilter( break; } }else{ +#ifdef SQLITE_RTREE_INT_ONLY + p->rValue = sqlite3_value_int64(argv[ii]); +#else p->rValue = sqlite3_value_double(argv[ii]); +#endif } } } @@ -1418,11 +1443,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ /* ** Return the N-dimensional volumn of the cell stored in *p. */ -static float cellArea(Rtree *pRtree, RtreeCell *p){ - float area = 1.0; +static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ + RtreeDValue area = (RtreeDValue)1; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); + area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); } return area; } @@ -1431,11 +1456,11 @@ static float cellArea(Rtree *pRtree, RtreeCell *p){ ** Return the margin length of cell p. The margin length is the sum ** of the objects size in each dimension. */ -static float cellMargin(Rtree *pRtree, RtreeCell *p){ - float margin = 0.0; +static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ + RtreeDValue margin = (RtreeDValue)0; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); + margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); } return margin; } @@ -1480,8 +1505,8 @@ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ /* ** Return the amount cell p would grow by if it were unioned with pCell. */ -static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ - float area; +static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ + RtreeDValue area; RtreeCell cell; memcpy(&cell, p, sizeof(RtreeCell)); area = cellArea(pRtree, &cell); @@ -1490,7 +1515,7 @@ static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ } #if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT -static float cellOverlap( +static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, RtreeCell *aCell, @@ -1498,7 +1523,7 @@ static float cellOverlap( int iExclude ){ int ii; - float overlap = 0.0; + RtreeDValue overlap = 0.0; for(ii=0; iinDim*2); jj+=2){ - double x1; - double x2; + RtreeDValue x1, x2; x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); @@ -1520,7 +1544,7 @@ static float cellOverlap( o = 0.0; break; }else{ - o = o * (float)(x2-x1); + o = o * (x2-x1); } } overlap += o; @@ -1531,7 +1555,7 @@ static float cellOverlap( #endif #if VARIANT_RSTARTREE_CHOOSESUBTREE -static float cellOverlapEnlargement( +static RtreeDValue cellOverlapEnlargement( Rtree *pRtree, RtreeCell *p, RtreeCell *pInsert, @@ -1539,12 +1563,11 @@ static float cellOverlapEnlargement( int nCell, int iExclude ){ - double before; - double after; + RtreeDValue before, after; before = cellOverlap(pRtree, p, aCell, nCell, iExclude); cellUnion(pRtree, p, pInsert); after = cellOverlap(pRtree, p, aCell, nCell, iExclude); - return (float)(after-before); + return (after-before); } #endif @@ -1568,11 +1591,11 @@ static int ChooseLeaf( int iCell; sqlite3_int64 iBest = 0; - float fMinGrowth = 0.0; - float fMinArea = 0.0; + RtreeDValue fMinGrowth = 0.0; + RtreeDValue fMinArea = 0.0; #if VARIANT_RSTARTREE_CHOOSESUBTREE - float fMinOverlap = 0.0; - float overlap; + RtreeDValue fMinOverlap = 0.0; + RtreeDValue overlap; #endif int nCell = NCELL(pNode); @@ -1603,8 +1626,8 @@ static int ChooseLeaf( */ for(iCell=0; iCellnDim; i++){ - float x1 = DCOORD(aCell[0].aCoord[i*2]); - float x2 = DCOORD(aCell[0].aCoord[i*2+1]); - float x3 = x1; - float x4 = x2; + RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); + RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); + RtreeDValue x3 = x1; + RtreeDValue x4 = x2; int jj; int iCellLeft = 0; int iCellRight = 0; for(jj=1; jjx4 ) x4 = right; @@ -1765,7 +1788,7 @@ static void LinearPickSeeds( } if( x4!=x1 ){ - float normalwidth = (x3 - x2) / (x4 - x1); + RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); if( normalwidth>maxNormalInnerWidth ){ iLeftSeed = iCellLeft; iRightSeed = iCellRight; @@ -1794,13 +1817,13 @@ static RtreeCell *QuadraticPickNext( #define FABS(a) ((a)<0.0?-1.0*(a):(a)) int iSelect = -1; - float fDiff; + RtreeDValue fDiff; int ii; for(ii=0; iifDiff ){ fDiff = diff; iSelect = ii; @@ -1827,13 +1850,13 @@ static void QuadraticPickSeeds( int iLeftSeed = 0; int iRightSeed = 1; - float fWaste = 0.0; + RtreeDValue fWaste = 0.0; for(ii=0; iifWaste ){ iLeftSeed = ii; @@ -1868,7 +1891,7 @@ static void QuadraticPickSeeds( static void SortByDistance( int *aIdx, int nIdx, - float *aDistance, + RtreeDValue *aDistance, int *aSpare ){ if( nIdx>1 ){ @@ -1894,8 +1917,8 @@ static void SortByDistance( aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ - float fLeft = aDistance[aLeft[iLeft]]; - float fRight = aDistance[aRight[iRight]]; + RtreeDValue fLeft = aDistance[aLeft[iLeft]]; + RtreeDValue fRight = aDistance[aRight[iRight]]; if( fLeftnDim+1)*(sizeof(int*)+nCell*sizeof(int)); @@ -2027,9 +2050,9 @@ static int splitNodeStartree( } for(ii=0; iinDim; ii++){ - float margin = 0.0; - float fBestOverlap = 0.0; - float fBestArea = 0.0; + RtreeDValue margin = 0.0; + RtreeDValue fBestOverlap = 0.0; + RtreeDValue fBestArea = 0.0; int iBestLeft = 0; int nLeft; @@ -2041,8 +2064,8 @@ static int splitNodeStartree( RtreeCell left; RtreeCell right; int kk; - float overlap; - float area; + RtreeDValue overlap; + RtreeDValue area; memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); @@ -2125,7 +2148,7 @@ static int splitNodeGuttman( for(i=nCell-2; i>0; i--){ RtreeCell *pNext; pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); - float diff = + RtreeDValue diff = cellGrowth(pRtree, pBboxLeft, pNext) - cellGrowth(pRtree, pBboxRight, pNext) ; @@ -2458,32 +2481,34 @@ static int Reinsert( int *aOrder; int *aSpare; RtreeCell *aCell; - float *aDistance; + RtreeDValue *aDistance; int nCell; - float aCenterCoord[RTREE_MAX_DIMENSIONS]; + RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS]; int iDim; int ii; int rc = SQLITE_OK; + int n; - memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS); + memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS); nCell = NCELL(pNode)+1; + n = (nCell+1)&(~1); /* Allocate the buffers used by this operation. The allocation is ** relinquished before this function returns. */ - aCell = (RtreeCell *)sqlite3_malloc(nCell * ( - sizeof(RtreeCell) + /* aCell array */ - sizeof(int) + /* aOrder array */ - sizeof(int) + /* aSpare array */ - sizeof(float) /* aDistance array */ + aCell = (RtreeCell *)sqlite3_malloc(n * ( + sizeof(RtreeCell) + /* aCell array */ + sizeof(int) + /* aOrder array */ + sizeof(int) + /* aSpare array */ + sizeof(RtreeDValue) /* aDistance array */ )); if( !aCell ){ return SQLITE_NOMEM; } - aOrder = (int *)&aCell[nCell]; - aSpare = (int *)&aOrder[nCell]; - aDistance = (float *)&aSpare[nCell]; + aOrder = (int *)&aCell[n]; + aSpare = (int *)&aOrder[n]; + aDistance = (RtreeDValue *)&aSpare[n]; for(ii=0; iinDim; iDim++){ - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]); - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); } } for(iDim=0; iDimnDim; iDim++){ - aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0)); + aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); } for(ii=0; iinDim; iDim++){ - float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) - - DCOORD(aCell[ii].aCoord[iDim*2])); + RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - + DCOORD(aCell[ii].aCoord[iDim*2])); aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); } } @@ -2747,16 +2772,19 @@ static int rtreeUpdate( /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ assert( nData==(pRtree->nDim*2 + 3) ); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]); - cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]); + cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]); + cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ rc = SQLITE_CONSTRAINT; goto constraint; } } - }else{ + }else +#endif + { for(ii=0; ii<(pRtree->nDim*2); ii+=2){ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); @@ -3154,7 +3182,13 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); nCell = (int)strlen(zCell); for(jj=0; jjpContext = pGeomCtx->pContext; pBlob->nParam = nArg; for(i=0; iaParam[i] = sqlite3_value_int64(aArg[i]); +#else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); +#endif } sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); } @@ -3253,7 +3295,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), void *pContext ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index 583b028507..e3c7d68e82 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -104,6 +104,18 @@ for {set nCol 1} {$nCol<[llength $cols]} {incr nCol} { catchsql { DROP TABLE t1 } } +# Like execsql except display output as integer where that can be +# done without loss of information. +# +proc execsql_intout {sql} { + set out {} + foreach term [execsql $sql] { + regsub {\.0$} $term {} term + lappend out $term + } + return $out +} + # Test that it is possible to open an existing database that contains # r-tree tables. # @@ -117,8 +129,8 @@ do_test rtree-1.4.1 { do_test rtree-1.4.2 { db close sqlite3 db test.db - execsql { SELECT * FROM t1 ORDER BY ii } -} {1 5.0 10.0 2 15.0 20.0} + execsql_intout { SELECT * FROM t1 ORDER BY ii } +} {1 5 10 2 15 20} do_test rtree-1.4.3 { execsql { DROP TABLE t1 } } {} @@ -127,12 +139,12 @@ do_test rtree-1.4.3 { # column names. # do_test rtree-1.5.1 { - execsql { + execsql_intout { CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim"); INSERT INTO t1 VALUES(1, 2, 3); SELECT "the key", "x dim.", "x2'dim" FROM t1; } -} {1 2.0 3.0} +} {1 2 3} do_test rtree-1.5.1 { execsql { DROP TABLE t1 } } {} @@ -161,8 +173,8 @@ do_test rtree-2.1.1 { do_test rtree-2.1.2 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } - execsql { SELECT * FROM t1 } -} {1 1.0 3.0 2.0 4.0} + execsql_intout { SELECT * FROM t1 } +} {1 1 3 2 4} do_test rtree-2.1.3 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } execsql { SELECT rowid FROM t1 ORDER BY rowid } @@ -201,17 +213,17 @@ do_test rtree-3.1.1 { } } {} do_test rtree-3.1.2 { - execsql { + execsql_intout { INSERT INTO t1 VALUES(5, 1, 3, 2, 4); SELECT * FROM t1; } -} {5 1.0 3.0 2.0 4.0} +} {5 1 3 2 4} do_test rtree-3.1.3 { - execsql { + execsql_intout { INSERT INTO t1 VALUES(6, 2, 6, 4, 8); SELECT * FROM t1; } -} {5 1.0 3.0 2.0 4.0 6 2.0 6.0 4.0 8.0} +} {5 1 3 2 4 6 2 6 4 8} # Test the constraint on the coordinates (c[i]<=c[i+1] where (i%2==0)): do_test rtree-3.2.1 { @@ -228,25 +240,25 @@ do_test rtree-5.1.1 { execsql { CREATE VIRTUAL TABLE t2 USING rtree(ii, x1, x2) } } {} do_test rtree-5.1.2 { - execsql { + execsql_intout { INSERT INTO t2 VALUES(1, 10, 20); INSERT INTO t2 VALUES(2, 30, 40); INSERT INTO t2 VALUES(3, 50, 60); SELECT * FROM t2 ORDER BY ii; } -} {1 10.0 20.0 2 30.0 40.0 3 50.0 60.0} +} {1 10 20 2 30 40 3 50 60} do_test rtree-5.1.3 { - execsql { + execsql_intout { DELETE FROM t2 WHERE ii=2; SELECT * FROM t2 ORDER BY ii; } -} {1 10.0 20.0 3 50.0 60.0} +} {1 10 20 3 50 60} do_test rtree-5.1.4 { - execsql { + execsql_intout { DELETE FROM t2 WHERE ii=1; SELECT * FROM t2 ORDER BY ii; } -} {3 50.0 60.0} +} {3 50 60} do_test rtree-5.1.5 { execsql { DELETE FROM t2 WHERE ii=3; @@ -264,16 +276,16 @@ do_test rtree-6.1.1 { execsql { CREATE VIRTUAL TABLE t3 USING rtree(ii, x1, x2, y1, y2) } } {} do_test rtree-6.1.2 { - execsql { + execsql_intout { INSERT INTO t3 VALUES(1, 2, 3, 4, 5); UPDATE t3 SET x2=5; SELECT * FROM t3; } -} {1 2.0 5.0 4.0 5.0} +} {1 2 5 4 5} do_test rtree-6.1.3 { execsql { UPDATE t3 SET ii = 2 } - execsql { SELECT * FROM t3 } -} {2 2.0 5.0 4.0 5.0} + execsql_intout { SELECT * FROM t3 } +} {2 2 5 4 5} #---------------------------------------------------------------------------- # Test cases rtree-7.* test rename operations. @@ -286,29 +298,29 @@ do_test rtree-7.1.1 { } {} do_test rtree-7.1.2 { execsql { ALTER TABLE t4 RENAME TO t5 } - execsql { SELECT * FROM t5 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t5 } +} {1 2 3 4 5 6 7} do_test rtree-7.1.3 { db close sqlite3 db test.db - execsql { SELECT * FROM t5 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t5 } +} {1 2 3 4 5 6 7} do_test rtree-7.1.4 { execsql { ALTER TABLE t5 RENAME TO 'raisara "one"'''} - execsql { SELECT * FROM "raisara ""one""'" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "raisara ""one""'" } +} {1 2 3 4 5 6 7} do_test rtree-7.1.5 { - execsql { SELECT * FROM 'raisara "one"''' } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM 'raisara "one"''' } +} {1 2 3 4 5 6 7} do_test rtree-7.1.6 { execsql { ALTER TABLE "raisara ""one""'" RENAME TO "abc 123" } - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.1.7 { db close sqlite3 db test.db - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} # An error midway through a rename operation. do_test rtree-7.2.1 { @@ -318,8 +330,8 @@ do_test rtree-7.2.1 { catchsql { ALTER TABLE "abc 123" RENAME TO t4 } } {1 {SQL logic error or missing database}} do_test rtree-7.2.2 { - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.2.3 { execsql { DROP TABLE t4_node; @@ -330,13 +342,13 @@ do_test rtree-7.2.3 { do_test rtree-7.2.4 { db close sqlite3 db test.db - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.2.5 { execsql { DROP TABLE t4_rowid } execsql { ALTER TABLE "abc 123" RENAME TO t4 } - execsql { SELECT * FROM t4 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t4 } +} {1 2 3 4 5 6 7} #---------------------------------------------------------------------------- diff --git a/ext/rtree/rtree4.test b/ext/rtree/rtree4.test index 708d335b06..a3872b0735 100644 --- a/ext/rtree/rtree4.test +++ b/ext/rtree/rtree4.test @@ -27,21 +27,38 @@ if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } -# Return a floating point number between -X and X. -# -proc rand {X} { - return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] -} - -# Return a positive floating point number less than or equal to X -# -proc randincr {X} { - while 1 { - set r [expr {int(rand()*$X*32.0)/32.0}] - if {$r>0.0} {return $r} +ifcapable !rtree_int_only { + # Return a floating point number between -X and X. + # + proc rand {X} { + return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] + } + + # Return a positive floating point number less than or equal to X + # + proc randincr {X} { + while 1 { + set r [expr {int(rand()*$X*32.0)/32.0}] + if {$r>0.0} {return $r} + } + } +} else { + # For rtree_int_only, return an number between -X and X. + # + proc rand {X} { + return [expr {int((rand()-0.5)*2*$X)}] + } + + # Return a positive integer less than or equal to X + # + proc randincr {X} { + while 1 { + set r [expr {int(rand()*$X)+1}] + if {$r>0} {return $r} + } } } - + # Scramble the $inlist into a random order. # proc scramble {inlist} { diff --git a/ext/rtree/rtree5.test b/ext/rtree/rtree5.test index ea2946f918..8990772356 100644 --- a/ext/rtree/rtree5.test +++ b/ext/rtree/rtree5.test @@ -49,9 +49,11 @@ do_test rtree5-1.6 { do_test rtree5-1.7 { execsql { SELECT count(*) FROM t1 WHERE x1==5 } } {1} -do_test rtree5-1.8 { - execsql { SELECT count(*) FROM t1 WHERE x1==5.2 } -} {0} +ifcapable !rtree_int_only { + do_test rtree5-1.8 { + execsql { SELECT count(*) FROM t1 WHERE x1==5.2 } + } {0} +} do_test rtree5-1.9 { execsql { SELECT count(*) FROM t1 WHERE x1==5.0 } } {1} diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index ba0e53c994..9d57016231 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -16,7 +16,7 @@ if {![info exists testdir]} { } source $testdir/tester.tcl -ifcapable !rtree { +ifcapable !rtree || rtree_int_only { finish_test return } diff --git a/ext/rtree/rtree7.test b/ext/rtree/rtree7.test index 31dae0cd8a..4eee4c219a 100644 --- a/ext/rtree/rtree7.test +++ b/ext/rtree/rtree7.test @@ -24,6 +24,18 @@ ifcapable !rtree||!vacuum { return } +# Like execsql except display output as integer where that can be +# done without loss of information. +# +proc execsql_intout {sql} { + set out {} + foreach term [execsql $sql] { + regsub {\.0$} $term {} term + lappend out $term + } + return $out +} + do_test rtree7-1.1 { execsql { PRAGMA page_size = 1024; @@ -32,27 +44,27 @@ do_test rtree7-1.1 { } } {} do_test rtree7-1.2 { - execsql { SELECT * FROM rt } -} {1 1.0 2.0 3.0 4.0} + execsql_intout { SELECT * FROM rt } +} {1 1 2 3 4} do_test rtree7-1.3 { - execsql { + execsql_intout { PRAGMA page_size = 2048; VACUUM; SELECT * FROM rt; } -} {1 1.0 2.0 3.0 4.0} +} {1 1 2 3 4} do_test rtree7-1.4 { for {set i 2} {$i <= 51} {incr i} { execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) } } - execsql { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } -} {51.0 102.0 153.0 204.0} + execsql_intout { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } +} {51 102 153 204} do_test rtree7-1.5 { - execsql { + execsql_intout { PRAGMA page_size = 512; VACUUM; SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } -} {51.0 102.0 153.0 204.0} +} {51 102 153 204} finish_test diff --git a/ext/rtree/rtree9.test b/ext/rtree/rtree9.test index ddee277ef5..6479516bed 100644 --- a/ext/rtree/rtree9.test +++ b/ext/rtree/rtree9.test @@ -17,6 +17,7 @@ if {![info exists testdir]} { } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } +ifcapable rtree_int_only { finish_test; return } register_cube_geom db diff --git a/ext/rtree/rtreeB.test b/ext/rtree/rtreeB.test index 2756fceedb..7cb445cc4f 100644 --- a/ext/rtree/rtreeB.test +++ b/ext/rtree/rtreeB.test @@ -18,17 +18,30 @@ if {![info exists testdir]} { source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } -do_test rtreeB-1.1 { - db eval { - CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); - INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); - INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); - INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); - INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); - INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); - SELECT rtreenode(2, data) FROM t1_node; - } -} {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} - +ifcapable rtree_int_only { + do_test rtreeB-1.1-intonly { + db eval { + CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); + INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); + INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); + INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); + INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); + INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); + SELECT rtreenode(2, data) FROM t1_node; + } + } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}} +} else { + do_test rtreeB-1.1 { + db eval { + CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); + INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); + INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); + INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); + INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); + INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); + SELECT rtreenode(2, data) FROM t1_node; + } + } {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} +} finish_test diff --git a/ext/rtree/sqlite3rtree.h b/ext/rtree/sqlite3rtree.h index cffb300092..c849091f29 100644 --- a/ext/rtree/sqlite3rtree.h +++ b/ext/rtree/sqlite3rtree.h @@ -31,7 +31,11 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif void *pContext ); diff --git a/manifest b/manifest index d8e545b9dc..bebaba541e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\s#ifdefs\sto\sallow\sa\stest\sbuild\sto\ssucceed\seven\sif\sSQLITE_ENABLE_FTS3\sis\nnot\sdefined. -D 2012-04-02T17:18:23.248 +C The\sSQLITE_RTREE_INT_ONLY\scompile-time\soption\scauses\sthe\sRTree\sextension\s\nto\suse\sonly\sinteger\smath\sand\sstore\sonly\sinteger\scoordinates. +D 2012-04-02T21:35:42.939 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -86,22 +86,22 @@ F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 F ext/icu/icu.c eb9ae1d79046bd7871aa97ee6da51eb770134b5a F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 4c1878818fc50efe5c2c7b8809d5cd0d88c7d396 +F ext/rtree/rtree.c 73502e5336162fdc8f5d1c4bdd4ec6b1299c2f2a F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e -F ext/rtree/rtree1.test 28e1b8da4da98093ce3210187434dd760a8d89d8 +F ext/rtree/rtree1.test e474a2b5eff231496dbd073fe67e5fbaf7f444c9 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc -F ext/rtree/rtree4.test 0061e6f464fd3dc6a79f82454c5a1c3dadbe42af -F ext/rtree/rtree5.test ce3d7ccae2cfd9d2e1052b462424964c9bdcda12 -F ext/rtree/rtree6.test 0b380bd9af93f3bc496eef42502a336f58949c1b -F ext/rtree/rtree7.test bcb647b42920b3b5d025846689147778485cc318 +F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0 +F ext/rtree/rtree5.test 9a229678a00f40e6aedb40cb3a07ec5444af892c +F ext/rtree/rtree6.test f67ed7d362ab9a0d13dc2b3d34939e69e0829542 +F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree8.test 9772e16da71e17e02bdebf0a5188590f289ab37d -F ext/rtree/rtree9.test df9843d1a9195249c8d3b4ea6aedda2d5c73e9c2 +F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf -F ext/rtree/rtreeB.test b1916a9cecb86b02529c4cc5a546e8d6e7ff10da +F ext/rtree/rtreeB.test 983e567b49b5dca165940f66b87e161aa30e82b2 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea -F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 +F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -203,7 +203,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2 -F src/test_config.c a036a69b550ebc477ab9ca2b37269201f888436e +F src/test_config.c 0de329e736eb4aa5845069bed630e5c72f012264 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd @@ -223,7 +223,7 @@ F src/test_osinst.c 7f790ac89c5a585d51b341274d9691c3391e0923 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c a545115f837da4ef32f6b5578f147b44cfb13fd7 F src/test_quota.h 9ffa1d3ad6d0a6a24e8670ea64b909c717ec3358 -F src/test_rtree.c 6d06306e29946dc36f528a3a2cdc3add794656f1 +F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f F src/test_stat.c d7035cfcc0ff1f93c000b621f36524318e004e11 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P af602d87736b52802a4e760ffeeaa28112b99d9a -R 1de8fb5482810a4710e15863a31ff0ee +P fb121980e48af368353431fd04924e414b65c852 +R 5f487522a2da2d1baf5cda41d792b333 U drh -Z 057914300e7aa29e2f4f5068087794b4 +Z f6050a33b89113e7c2cd85615563f7a3 diff --git a/manifest.uuid b/manifest.uuid index a74c90f45f..211e12f14c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb121980e48af368353431fd04924e414b65c852 \ No newline at end of file +02b7640f5118e0a635b68f65765191bb3171b7bd \ No newline at end of file diff --git a/src/test_config.c b/src/test_config.c index 18442a49e0..f096ebf236 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -420,6 +420,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double", Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_RTREE_INT_ONLY + Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY); #else diff --git a/src/test_rtree.c b/src/test_rtree.c index 9745b00541..d3c9e0cb3d 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -49,7 +49,11 @@ static void circle_del(void *p){ static int circle_geom( sqlite3_rtree_geometry *p, int nCoord, +#ifdef SQLITE_RTREE_INT_ONLY + sqlite3_int64 *aCoord, +#else double *aCoord, +#endif int *pRes ){ int i; /* Iterator variable */ @@ -188,8 +192,12 @@ static int gHere = 42; */ static int cube_geom( sqlite3_rtree_geometry *p, - int nCoord, + int nCoord, +#ifdef SQLITE_RTREE_INT_ONLY + sqlite3_int64 *aCoord, +#else double *aCoord, +#endif int *piRes ){ Cube *pCube = (Cube *)p->pUser; From 3aeea463978980ad95060ad201c3ac9462555637 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 3 Apr 2012 14:59:50 +0000 Subject: [PATCH 10/32] Enhance the "showdb" utility program with the "pgidx" option. Now requires linkage with the amalgamation. FossilOrigin-Name: 4b5737014c6f1638de9dc162463508ea7dfe333d --- manifest | 12 +-- manifest.uuid | 2 +- tool/showdb.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index bebaba541e..095f368fee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sSQLITE_RTREE_INT_ONLY\scompile-time\soption\scauses\sthe\sRTree\sextension\s\nto\suse\sonly\sinteger\smath\sand\sstore\sonly\sinteger\scoordinates. -D 2012-04-02T21:35:42.939 +C Enhance\sthe\s"showdb"\sutility\sprogram\swith\sthe\s"pgidx"\soption.\s\sNow\srequires\nlinkage\swith\sthe\samalgamation. +D 2012-04-03T14:59:50.844 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -982,7 +982,7 @@ F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3 F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836 F tool/shell4.test 35f9c3d452b4e76d5013c63e1fd07478a62f14ce F tool/shell5.test 0e987fb8d40638bb5c90163cb58cbe3e07dbed56 -F tool/showdb.c 43e913d954684c2f5007dcab46d1a1308852a0ad +F tool/showdb.c 9cdc45377f7512902232bdc18bd5119cc2512a1a F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02 F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P fb121980e48af368353431fd04924e414b65c852 -R 5f487522a2da2d1baf5cda41d792b333 +P 02b7640f5118e0a635b68f65765191bb3171b7bd +R 4634bc5c716828f15113d298489e79da U drh -Z f6050a33b89113e7c2cd85615563f7a3 +Z b9b2c57600f8181cc1cad22a91aba3cd diff --git a/manifest.uuid b/manifest.uuid index 211e12f14c..fb9d6b2b22 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02b7640f5118e0a635b68f65765191bb3171b7bd \ No newline at end of file +4b5737014c6f1638de9dc162463508ea7dfe333d \ No newline at end of file diff --git a/tool/showdb.c b/tool/showdb.c index 057abd32ba..a6e3060a14 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -9,6 +9,7 @@ #include #include #include +#include "sqlite3.h" static int pagesize = 1024; /* Size of a database page */ @@ -450,6 +451,222 @@ static void decode_trunk_page( } } +/* +** A short text comment on the use of each page. +*/ +static char **zPageUse; + +/* +** Add a comment on the use of a page. +*/ +static void page_usage_msg(int pgno, const char *zFormat, ...){ + va_list ap; + char *zMsg; + + va_start(ap, zFormat); + zMsg = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + if( pgno<=0 || pgno>mxPage ){ + printf("ERROR: page %d out of bounds. Range=1..%d. Msg: %s\n", + pgno, mxPage, zMsg); + sqlite3_free(zMsg); + return; + } + if( zPageUse[pgno]!=0 ){ + printf("ERROR: page %d used multiple times:\n", pgno); + printf("ERROR: previous: %s\n", zPageUse[pgno]); + printf("ERROR: current: %s\n", zPageUse[pgno]); + sqlite3_free(zPageUse[pgno]); + } + zPageUse[pgno] = zMsg; +} + +/* +** Find overflow pages of a cell and describe their usage. +*/ +static void page_usage_cell( + unsigned char cType, /* Page type */ + unsigned char *a, /* Cell content */ + int pgno, /* page containing the cell */ + int cellno /* Index of the cell on the page */ +){ + int i; + int nDesc = 0; + int n = 0; + i64 nPayload; + i64 rowid; + int nLocal; + i = 0; + if( cType<=5 ){ + a += 4; + n += 4; + } + if( cType!=5 ){ + i = decodeVarint(a, &nPayload); + a += i; + n += i; + nLocal = localPayload(nPayload, cType); + }else{ + nPayload = nLocal = 0; + } + if( cType==5 || cType==13 ){ + i = decodeVarint(a, &rowid); + a += i; + n += i; + } + if( nLocalmxPage ) return; + a = getContent((pgno-1)*pagesize, pagesize); + switch( a[hdr] ){ + case 2: zType = "interior node of index"; break; + case 5: zType = "interior node of table"; break; + case 10: zType = "leaf of index"; break; + case 13: zType = "leaf of table"; break; + } + if( parent ){ + page_usage_msg(pgno, "%s [%s], child %d of page %d", + zType, zName, idx, parent); + }else{ + page_usage_msg(pgno, "root %s [%s]", zType, zName); + } + nCell = a[hdr+3]*256 + a[hdr+4]; + if( a[hdr]==2 || a[hdr]==5 ){ + int cellstart = hdr+12; + unsigned int child; + for(i=0; i0 && pgno<=mxPage && (cnt++) Date: Tue, 3 Apr 2012 15:10:34 +0000 Subject: [PATCH 11/32] If the SELECT that finds all root pages in the showdb fails, then report an error. FossilOrigin-Name: 4b16141501655faa23e7d34ad05570ea929abb7c --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/showdb.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 095f368fee..518760ddd0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\s"showdb"\sutility\sprogram\swith\sthe\s"pgidx"\soption.\s\sNow\srequires\nlinkage\swith\sthe\samalgamation. -D 2012-04-03T14:59:50.844 +C If\sthe\sSELECT\sthat\sfinds\sall\sroot\spages\sin\sthe\sshowdb\sfails,\sthen\sreport\nan\serror. +D 2012-04-03T15:10:34.981 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -982,7 +982,7 @@ F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3 F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836 F tool/shell4.test 35f9c3d452b4e76d5013c63e1fd07478a62f14ce F tool/shell5.test 0e987fb8d40638bb5c90163cb58cbe3e07dbed56 -F tool/showdb.c 9cdc45377f7512902232bdc18bd5119cc2512a1a +F tool/showdb.c 2e28d8e499b016485672e9a7ac65dacc0d28ff69 F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02 F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 02b7640f5118e0a635b68f65765191bb3171b7bd -R 4634bc5c716828f15113d298489e79da +P 4b5737014c6f1638de9dc162463508ea7dfe333d +R 84ab6304cfe006dbe7cfc59187764161 U drh -Z b9b2c57600f8181cc1cad22a91aba3cd +Z d270e8613e5392cdea76e9c49f53ec67 diff --git a/manifest.uuid b/manifest.uuid index fb9d6b2b22..6315693599 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4b5737014c6f1638de9dc162463508ea7dfe333d \ No newline at end of file +4b16141501655faa23e7d34ad05570ea929abb7c \ No newline at end of file diff --git a/tool/showdb.c b/tool/showdb.c index a6e3060a14..d378d05d36 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -654,6 +654,8 @@ static void page_usage_report(const char *zDbName){ int pgno = sqlite3_column_int(pStmt, 2); page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1)); } + }else{ + printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db)); } sqlite3_finalize(pStmt); sqlite3_close(db); From 67d97343a3159bad7615b8c2a3eaf4e7028e6ef3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 3 Apr 2012 17:01:36 +0000 Subject: [PATCH 12/32] Rerun autoconf to update the configure script for version 3.7.12 FossilOrigin-Name: 6d73eb20e825f51143a1b59ad33f44e6448ef760 --- configure | 18 +++++++++--------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/configure b/configure index aa16558171..dfe7447dd0 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for sqlite 3.7.11. +# Generated by GNU Autoconf 2.62 for sqlite 3.7.12. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.7.11' -PACKAGE_STRING='sqlite 3.7.11' +PACKAGE_VERSION='3.7.12' +PACKAGE_STRING='sqlite 3.7.12' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. @@ -1485,7 +1485,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.7.11 to adapt to many kinds of systems. +\`configure' configures sqlite 3.7.12 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1550,7 +1550,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.7.11:";; + short | recursive ) echo "Configuration of sqlite 3.7.12:";; esac cat <<\_ACEOF @@ -1666,7 +1666,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.7.11 +sqlite configure 3.7.12 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1680,7 +1680,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.7.11, which was +It was created by sqlite $as_me 3.7.12, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ @@ -14032,7 +14032,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.7.11, which was +This file was extended by sqlite $as_me 3.7.12, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14085,7 +14085,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -sqlite config.status 3.7.11 +sqlite config.status 3.7.12 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/manifest b/manifest index 518760ddd0..f445e1cfca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sthe\sSELECT\sthat\sfinds\sall\sroot\spages\sin\sthe\sshowdb\sfails,\sthen\sreport\nan\serror. -D 2012-04-03T15:10:34.981 +C Rerun\sautoconf\sto\supdate\sthe\sconfigure\sscript\sfor\sversion\s3.7.12 +D 2012-04-03T17:01:36.071 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -23,7 +23,7 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 4ee31677412c454d0978a64872faf3ec36ff94ca x +F configure eb9e5e7f4c1601b5acf674a724e1a778481d2835 x F configure.ac 9ee886c21c095b3272137b1553ae416c8b8c8557 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 4b5737014c6f1638de9dc162463508ea7dfe333d -R 84ab6304cfe006dbe7cfc59187764161 +P 4b16141501655faa23e7d34ad05570ea929abb7c +R a3eb7ac55825b623c91bd4b43a16c073 U drh -Z d270e8613e5392cdea76e9c49f53ec67 +Z a16c1855861d082310638d4ebfce5b46 diff --git a/manifest.uuid b/manifest.uuid index 6315693599..30286e6026 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4b16141501655faa23e7d34ad05570ea929abb7c \ No newline at end of file +6d73eb20e825f51143a1b59ad33f44e6448ef760 \ No newline at end of file From 2aad3da6eaedf4fa72fe06ec1b2e4d1c964bf3e3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 3 Apr 2012 17:05:16 +0000 Subject: [PATCH 13/32] Fix a typo in the rtree6.test script that prevented it from running. FossilOrigin-Name: 221fe4a8ea5bea90031e459746ea71ff173e6f52 --- ext/rtree/rtree6.test | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index 9d57016231..92edc8d104 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -16,7 +16,7 @@ if {![info exists testdir]} { } source $testdir/tester.tcl -ifcapable !rtree || rtree_int_only { +ifcapable {!rtree || rtree_int_only} { finish_test return } diff --git a/manifest b/manifest index f445e1cfca..be9d261014 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rerun\sautoconf\sto\supdate\sthe\sconfigure\sscript\sfor\sversion\s3.7.12 -D 2012-04-03T17:01:36.071 +C Fix\sa\stypo\sin\sthe\srtree6.test\sscript\sthat\sprevented\sit\sfrom\srunning. +D 2012-04-03T17:05:16.797 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -93,7 +93,7 @@ F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0 F ext/rtree/rtree5.test 9a229678a00f40e6aedb40cb3a07ec5444af892c -F ext/rtree/rtree6.test f67ed7d362ab9a0d13dc2b3d34939e69e0829542 +F ext/rtree/rtree6.test 3ff9113b4a872fa935309e3511cd9b7cdb4d2472 F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree8.test 9772e16da71e17e02bdebf0a5188590f289ab37d F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 4b16141501655faa23e7d34ad05570ea929abb7c -R a3eb7ac55825b623c91bd4b43a16c073 +P 6d73eb20e825f51143a1b59ad33f44e6448ef760 +R 1bfa9697c3ee58e945b220e1f2e117e6 U drh -Z a16c1855861d082310638d4ebfce5b46 +Z 04df2a29417f5db40a26641a7a738bb8 diff --git a/manifest.uuid b/manifest.uuid index 30286e6026..286c3c4141 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6d73eb20e825f51143a1b59ad33f44e6448ef760 \ No newline at end of file +221fe4a8ea5bea90031e459746ea71ff173e6f52 \ No newline at end of file From 1235bb18159f55bde171a39fc85fe25158e49e0a Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 3 Apr 2012 17:43:28 +0000 Subject: [PATCH 14/32] Modify the integrity-check code to reduce the size of the large allocation from 4 bytes to 1 bit for each page in the database file. FossilOrigin-Name: fa3a498dfe9ed59c30da5eaa0d7cad167fd4e393 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 42 ++++++++++++++++++++++++++++++------------ src/btreeInt.h | 8 +++++++- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index be9d261014..9edb1496da 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\srtree6.test\sscript\sthat\sprevented\sit\sfrom\srunning. -D 2012-04-03T17:05:16.797 +C Modify\sthe\sintegrity-check\scode\sto\sreduce\sthe\ssize\sof\sthe\slarge\sallocation\sfrom\s4\sbytes\sto\s1\sbit\sfor\seach\spage\sin\sthe\sdatabase\sfile. +D 2012-04-03T17:43:28.322 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -126,9 +126,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 6be23a344d3301ae38e92fddb3a33b91c309fce4 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 02aeee1f6d425e11f7b9b2d9d461ac501645ed6f +F src/btree.c df800f10896bc2ddaa1125c532d6e7a7b9efc532 F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923 -F src/btreeInt.h 26d8ca625b141927fe6620c1d2cf58eaf494ca0c +F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e F src/build.c 987c6933ea170e443dc6a79d52f8d2506206b12b F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 6d73eb20e825f51143a1b59ad33f44e6448ef760 -R 1bfa9697c3ee58e945b220e1f2e117e6 -U drh -Z 04df2a29417f5db40a26641a7a738bb8 +P 221fe4a8ea5bea90031e459746ea71ff173e6f52 +R 32aad9893eefdebd852afcbce9893d62 +U dan +Z 24eef38a1ddea33d5b3c726c6b9516d2 diff --git a/manifest.uuid b/manifest.uuid index 286c3c4141..6ef0041f8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -221fe4a8ea5bea90031e459746ea71ff173e6f52 \ No newline at end of file +fa3a498dfe9ed59c30da5eaa0d7cad167fd4e393 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index d24c2be069..2876526925 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7554,6 +7554,25 @@ static void checkAppendMsg( #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK + +/* +** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that +** corresponds to page iPg is already set. +*/ +static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); +} + +/* +** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. +*/ +static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); +} + + /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. @@ -7568,11 +7587,12 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } - if( pCheck->anRef[iPage]==1 ){ + if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } - return (pCheck->anRef[iPage]++)>1; + setPageReferenced(pCheck, iPage); + return 0; } #ifndef SQLITE_OMIT_AUTOVACUUM @@ -7948,17 +7968,15 @@ char *sqlite3BtreeIntegrityCheck( sqlite3BtreeLeave(p); return 0; } - sCheck.anRef = sqlite3Malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); - if( !sCheck.anRef ){ + + sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); + if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } - for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nPage ){ - sCheck.anRef[i] = 1; - } + if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); sCheck.errMsg.useMalloc = 2; @@ -7983,18 +8001,18 @@ char *sqlite3BtreeIntegrityCheck( */ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM - if( sCheck.anRef[i]==0 ){ + if( getPageReferenced(&sCheck, i)==0 ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain ** references to pointer-map pages. */ - if( sCheck.anRef[i]==0 && + if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } - if( sCheck.anRef[i]!=0 && + if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } @@ -8015,7 +8033,7 @@ char *sqlite3BtreeIntegrityCheck( /* Clean up and report errors. */ sqlite3BtreeLeave(p); - sqlite3_free(sCheck.anRef); + sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ sqlite3StrAccumReset(&sCheck.errMsg); *pnErr = sCheck.nErr+1; diff --git a/src/btreeInt.h b/src/btreeInt.h index 841e2c6eab..0d21497966 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -631,12 +631,18 @@ struct BtCursor { /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. +** +** The aRef[] array is allocated so that there is 1 bit for each page in +** the database. As the integrity-check proceeds, for each page used in +** the database the corresponding bit is set. This allows integrity-check to +** detect pages that are used twice and orphaned pages (both of which +** indicate corruption). */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ - int *anRef; /* Number of times each page is referenced */ + u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ From 2bd2cfc2b5c5d69a9d68afeb7444f1f8d58c5393 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 3 Apr 2012 18:33:43 +0000 Subject: [PATCH 15/32] Modify capi3.test and capi3c.test so that they work with SQLITE_OMIT_AUTORESET builds. FossilOrigin-Name: 1d5e744cc645150ccaa7256663146fc7b8540bd5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/capi3.test | 6 ++++++ test/capi3c.test | 6 ++++++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9edb1496da..00bf39318a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\sintegrity-check\scode\sto\sreduce\sthe\ssize\sof\sthe\slarge\sallocation\sfrom\s4\sbytes\sto\s1\sbit\sfor\seach\spage\sin\sthe\sdatabase\sfile. -D 2012-04-03T17:43:28.322 +C Modify\scapi3.test\sand\scapi3c.test\sso\sthat\sthey\swork\swith\sSQLITE_OMIT_AUTORESET\sbuilds. +D 2012-04-03T18:33:43.337 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -316,9 +316,9 @@ F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test f64136b0893c293d0b910ed057b3b711249099a7 F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360 -F test/capi3.test 9c8b58b6a6aeb14e69bd8c8c7721b47d640464d1 +F test/capi3.test 8dedb0050610e9ff95cd9d487beb0ce5f33a31ee F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 -F test/capi3c.test 1b5424d2ac57b7b443b5de5b9a287642c02279b6 +F test/capi3c.test 01f197d73f4d4d66316483662f475cab7ab5bd60 F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1 F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 221fe4a8ea5bea90031e459746ea71ff173e6f52 -R 32aad9893eefdebd852afcbce9893d62 +P fa3a498dfe9ed59c30da5eaa0d7cad167fd4e393 +R 93f41d5cd0dd5634edd499aa7b12c353 U dan -Z 24eef38a1ddea33d5b3c726c6b9516d2 +Z 6ebde95baa77d452c6bdb9a26f49bf26 diff --git a/manifest.uuid b/manifest.uuid index 6ef0041f8e..da300bb8d4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa3a498dfe9ed59c30da5eaa0d7cad167fd4e393 \ No newline at end of file +1d5e744cc645150ccaa7256663146fc7b8540bd5 \ No newline at end of file diff --git a/test/capi3.test b/test/capi3.test index a9aab1e615..d9106267c5 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -901,6 +901,12 @@ do_test capi3-11.9.3 { do_test capi3-11.10 { sqlite3_step $STMT } {SQLITE_ERROR} +ifcapable !autoreset { + # If SQLITE_OMIT_AUTORESET is defined, then the statement must be + # reset() before it can be passed to step() again. + do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} + do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} +} do_test capi3-11.11 { sqlite3_step $STMT } {SQLITE_ROW} diff --git a/test/capi3c.test b/test/capi3c.test index adef7f9189..4092091894 100644 --- a/test/capi3c.test +++ b/test/capi3c.test @@ -856,6 +856,12 @@ do_test capi3c-11.9.3 { do_test capi3c-11.10 { sqlite3_step $STMT } {SQLITE_ABORT} +ifcapable !autoreset { + # If SQLITE_OMIT_AUTORESET is defined, then the statement must be + # reset() before it can be passed to step() again. + do_test capi3-11.11a { sqlite3_step $STMT } {SQLITE_MISUSE} + do_test capi3-11.11b { sqlite3_reset $STMT } {SQLITE_ABORT} +} do_test capi3c-11.11 { sqlite3_step $STMT } {SQLITE_ROW} From c8f8616c411a5dfe39469aed23ad7b6008bbd3a7 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 3 Apr 2012 18:34:24 +0000 Subject: [PATCH 16/32] Do not run attempt to run test file fts4merge3.test unless the build includes FTS. FossilOrigin-Name: 0506bf86d31e821a905e3a8a03c4817e326f7f44 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/fts4merge3.test | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 00bf39318a..c9deb0c9af 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\scapi3.test\sand\scapi3c.test\sso\sthat\sthey\swork\swith\sSQLITE_OMIT_AUTORESET\sbuilds. -D 2012-04-03T18:33:43.337 +C Do\snot\srun\sattempt\sto\srun\stest\sfile\sfts4merge3.test\sunless\sthe\sbuild\sincludes\sFTS. +D 2012-04-03T18:34:24.492 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -502,7 +502,7 @@ F test/fts4content.test 17b2360f7d1a9a7e5aa8022783f5c5731b6dfd4f F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7 F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 -F test/fts4merge3.test 640611c05f01e9e018ac10afd188b018d8fcd4e5 +F test/fts4merge3.test 125c3334f49bc171b3310efc99358cd05475c1d6 F test/func.test 9809b7622d721904a8cc33c1ffb87f46d506ed01 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P fa3a498dfe9ed59c30da5eaa0d7cad167fd4e393 -R 93f41d5cd0dd5634edd499aa7b12c353 +P 1d5e744cc645150ccaa7256663146fc7b8540bd5 +R 1f313aea8b457ed25b447b7c1422a6b5 U dan -Z 6ebde95baa77d452c6bdb9a26f49bf26 +Z 3c559de9db801435fc52303089f6fab9 diff --git a/manifest.uuid b/manifest.uuid index da300bb8d4..136f7e72d9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d5e744cc645150ccaa7256663146fc7b8540bd5 \ No newline at end of file +0506bf86d31e821a905e3a8a03c4817e326f7f44 \ No newline at end of file diff --git a/test/fts4merge3.test b/test/fts4merge3.test index d591329fb0..3fd300daf9 100644 --- a/test/fts4merge3.test +++ b/test/fts4merge3.test @@ -20,6 +20,11 @@ source $testdir/bc_common.tcl set ::testprefix fts4merge3 +ifcapable !fts3 { + finish_test + return +} + if {"" == [bc_find_binaries backcompat.test]} { finish_test return From 1779efd4832069d2f90ef757690972acd7281bd4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Apr 2012 13:43:13 +0000 Subject: [PATCH 17/32] In the multiplexor extension, improve the error logging when a chunk fails to open. FossilOrigin-Name: 781453c686656a7bd4a274a3b3204ceb6ecae8df --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/test_multiplex.c | 11 ++++++++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index c9deb0c9af..9c37e509fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\srun\sattempt\sto\srun\stest\sfile\sfts4merge3.test\sunless\sthe\sbuild\sincludes\sFTS. -D 2012-04-03T18:34:24.492 +C In\sthe\smultiplexor\sextension,\simprove\sthe\serror\slogging\swhen\sa\schunk\sfails\nto\sopen. +D 2012-04-04T13:43:13.686 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -215,7 +215,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c b964473ff1b7a65626763f068fa6a810385d1fbf F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c 3f5903a1528fd32fe4c472a3bd0259128d8faaef -F src/test_multiplex.c 30ca0348953abd3add46fe4ee19e3f9e669b7e56 +F src/test_multiplex.c 151f66e79b4a7e2cf66e6149deace77b461e0360 F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 5e1382e7844c703c77c4c2aee82f8359555b5a8e @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 1d5e744cc645150ccaa7256663146fc7b8540bd5 -R 1f313aea8b457ed25b447b7c1422a6b5 -U dan -Z 3c559de9db801435fc52303089f6fab9 +P 0506bf86d31e821a905e3a8a03c4817e326f7f44 +R fbd3d19fe8454971555d508563f6c5ba +U drh +Z a9ed2607a4279c682b012061bc35b79f diff --git a/manifest.uuid b/manifest.uuid index 136f7e72d9..93bc4fa1e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0506bf86d31e821a905e3a8a03c4817e326f7f44 \ No newline at end of file +781453c686656a7bd4a274a3b3204ceb6ecae8df \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 32dd8e33e8..f87f6a9be6 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -329,6 +329,7 @@ static sqlite3_file *multiplexSubOpen( ** database may therefore not grow to larger than 400 chunks. Attempting ** to open chunk 401 indicates the database is full. */ if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ + sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", zName); *rc = SQLITE_FULL; return 0; } @@ -347,7 +348,13 @@ static sqlite3_file *multiplexSubOpen( }else{ *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists); - if( *rc || !bExists ) return 0; + if( *rc || !bExists ){ + if( *rc ){ + sqlite3_log(*rc, "multiplexor.xAccess failure on %s", + pGroup->aReal[iChunk].z); + } + return 0; + } flags &= ~SQLITE_OPEN_CREATE; } pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); @@ -359,6 +366,8 @@ static sqlite3_file *multiplexSubOpen( *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen, flags, pOutFlags); if( (*rc)!=SQLITE_OK ){ + sqlite3_log(*rc, "multiplexor.xOpen failure on %s", + pGroup->aReal[iChunk].z); sqlite3_free(pSubOpen); pGroup->aReal[iChunk].p = 0; return 0; From 689453dbf03cd620f24f3ae59d81c36630f276cb Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Apr 2012 13:58:19 +0000 Subject: [PATCH 18/32] Fix the multiplexor logging so that it works with SQLITE_ENABLE_8_3_NAMES. FossilOrigin-Name: 9e1e2fe2950bb96784413eae934314d95bce08e7 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_multiplex.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 9c37e509fb..00ddad0755 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\smultiplexor\sextension,\simprove\sthe\serror\slogging\swhen\sa\schunk\sfails\nto\sopen. -D 2012-04-04T13:43:13.686 +C Fix\sthe\smultiplexor\slogging\sso\sthat\sit\sworks\swith\sSQLITE_ENABLE_8_3_NAMES. +D 2012-04-04T13:58:19.112 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -215,7 +215,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207 F src/test_journal.c b964473ff1b7a65626763f068fa6a810385d1fbf F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e F src/test_malloc.c 3f5903a1528fd32fe4c472a3bd0259128d8faaef -F src/test_multiplex.c 151f66e79b4a7e2cf66e6149deace77b461e0360 +F src/test_multiplex.c 3dffd0fe6c96ac7c5150485b55244e73faab5380 F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 5e1382e7844c703c77c4c2aee82f8359555b5a8e @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 0506bf86d31e821a905e3a8a03c4817e326f7f44 -R fbd3d19fe8454971555d508563f6c5ba +P 781453c686656a7bd4a274a3b3204ceb6ecae8df +R c73cb9ac19cc77c57d2e11c87f4932e5 U drh -Z a9ed2607a4279c682b012061bc35b79f +Z d5193cf8e689933624e4e4454cffd3d6 diff --git a/manifest.uuid b/manifest.uuid index 93bc4fa1e0..47a3f74825 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -781453c686656a7bd4a274a3b3204ceb6ecae8df \ No newline at end of file +9e1e2fe2950bb96784413eae934314d95bce08e7 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index f87f6a9be6..62b4902a8d 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -329,7 +329,7 @@ static sqlite3_file *multiplexSubOpen( ** database may therefore not grow to larger than 400 chunks. Attempting ** to open chunk 401 indicates the database is full. */ if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ - sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", zName); + sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName); *rc = SQLITE_FULL; return 0; } From 42f64e52eef7104860596a28176ece3ae9aed89a Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Apr 2012 16:56:23 +0000 Subject: [PATCH 19/32] Add the ".trace" option to the command-line shell. FossilOrigin-Name: b9ac3d7e340eb616fd23cc7dbdef6fdd66a79fe4 --- manifest | 12 +++---- manifest.uuid | 2 +- src/shell.c | 93 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index 00ddad0755..036172c168 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\smultiplexor\slogging\sso\sthat\sit\sworks\swith\sSQLITE_ENABLE_8_3_NAMES. -D 2012-04-04T13:58:19.112 +C Add\sthe\s".trace"\soption\sto\sthe\scommand-line\sshell. +D 2012-04-04T16:56:23.330 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 -F src/shell.c abf18d6ee54f2631860a98fdd7ab1327f470db67 +F src/shell.c ce4d41582182b8fad3be364e2fa295b70bc342ab F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h d701123ab4c8774ee2837cd4ade84e370d665f87 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 781453c686656a7bd4a274a3b3204ceb6ecae8df -R c73cb9ac19cc77c57d2e11c87f4932e5 +P 9e1e2fe2950bb96784413eae934314d95bce08e7 +R 7ce64940a4af6b82ea18cf10b0da61e8 U drh -Z d5193cf8e689933624e4e4454cffd3d6 +Z 783b4beff01e2d5037d4d8570a1550e1 diff --git a/manifest.uuid b/manifest.uuid index 47a3f74825..18daab3bde 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e1e2fe2950bb96784413eae934314d95bce08e7 \ No newline at end of file +b9ac3d7e340eb616fd23cc7dbdef6fdd66a79fe4 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 4287ef17d8..6aa844cfbb 100644 --- a/src/shell.c +++ b/src/shell.c @@ -421,6 +421,7 @@ struct callback_data { int statsOn; /* True to display memory stats before each finalize */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ + FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ @@ -1433,6 +1434,7 @@ static char zHelp[] = " If TABLE specified, only list tables matching\n" " LIKE pattern TABLE.\n" ".timeout MS Try opening locked tables for MS milliseconds\n" + ".trace FILE|off Output each SQL statement as it is run\n" ".vfsname ?AUX? Print the name of the VFS stack\n" ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" ; @@ -1522,6 +1524,43 @@ static int booleanValue(char *zArg){ return val; } +/* +** Close an output file, assuming it is not stderr or stdout +*/ +static void output_file_close(FILE *f){ + if( f && f!=stdout && f!=stderr ) fclose(f); +} + +/* +** Try to open an output file. The names "stdout" and "stderr" are +** recognized and do the right thing. NULL is returned if the output +** filename is "off". +*/ +static FILE *output_file_open(const char *zFile){ + FILE *f; + if( strcmp(zFile,"stdout")==0 ){ + f = stdout; + }else if( strcmp(zFile, "stderr")==0 ){ + f = stderr; + }else if( strcmp(zFile, "off")==0 ){ + f = 0; + }else{ + f = fopen(zFile, "wb"); + if( f==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + } + } + return f; +} + +/* +** A routine for handling output from sqlite3_trace(). +*/ +static void sql_trace_callback(void *pArg, const char *z){ + FILE *f = (FILE*)pArg; + if( f ) fprintf(f, "%s\n", z); +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -1932,22 +1971,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){ const char *zFile = azArg[1]; - if( p->pLog && p->pLog!=stdout && p->pLog!=stderr ){ - fclose(p->pLog); - p->pLog = 0; - } - if( strcmp(zFile,"stdout")==0 ){ - p->pLog = stdout; - }else if( strcmp(zFile, "stderr")==0 ){ - p->pLog = stderr; - }else if( strcmp(zFile, "off")==0 ){ - p->pLog = 0; - }else{ - p->pLog = fopen(zFile, "w"); - if( p->pLog==0 ){ - fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); - } - } + output_file_close(p->pLog); + p->pLog = output_file_open(zFile); }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){ @@ -2000,17 +2025,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ - if( p->out!=stdout ){ - if( p->outfile[0]=='|' ){ - pclose(p->out); - }else{ - fclose(p->out); - } + if( p->outfile[0]=='|' ){ + pclose(p->out); + }else{ + output_file_close(p->out); } - if( strcmp(azArg[1],"stdout")==0 ){ - p->out = stdout; - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); - }else if( azArg[1][0]=='|' ){ + p->outfile[0] = 0; + if( azArg[1][0]=='|' ){ p->out = popen(&azArg[1][1], "w"); if( p->out==0 ){ fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]); @@ -2020,13 +2041,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } }else{ - p->out = fopen(azArg[1], "wb"); + p->out = output_file_open(azArg[1]); if( p->out==0 ){ - fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]); + if( strcmp(azArg[1],"off")!=0 ){ + fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]); + } p->out = stdout; rc = 1; } else { - sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } } }else @@ -2396,6 +2419,18 @@ static int do_meta_command(char *zLine, struct callback_data *p){ enableTimer = booleanValue(azArg[1]); }else + if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ + output_file_close(p->traceOut); + p->traceOut = output_file_open(azArg[1]); +#ifndef SQLITE_OMIT_TRACE + if( p->traceOut==0 ){ + sqlite3_trace(p->db, 0, 0); + }else{ + sqlite3_trace(p->db, sql_trace_callback, p->traceOut); + } +#endif + }else + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ printf("SQLite %s %s\n" /*extra-version-info*/, sqlite3_libversion(), sqlite3_sourceid()); From 3343b439152083def34f7de064fee204bc8d0f4d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 5 Apr 2012 01:37:32 +0000 Subject: [PATCH 20/32] Performance improvements for the RowSet object when it undergoes many cycles between RowSetInsert and RowSetTest. FossilOrigin-Name: 49d20ede5f4c0895a165126d5cf7c95a0510ba35 --- manifest | 12 +-- manifest.uuid | 2 +- src/rowset.c | 212 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 156 insertions(+), 70 deletions(-) diff --git a/manifest b/manifest index 036172c168..dbc5928c3f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s".trace"\soption\sto\sthe\scommand-line\sshell. -D 2012-04-04T16:56:23.330 +C Performance\simprovements\sfor\sthe\sRowSet\sobject\swhen\sit\sundergoes\smany\ncycles\sbetween\sRowSetInsert\sand\sRowSetTest. +D 2012-04-05T01:37:32.902 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -180,7 +180,7 @@ F src/prepare.c ec4989f7f480544bdc4192fe663470d2a2d7d61e F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 -F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 +F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 F src/shell.c ce4d41582182b8fad3be364e2fa295b70bc342ab F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 9e1e2fe2950bb96784413eae934314d95bce08e7 -R 7ce64940a4af6b82ea18cf10b0da61e8 +P b9ac3d7e340eb616fd23cc7dbdef6fdd66a79fe4 +R a1d15ac4a2f200ebad8c15bdd80077ea U drh -Z 783b4beff01e2d5037d4d8570a1550e1 +Z 3eabbe65a412e07d9d0e849fd433908a diff --git a/manifest.uuid b/manifest.uuid index 18daab3bde..99e0c0b36c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b9ac3d7e340eb616fd23cc7dbdef6fdd66a79fe4 \ No newline at end of file +49d20ede5f4c0895a165126d5cf7c95a0510ba35 \ No newline at end of file diff --git a/src/rowset.c b/src/rowset.c index d84bb93abf..58c18b78db 100644 --- a/src/rowset.c +++ b/src/rowset.c @@ -76,6 +76,11 @@ /* ** Each entry in a RowSet is an instance of the following object. +** +** This same object is reused to store a linked list of trees of RowSetEntry +** objects. In that alternative use, pRight points to the next entry +** in the list, pLeft points to the tree, and v is unused. The +** RowSet.pForest value points to the head of this forest list. */ struct RowSetEntry { i64 v; /* ROWID value for this entry */ @@ -105,12 +110,18 @@ struct RowSet { struct RowSetEntry *pEntry; /* List of entries using pRight */ struct RowSetEntry *pLast; /* Last entry on the pEntry list */ struct RowSetEntry *pFresh; /* Source of new entry objects */ - struct RowSetEntry *pTree; /* Binary tree of entries */ + struct RowSetEntry *pForest; /* List of binary trees of entries */ u16 nFresh; /* Number of objects on pFresh */ - u8 isSorted; /* True if pEntry is sorted */ + u8 rsFlags; /* Various flags */ u8 iBatch; /* Current insert batch */ }; +/* +** Allowed values for RowSet.rsFlags +*/ +#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ +#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ + /* ** Turn bulk memory into a RowSet object. N bytes of memory ** are available at pSpace. The db pointer is used as a memory context @@ -131,10 +142,10 @@ RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ p->db = db; p->pEntry = 0; p->pLast = 0; - p->pTree = 0; + p->pForest = 0; p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); - p->isSorted = 1; + p->rsFlags = ROWSET_SORTED; p->iBatch = 0; return p; } @@ -154,8 +165,33 @@ void sqlite3RowSetClear(RowSet *p){ p->nFresh = 0; p->pEntry = 0; p->pLast = 0; - p->pTree = 0; - p->isSorted = 1; + p->pForest = 0; + p->rsFlags = ROWSET_SORTED; +} + +/* +** Allocate a new RowSetEntry object that is associated with the +** given RowSet. Return a pointer to the new and completely uninitialized +** objected. +** +** In an OOM situation, the RowSet.db->mallocFailed flag is set and this +** routine returns NULL. +*/ +static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ + assert( p!=0 ); + if( p->nFresh==0 ){ + struct RowSetChunk *pNew; + pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); + if( pNew==0 ){ + return 0; + } + pNew->pNextChunk = p->pChunk; + p->pChunk = pNew; + p->pFresh = pNew->aEntry; + p->nFresh = ROWSET_ENTRY_PER_CHUNK; + } + p->nFresh--; + return p->pFresh++; } /* @@ -167,30 +203,21 @@ void sqlite3RowSetClear(RowSet *p){ void sqlite3RowSetInsert(RowSet *p, i64 rowid){ struct RowSetEntry *pEntry; /* The new entry */ struct RowSetEntry *pLast; /* The last prior entry */ - assert( p!=0 ); - if( p->nFresh==0 ){ - struct RowSetChunk *pNew; - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); - if( pNew==0 ){ - return; - } - pNew->pNextChunk = p->pChunk; - p->pChunk = pNew; - p->pFresh = pNew->aEntry; - p->nFresh = ROWSET_ENTRY_PER_CHUNK; - } - pEntry = p->pFresh++; - p->nFresh--; + + /* This routine is never called after sqlite3RowSetNext() */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + pEntry = rowSetEntryAlloc(p); + if( pEntry==0 ) return; pEntry->v = rowid; pEntry->pRight = 0; pLast = p->pLast; if( pLast ){ - if( p->isSorted && rowid<=pLast->v ){ - p->isSorted = 0; + if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ + p->rsFlags &= ~ROWSET_SORTED; } pLast->pRight = pEntry; }else{ - assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */ p->pEntry = pEntry; } p->pLast = pEntry; @@ -202,7 +229,7 @@ void sqlite3RowSetInsert(RowSet *p, i64 rowid){ ** The input lists are connected via pRight pointers and are ** assumed to each already be in sorted order. */ -static struct RowSetEntry *rowSetMerge( +static struct RowSetEntry *rowSetEntryMerge( struct RowSetEntry *pA, /* First sorted list to be merged */ struct RowSetEntry *pB /* Second sorted list to be merged */ ){ @@ -236,32 +263,29 @@ static struct RowSetEntry *rowSetMerge( } /* -** Sort all elements on the pEntry list of the RowSet into ascending order. +** Sort all elements on the list of RowSetEntry objects into order of +** increasing v. */ -static void rowSetSort(RowSet *p){ +static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ unsigned int i; - struct RowSetEntry *pEntry; - struct RowSetEntry *aBucket[40]; + struct RowSetEntry *pNext, *aBucket[40]; - assert( p->isSorted==0 ); memset(aBucket, 0, sizeof(aBucket)); - while( p->pEntry ){ - pEntry = p->pEntry; - p->pEntry = pEntry->pRight; - pEntry->pRight = 0; + while( pIn ){ + pNext = pIn->pRight; + pIn->pRight = 0; for(i=0; aBucket[i]; i++){ - pEntry = rowSetMerge(aBucket[i], pEntry); + pIn = rowSetEntryMerge(aBucket[i], pIn); aBucket[i] = 0; } - aBucket[i] = pEntry; + aBucket[i] = pIn; + pIn = pNext; } - pEntry = 0; + pIn = 0; for(i=0; ipEntry = pEntry; - p->pLast = 0; - p->isSorted = 1; + return pIn; } @@ -355,20 +379,37 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ } /* -** Convert the list in p->pEntry into a sorted list if it is not -** sorted already. If there is a binary tree on p->pTree, then -** convert it into a list too and merge it into the p->pEntry list. +** Take all the entries on p->pEntry and on the trees in p->pForest and +** sort them all together into one big ordered list on p->pEntry. +** +** This routine should only be called once in the life of a RowSet. */ static void rowSetToList(RowSet *p){ - if( !p->isSorted ){ - rowSetSort(p); + + /* This routine is called only once */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + if( (p->rsFlags & ROWSET_SORTED)==0 ){ + p->pEntry = rowSetEntrySort(p->pEntry); } - if( p->pTree ){ - struct RowSetEntry *pHead, *pTail; - rowSetTreeToList(p->pTree, &pHead, &pTail); - p->pTree = 0; - p->pEntry = rowSetMerge(p->pEntry, pHead); + + /* While this module could theoretically support it, sqlite3RowSetNext() + ** is never called after sqlite3RowSetText() for the same RowSet. So + ** there is never a forest to deal with. Should this change, simply + ** remove the assert() and the #if 0. */ + assert( p->pForest==0 ); +#if 0 + while( p->pForest ){ + struct RowSetEntry *pTree = p->pForest->pLeft; + if( pTree ){ + struct RowSetEntry *pHead, *pTail; + rowSetTreeToList(pTree, &pHead, &pTail); + p->pEntry = rowSetEntryMerge(p->pEntry, pHead); + } + p->pForest = p->pForest->pRight; } +#endif + p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ } /* @@ -380,7 +421,12 @@ static void rowSetToList(RowSet *p){ ** routine may not be called again. */ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ - rowSetToList(p); + assert( p!=0 ); + + /* Merge the forest into a single sorted list on first call */ + if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); + + /* Return the next entry on the list */ if( p->pEntry ){ *pRowid = p->pEntry->v; p->pEntry = p->pEntry->pRight; @@ -396,26 +442,66 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ /* ** Check to see if element iRowid was inserted into the the rowset as ** part of any insert batch prior to iBatch. Return 1 or 0. +** +** If this is the first test of a new batch and if there exist entires +** on pRowSet->pEntry, then sort those entires into the forest at +** pRowSet->pForest so that they can be tested. */ int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ - struct RowSetEntry *p; + struct RowSetEntry *p, *pTree; + + /* This routine is never called after sqlite3RowSetNext() */ + assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); + + /* Sort entries into the forest on the first test of a new batch + */ if( iBatch!=pRowSet->iBatch ){ - if( pRowSet->pEntry ){ - rowSetToList(pRowSet); - pRowSet->pTree = rowSetListToTree(pRowSet->pEntry); + p = pRowSet->pEntry; + if( p ){ + struct RowSetEntry **ppPrevTree = &pRowSet->pForest; + if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ + p = rowSetEntrySort(p); + } + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + ppPrevTree = &pTree->pRight; + if( pTree->pLeft==0 ){ + pTree->pLeft = rowSetListToTree(p); + break; + }else{ + struct RowSetEntry *pAux, *pTail; + rowSetTreeToList(pTree->pLeft, &pAux, &pTail); + pTree->pLeft = 0; + p = rowSetEntryMerge(pAux, p); + } + } + if( pTree==0 ){ + *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); + if( pTree ){ + pTree->v = 0; + pTree->pRight = 0; + pTree->pLeft = rowSetListToTree(p); + } + } pRowSet->pEntry = 0; pRowSet->pLast = 0; + pRowSet->rsFlags |= ROWSET_SORTED; } pRowSet->iBatch = iBatch; } - p = pRowSet->pTree; - while( p ){ - if( p->vpRight; - }else if( p->v>iRowid ){ - p = p->pLeft; - }else{ - return 1; + + /* Test to see if the iRowid value appears anywhere in the forest. + ** Return 1 if it does and 0 if not. + */ + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + p = pTree->pLeft; + while( p ){ + if( p->vpRight; + }else if( p->v>iRowid ){ + p = p->pLeft; + }else{ + return 1; + } } } return 0; From b8af4b79193ee3170e7f0083956d7517801b7875 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 5 Apr 2012 20:04:39 +0000 Subject: [PATCH 21/32] Ignore the value of SQLITE_FCNTL_CHUNK_SIZE if it is negative. FossilOrigin-Name: 1b08fef9451f4d59148548faed115d1a5d0bcd98 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index dbc5928c3f..7410df23a0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovements\sfor\sthe\sRowSet\sobject\swhen\sit\sundergoes\smany\ncycles\sbetween\sRowSetInsert\sand\sRowSetTest. -D 2012-04-05T01:37:32.902 +C Ignore\sthe\svalue\sof\sSQLITE_FCNTL_CHUNK_SIZE\sif\sit\sis\snegative. +D 2012-04-05T20:04:39.277 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c F src/os.h 59beba555b65a450bd1d804220532971d4299f60 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 -F src/os_unix.c 0e3d2942d228d0366fb80a3640f35caf413b66d1 +F src/os_unix.c 75eff7b41cdc9f319eb0c610c19fd9bb37093e5d F src/os_win.c 5e9e933a412ab35de2a6506b3c6a8295b31b309e F src/pager.c 85988507fa20acc60defb834722eddf4633e4aeb F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P b9ac3d7e340eb616fd23cc7dbdef6fdd66a79fe4 -R a1d15ac4a2f200ebad8c15bdd80077ea +P 49d20ede5f4c0895a165126d5cf7c95a0510ba35 +R 6fcd7b8559835dc1ae4791a624b5bb49 U drh -Z 3eabbe65a412e07d9d0e849fd433908a +Z c7852355bd734400b5b2791a5df22d3c diff --git a/manifest.uuid b/manifest.uuid index 99e0c0b36c..43947c34c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -49d20ede5f4c0895a165126d5cf7c95a0510ba35 \ No newline at end of file +1b08fef9451f4d59148548faed115d1a5d0bcd98 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 48c130935e..559d156496 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3421,7 +3421,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ ** actual file size after the operation may be larger than the requested ** size). */ - if( pFile->szChunk ){ + if( pFile->szChunk>0 ){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } From 370026242abd997ae6e417099a91cc559b4cb0fb Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Apr 2012 00:09:27 +0000 Subject: [PATCH 22/32] Update sqlite3_analyzer to correctly find all database files when the multiplexor is being used. FossilOrigin-Name: 1bfc30cb0fdc4b9def989eea2d78f6ac851633fa --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/spaceanal.tcl | 5 ++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7410df23a0..995368f0bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ignore\sthe\svalue\sof\sSQLITE_FCNTL_CHUNK_SIZE\sif\sit\sis\snegative. -D 2012-04-05T20:04:39.277 +C Update\ssqlite3_analyzer\sto\scorrectly\sfind\sall\sdatabase\sfiles\swhen\sthe\nmultiplexor\sis\sbeing\sused. +D 2012-04-06T00:09:27.071 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -987,7 +987,7 @@ F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02 F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b -F tool/spaceanal.tcl 15f6cd939b4ecc14d061de7e8ace89e26c30c40b +F tool/spaceanal.tcl e42273000686a4afbf6a5e5d7fb12be65e92afb1 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 49d20ede5f4c0895a165126d5cf7c95a0510ba35 -R 6fcd7b8559835dc1ae4791a624b5bb49 +P 1b08fef9451f4d59148548faed115d1a5d0bcd98 +R 220148404893713f89fb8c5c7ad54b6d U drh -Z c7852355bd734400b5b2791a5df22d3c +Z 737b7c44e8ad27216e6474b5a72beb32 diff --git a/manifest.uuid b/manifest.uuid index 43947c34c6..c94684abbe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b08fef9451f4d59148548faed115d1a5d0bcd98 \ No newline at end of file +1bfc30cb0fdc4b9def989eea2d78f6ac851633fa \ No newline at end of file diff --git a/tool/spaceanal.tcl b/tool/spaceanal.tcl index 3dddfe42d4..fd59670ada 100644 --- a/tool/spaceanal.tcl +++ b/tool/spaceanal.tcl @@ -49,15 +49,14 @@ if {$true_file_size<512} { # set extension [file extension $file_to_analyze] set pattern $file_to_analyze -append pattern {[0-9][0-9]} +append pattern {[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] set extension {} } if {[string length $extension]>=2 && [string length $extension]<=4} { set pattern [file rootname $file_to_analyze] - append pattern [string range $extension 0 1] - append pattern {[0-9][0-9]} + append pattern {.[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] } From 89d5d6a2a76f72bbac57bb082f7d52bb829dd02c Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 7 Apr 2012 00:09:21 +0000 Subject: [PATCH 23/32] Fix the application-defined function logic so that functions with a variable number of parameters can be replaced or deleted correctly. Also refactor some of the function-finder code for clarity of presentation. FossilOrigin-Name: 09d5581c81fb6a9bf6a369d0abf5ef6b54637576 --- manifest | 16 ++++----- manifest.uuid | 2 +- src/callback.c | 89 ++++++++++++++++++++++++++++++------------------- src/resolve.c | 2 +- src/sqliteInt.h | 2 +- 5 files changed, 65 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index 995368f0bb..d2128ee46b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\ssqlite3_analyzer\sto\scorrectly\sfind\sall\sdatabase\sfiles\swhen\sthe\nmultiplexor\sis\sbeing\sused. -D 2012-04-06T00:09:27.071 +C Fix\sthe\sapplication-defined\sfunction\slogic\sso\sthat\sfunctions\swith\sa\svariable\nnumber\sof\sparameters\scan\sbe\sreplaced\sor\sdeleted\scorrectly.\s\sAlso\srefactor\nsome\sof\sthe\sfunction-finder\scode\sfor\sclarity\sof\spresentation. +D 2012-04-07T00:09:21.842 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -130,7 +130,7 @@ F src/btree.c df800f10896bc2ddaa1125c532d6e7a7b9efc532 F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923 F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e F src/build.c 987c6933ea170e443dc6a79d52f8d2506206b12b -F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a +F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 @@ -179,13 +179,13 @@ F src/pragma.c e708b3bb5704605816f617e0b1d63a5488060715 F src/prepare.c ec4989f7f480544bdc4192fe663470d2a2d7d61e F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 -F src/resolve.c 3d3e80a98f203ac6b9329e9621e29eda85ddfd40 +F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 F src/shell.c ce4d41582182b8fad3be364e2fa295b70bc342ab F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 -F src/sqliteInt.h d701123ab4c8774ee2837cd4ade84e370d665f87 +F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 1b08fef9451f4d59148548faed115d1a5d0bcd98 -R 220148404893713f89fb8c5c7ad54b6d +P 1bfc30cb0fdc4b9def989eea2d78f6ac851633fa +R 7617876a091e2e4cf9376c46017f187f U drh -Z 737b7c44e8ad27216e6474b5a72beb32 +Z 1d4ad19c22a54f0c05282a803680a670 diff --git a/manifest.uuid b/manifest.uuid index c94684abbe..bf2cf2526c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1bfc30cb0fdc4b9def989eea2d78f6ac851633fa \ No newline at end of file +09d5581c81fb6a9bf6a369d0abf5ef6b54637576 \ No newline at end of file diff --git a/src/callback.c b/src/callback.c index ce849085c2..a515e05e2a 100644 --- a/src/callback.c +++ b/src/callback.c @@ -223,38 +223,57 @@ CollSeq *sqlite3FindCollSeq( ** that uses encoding enc. The value returned indicates how well the ** request is matched. A higher value indicates a better match. ** +** If nArg is -1 that means to only return a match (non-zero) if p->nArg +** is also -1. In other words, we are searching for a function that +** takes a variable number of arguments. +** +** If nArg is -2 that means that we are searching for any function +** regardless of the number of arguments it uses, so return a positive +** match score for any +** ** The returned value is always between 0 and 6, as follows: ** -** 0: Not a match, or if nArg<0 and the function is has no implementation. -** 1: A variable arguments function that prefers UTF-8 when a UTF-16 -** encoding is requested, or vice versa. -** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is -** requested, or vice versa. -** 3: A variable arguments function using the same text encoding. -** 4: A function with the exact number of arguments requested that -** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. -** 5: A function with the exact number of arguments requested that -** prefers UTF-16LE when UTF-16BE is requested, or vice versa. -** 6: An exact match. +** 0: Not a match. +** 1: UTF8/16 conversion required and function takes any number of arguments. +** 2: UTF16 byte order change required and function takes any number of args. +** 3: encoding matches and function takes any number of arguments +** 4: UTF8/16 conversion required - argument count matches exactly +** 5: UTF16 byte order conversion required - argument count matches exactly +** 6: Perfect match: encoding and argument count match exactly. ** +** If nArg==(-2) then any function with a non-null xStep or xFunc is +** a perfect match and any function with both xStep and xFunc NULL is +** a non-match. */ -static int matchQuality(FuncDef *p, int nArg, u8 enc){ - int match = 0; - if( p->nArg==-1 || p->nArg==nArg - || (nArg==-1 && (p->xFunc!=0 || p->xStep!=0)) - ){ +#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ +static int matchQuality( + FuncDef *p, /* The function we are evaluating for match quality */ + int nArg, /* Desired number of arguments. (-1)==any */ + u8 enc /* Desired text encoding */ +){ + int match; + + /* nArg of -2 is a special case */ + if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH; + + /* Wrong number of arguments means "no match" */ + if( p->nArg!=nArg && p->nArg>=0 ) return 0; + + /* Give a better score to a function with a specific number of arguments + ** than to function that accepts any number of arguments. */ + if( p->nArg==nArg ){ + match = 4; + }else{ match = 1; - if( p->nArg==nArg || nArg==-1 ){ - match = 4; - } - if( enc==p->iPrefEnc ){ - match += 2; - } - else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || - (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ - match += 1; - } } + + /* Bonus points if the text encoding matches */ + if( enc==p->iPrefEnc ){ + match += 2; /* Exact encoding match */ + }else if( (enc & p->iPrefEnc & 2)!=0 ){ + match += 1; /* Both are UTF16, but with different byte orders */ + } + return match; } @@ -310,13 +329,12 @@ void sqlite3FuncDefInsert( ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a -** no matching function previously existed. When createFlag is true -** and the nArg parameter is -1, then only a function that accepts -** any number of arguments will be returned. +** no matching function previously existed. ** -** If createFlag is false and nArg is -1, then the first valid -** function found is returned. A function is valid if either xFunc -** or xStep is non-zero. +** If nArg is -2, then the first valid function found is returned. A +** function is valid if either xFunc or xStep is non-zero. The nArg==(-2) +** case is used to see if zName is a valid function name for some number +** of arguments. If nArg is -2, then createFlag must be 0. ** ** If createFlag is false, then a function with the required name and ** number of arguments may be returned even if the eTextRep flag does not @@ -328,14 +346,15 @@ FuncDef *sqlite3FindFunction( int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ - int createFlag /* Create new entry if true and does not otherwise exist */ + u8 createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *p; /* Iterator variable */ FuncDef *pBest = 0; /* Best match found so far */ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ - + assert( nArg>=(-2) ); + assert( nArg>=(-1) || createFlag==0 ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); @@ -381,7 +400,7 @@ FuncDef *sqlite3FindFunction( ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ - if( createFlag && (bestScore<6 || pBest->nArg!=nArg) && + if( createFlag && bestScorezName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; diff --git a/src/resolve.c b/src/resolve.c index 3da48136fd..6590cd8ac4 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -533,7 +533,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ - pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c52244c116..ccffe09c2e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2845,7 +2845,7 @@ SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); IdList *sqlite3IdListDup(sqlite3*,IdList*); Select *sqlite3SelectDup(sqlite3*,Select*,int); void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); -FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); +FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); void sqlite3RegisterBuiltinFunctions(sqlite3*); void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterGlobalFunctions(void); From 35c86a94cf1992c62b08ffc35dc630ddbe5dd541 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Apr 2012 16:05:27 +0000 Subject: [PATCH 24/32] Fix a copy/paste error in a comment in the fuzzer. No changes to code. FossilOrigin-Name: 7433f2b5508ebf09d0e3e32a995f1126eaab8999 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_fuzzer.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index d2128ee46b..acbdddb62b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sapplication-defined\sfunction\slogic\sso\sthat\sfunctions\swith\sa\svariable\nnumber\sof\sparameters\scan\sbe\sreplaced\sor\sdeleted\scorrectly.\s\sAlso\srefactor\nsome\sof\sthe\sfunction-finder\scode\sfor\sclarity\sof\spresentation. -D 2012-04-07T00:09:21.842 +C Fix\sa\scopy/paste\serror\sin\sa\scomment\sin\sthe\sfuzzer.\s\sNo\schanges\sto\scode. +D 2012-04-10T16:05:27.567 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -207,7 +207,7 @@ F src/test_config.c 0de329e736eb4aa5845069bed630e5c72f012264 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd -F src/test_fuzzer.c 3703a190bd79a43e5f097d59c73ab38961d14872 +F src/test_fuzzer.c 7e431cb04f4457b676a2764839d2857fdd91ec4e F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 1bfc30cb0fdc4b9def989eea2d78f6ac851633fa -R 7617876a091e2e4cf9376c46017f187f +P 09d5581c81fb6a9bf6a369d0abf5ef6b54637576 +R 943f4e1c7aaa43ed0d8f52aacf8c1af9 U drh -Z 1d4ad19c22a54f0c05282a803680a670 +Z bb1afab0a69bf02921a229d11d9f81e5 diff --git a/manifest.uuid b/manifest.uuid index bf2cf2526c..0184cf7589 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -09d5581c81fb6a9bf6a369d0abf5ef6b54637576 \ No newline at end of file +7433f2b5508ebf09d0e3e32a995f1126eaab8999 \ No newline at end of file diff --git a/src/test_fuzzer.c b/src/test_fuzzer.c index 60d56ee1ea..d32a39c155 100644 --- a/src/test_fuzzer.c +++ b/src/test_fuzzer.c @@ -1127,8 +1127,7 @@ static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ } /* -** A virtual table module that provides read-only access to a -** Tcl global variable namespace. +** A virtual table module that implements the "fuzzer". */ static sqlite3_module fuzzerModule = { 0, /* iVersion */ From c00ce490c59a3466063d70ea800e01aba6994cee Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Apr 2012 17:53:47 +0000 Subject: [PATCH 25/32] Add new interfaces to the test_quota.c module: sqlite3_quota_ftruncate(), sqlite3_quota_file_size(), sqlite3_quota_file_truesize(), and sqlite3_quota_file_mtime(). FossilOrigin-Name: 2fa9f54309aea9927fb3695a986febd4963df7d1 --- manifest | 16 ++-- manifest.uuid | 2 +- src/test_quota.c | 232 +++++++++++++++++++++++++++++++++++++++++++---- src/test_quota.h | 50 ++++++++++ test/quota2.test | 37 +++++++- 5 files changed, 309 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index acbdddb62b..183c09e20e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scopy/paste\serror\sin\sa\scomment\sin\sthe\sfuzzer.\s\sNo\schanges\sto\scode. -D 2012-04-10T16:05:27.567 +C Add\snew\sinterfaces\sto\sthe\stest_quota.c\smodule:\s\ssqlite3_quota_ftruncate(),\nsqlite3_quota_file_size(),\ssqlite3_quota_file_truesize(),\sand\nsqlite3_quota_file_mtime(). +D 2012-04-10T17:53:47.880 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,8 +221,8 @@ F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e F src/test_onefile.c 5e1382e7844c703c77c4c2aee82f8359555b5a8e F src/test_osinst.c 7f790ac89c5a585d51b341274d9691c3391e0923 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 -F src/test_quota.c a545115f837da4ef32f6b5578f147b44cfb13fd7 -F src/test_quota.h 9ffa1d3ad6d0a6a24e8670ea64b909c717ec3358 +F src/test_quota.c 2ab468f5817b84f7105f78b77c300649ea5af8d1 +F src/test_quota.h ee5da2ae7f84d1c8e0e0e2ab33f01d69f10259b5 F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f @@ -651,7 +651,7 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 F test/quota.test c2f778dab4c7fb07bcfa962cc5c762f36d8061dc -F test/quota2.test 7e1c84f71f59388963fa8181a1292c87ae814d2d +F test/quota2.test bc9fdb2e46aace691c1a01a9cc8d097bd4d7c1ab F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 09d5581c81fb6a9bf6a369d0abf5ef6b54637576 -R 943f4e1c7aaa43ed0d8f52aacf8c1af9 +P 7433f2b5508ebf09d0e3e32a995f1126eaab8999 +R 85564f41a960bd198f1c0cd3cc4e501c U drh -Z bb1afab0a69bf02921a229d11d9f81e5 +Z b7da54f2c32a033935fc1a3628198083 diff --git a/manifest.uuid b/manifest.uuid index 0184cf7589..a6e3677ea1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7433f2b5508ebf09d0e3e32a995f1126eaab8999 \ No newline at end of file +2fa9f54309aea9927fb3695a986febd4963df7d1 \ No newline at end of file diff --git a/src/test_quota.c b/src/test_quota.c index e749851238..6514a28a13 100644 --- a/src/test_quota.c +++ b/src/test_quota.c @@ -120,6 +120,9 @@ struct quota_FILE { FILE *f; /* Open stdio file pointer */ sqlite3_int64 iOfst; /* Current offset into the file */ quotaFile *pFile; /* The file record in the quota system */ +#if SQLITE_OS_WIN + char *zMbcsName; /* Full MBCS pathname of the file */ +#endif }; @@ -979,7 +982,7 @@ int sqlite3_quota_file(const char *zFilename){ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ quota_FILE *p = 0; char *zFull = 0; - char *zFullTranslated; + char *zFullTranslated = 0; int rc; quotaGroup *pGroup; quotaFile *pFile; @@ -995,7 +998,6 @@ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ zFullTranslated = quota_utf8_to_mbcs(zFull); if( zFullTranslated==0 ) goto quota_fopen_error; p->f = fopen(zFullTranslated, zMode); - quota_mbcs_free(zFullTranslated); if( p->f==0 ) goto quota_fopen_error; quotaEnter(); pGroup = quotaGroupFind(zFull); @@ -1010,9 +1012,13 @@ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ } quotaLeave(); sqlite3_free(zFull); +#if SQLITE_OS_WIN + p->zMbcsName = zFullTranslated; +#endif return p; quota_fopen_error: + quota_mbcs_free(zFullTranslated); sqlite3_free(zFull); if( p && p->f ) fclose(p->f); sqlite3_free(p); @@ -1045,6 +1051,7 @@ size_t sqlite3_quota_fwrite( sqlite3_int64 iEnd; sqlite3_int64 szNew; quotaFile *pFile; + size_t rc; iOfst = ftell(p->f); iEnd = iOfst + size*nmemb; @@ -1068,8 +1075,23 @@ size_t sqlite3_quota_fwrite( pGroup->iSize = szNew; pFile->iSize = iEnd; quotaLeave(); + }else{ + pFile = 0; } - return fwrite(pBuf, size, nmemb, p->f); + rc = fwrite(pBuf, size, nmemb, p->f); + + /* If the write was incomplete, adjust the file size and group size + ** downward */ + if( rc=0 ? rc : 0; + sqlite3_int64 iNewEnd = iOfst + size*nWritten; + if( iNewEndpGroup->iSize += iNewEnd - pFile->iSize; + pFile->iSize = iNewEnd; + quotaLeave(); + } + return rc; } /* @@ -1093,6 +1115,9 @@ int sqlite3_quota_fclose(quota_FILE *p){ } quotaLeave(); } +#if SQLITE_OS_WIN + quota_mbcs_free(p->zMbcsName); +#endif sqlite3_free(p); return rc; } @@ -1135,6 +1160,83 @@ long sqlite3_quota_ftell(quota_FILE *p){ return ftell(p->f); } +/* +** Truncate a file to szNew bytes. +*/ +int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){ + quotaFile *pFile = p->pFile; + int rc; + if( (pFile = p->pFile)!=0 && pFile->iSizeiSizepGroup; + quotaEnter(); + pGroup->iSize += szNew - pFile->iSize; + quotaLeave(); + } +#if SQLITE_OS_UNIX + rc = ftruncate(fileno(p->f), szNew); +#endif +#if SQLITE_OS_WIN + rc = _chsize_s(_fileno(p->f), szNew); +#endif + if( pFile && rc==0 ){ + quotaGroup *pGroup = pFile->pGroup; + quotaEnter(); + pGroup->iSize += szNew - pFile->iSize; + pFile->iSize = szNew; + quotaLeave(); + } + return rc; +} + +/* +** Determine the time that the given file was last modified, in +** seconds size 1970. Write the result into *pTime. Return 0 on +** success and non-zero on any kind of error. +*/ +int sqlite3_quota_file_mtime(quota_FILE *p, time_t *pTime){ + int rc; +#if SQLITE_OS_UNIX + struct stat buf; + rc = fstat(fileno(p->f), &buf); +#endif +#if SQLITE_OS_WIN + struct _stati64 buf; + rc = _stati64(p->zMbcsName, &buf); +#endif + if( rc==0 ) *pTime = buf.st_mtime; + return rc; +} + +/* +** Return the true size of the file, as reported by the operating +** system. +*/ +sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){ + int rc; +#if SQLITE_OS_UNIX + struct stat buf; + rc = fstat(fileno(p->f), &buf); +#endif +#if SQLITE_OS_WIN + struct _stati64 buf; + rc = _stati64(p->zMbcsName, &buf); +#endif + return rc==0 ? buf.st_size : -1; +} + +/* +** Return the size of the file, as it is known to the quota subsystem. +*/ +sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){ + return p->pFile ? p->pFile->iSize : -1; +} + /* ** Remove a managed file. Update quotas accordingly. */ @@ -1656,6 +1758,96 @@ static int test_quota_ftell( return TCL_OK; } +/* +** tclcmd: sqlite3_quota_ftruncate HANDLE SIZE +*/ +static int test_quota_ftruncate( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + Tcl_WideInt w; + int rc; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + if( Tcl_GetWideIntFromObj(interp, objv[2], &w) ) return TCL_ERROR; + x = (sqlite3_int64)w; + rc = sqlite3_quota_ftruncate(p, x); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_size HANDLE +*/ +static int test_quota_file_size( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + x = sqlite3_quota_file_size(p); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_truesize HANDLE +*/ +static int test_quota_file_truesize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + sqlite3_int64 x; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + x = sqlite3_quota_file_truesize(p); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_quota_file_mtime HANDLE +*/ +static int test_quota_file_mtime( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + quota_FILE *p; + time_t t; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); + return TCL_ERROR; + } + p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + t = 0; + sqlite3_quota_file_mtime(p, &t); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); + return TCL_OK; +} + + /* ** tclcmd: sqlite3_quota_remove FILENAME */ @@ -1713,21 +1905,25 @@ int Sqlitequota_Init(Tcl_Interp *interp){ char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { - { "sqlite3_quota_initialize", test_quota_initialize }, - { "sqlite3_quota_shutdown", test_quota_shutdown }, - { "sqlite3_quota_set", test_quota_set }, - { "sqlite3_quota_file", test_quota_file }, - { "sqlite3_quota_dump", test_quota_dump }, - { "sqlite3_quota_fopen", test_quota_fopen }, - { "sqlite3_quota_fread", test_quota_fread }, - { "sqlite3_quota_fwrite", test_quota_fwrite }, - { "sqlite3_quota_fclose", test_quota_fclose }, - { "sqlite3_quota_fflush", test_quota_fflush }, - { "sqlite3_quota_fseek", test_quota_fseek }, - { "sqlite3_quota_rewind", test_quota_rewind }, - { "sqlite3_quota_ftell", test_quota_ftell }, - { "sqlite3_quota_remove", test_quota_remove }, - { "sqlite3_quota_glob", test_quota_glob }, + { "sqlite3_quota_initialize", test_quota_initialize }, + { "sqlite3_quota_shutdown", test_quota_shutdown }, + { "sqlite3_quota_set", test_quota_set }, + { "sqlite3_quota_file", test_quota_file }, + { "sqlite3_quota_dump", test_quota_dump }, + { "sqlite3_quota_fopen", test_quota_fopen }, + { "sqlite3_quota_fread", test_quota_fread }, + { "sqlite3_quota_fwrite", test_quota_fwrite }, + { "sqlite3_quota_fclose", test_quota_fclose }, + { "sqlite3_quota_fflush", test_quota_fflush }, + { "sqlite3_quota_fseek", test_quota_fseek }, + { "sqlite3_quota_rewind", test_quota_rewind }, + { "sqlite3_quota_ftell", test_quota_ftell }, + { "sqlite3_quota_ftruncate", test_quota_ftruncate }, + { "sqlite3_quota_file_size", test_quota_file_size }, + { "sqlite3_quota_file_truesize", test_quota_file_truesize }, + { "sqlite3_quota_file_mtime", test_quota_file_mtime }, + { "sqlite3_quota_remove", test_quota_remove }, + { "sqlite3_quota_glob", test_quota_glob }, }; int i; diff --git a/src/test_quota.h b/src/test_quota.h index a2fddbbc43..9bd4312c6c 100644 --- a/src/test_quota.h +++ b/src/test_quota.h @@ -29,6 +29,14 @@ #ifndef _QUOTA_H_ #include "sqlite3.h" #include +#include +#include +#if SQLITE_OS_UNIX +# include +#endif +#if SQLITE_OS_WIN +# include +#endif /* Make this callable from C++ */ #ifdef __cplusplus @@ -182,6 +190,48 @@ int sqlite3_quota_fseek(quota_FILE*, long, int); void sqlite3_quota_rewind(quota_FILE*); long sqlite3_quota_ftell(quota_FILE*); +/* +** Truncate a file previously opened by sqlite3_quota_fopen(). Return +** zero on success and non-zero on any kind of failure. +** +** The newSize argument must be less than or equal to the current file size. +** Any attempt to "truncate" a file to a larger size results in +** undefined behavior. +*/ +int sqlite3_quota_ftrunate(quota_FILE*, sqlite3_int64 newSize); + +/* +** Return the last modification time of the opened file, in seconds +** since 1970. +*/ +int sqlite3_quota_file_mtime(quota_FILE*, time_t *pTime); + +/* +** Return the size of the file as it is known to the quota system. +** +** This size might be different from the true size of the file on +** disk if some outside process has modified the file without using the +** quota mechanism, or if calls to sqlite3_quota_fwrite() have occurred +** which have increased the file size, but those writes have not yet been +** forced to disk using sqlite3_quota_fflush(). +** +** Return -1 if the file is not participating in quota management. +*/ +sqlite3_int64 sqlite3_quota_file_size(quota_FILE*); + +/* +** Return the true size of the file. +** +** The true size should be the same as the size of the file as known +** to the quota system, however the sizes might be different if the +** file has been extended or truncated via some outside process or if +** pending writes have not yet been flushed to disk. +** +** Return -1 if the file does not exist or if the size of the file +** cannot be determined for some reason. +*/ +sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*); + /* ** Delete a file from the disk, if that file is under quota management. ** Adjust quotas accordingly. diff --git a/test/quota2.test b/test/quota2.test index fae4d2dbd7..5bb50d7ce0 100644 --- a/test/quota2.test +++ b/test/quota2.test @@ -76,6 +76,13 @@ do_test quota2-1.1 { do_test quota2-1.2 { set ::quota } {PWD/quota2a/xyz.txt 4000 7000} +do_test quota2-1.2.1 { + sqlite3_quota_file_size $::h1 +} {4000} +do_test quota2-1.2.2 { + sqlite3_quota_fflush $::h1 1 + sqlite3_quota_file_truesize $::h1 +} {4000} do_test quota2-1.3 { sqlite3_quota_rewind $::h1 set ::x [sqlite3_quota_fread $::h1 1001 7] @@ -112,15 +119,43 @@ do_test quota2-1.11 { standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 1 0}}} do_test quota2-1.12 { + sqlite3_quota_ftruncate $::h1 3500 + sqlite3_quota_file_size $::h1 +} {3500} +do_test quota2-1.13 { + sqlite3_quota_file_truesize $::h1 +} {3500} +do_test quota2-1.14 { + standard_path [sqlite3_quota_dump] +} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 3500 {PWD/quota2a/xyz.txt 3500 1 0}}} +do_test quota2-1.15 { + sqlite3_quota_fseek $::h1 0 SEEK_END + sqlite3_quota_ftell $::h1 +} {3500} +do_test quota2-1.16 { + sqlite3_quota_fwrite $::h1 1 7000 $bigtext +} {500} +do_test quota2-1.17 { + sqlite3_quota_ftell $::h1 +} {4000} +do_test quota2-1.18 { + sqlite3_quota_file_size $::h1 +} {4000} +do_test quota2-1.19 { + sqlite3_quota_fflush $::h1 1 + sqlite3_quota_file_truesize $::h1 +} {4000} +do_test quota2-1.20 { sqlite3_quota_fclose $::h1 standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 0 0}}} -do_test quota2-1.13 { +do_test quota2-1.21 { sqlite3_quota_remove quota2a/xyz.txt standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}} + set quota {} do_test quota2-2.1 { set ::h1 [sqlite3_quota_fopen quota2c/xyz.txt w+b] From 85e7243acfb3cc4edb16f8276e374cd730b5a0a7 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Apr 2012 11:38:53 +0000 Subject: [PATCH 26/32] Fix harmless static-analysis warnings, mosting having to do with memory leaks in the command-line shell. Add a clang analysis of the command-line shell to the "warnings-clang.sh" script. Other minor cleanups to the command-line shell code. FossilOrigin-Name: 93a0f452a7023898ad3d62ee81b39a80477c332f --- ext/fts3/fts3_write.c | 1 - manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/shell.c | 27 +++++++++------------------ tool/build-shell.sh | 4 ++-- tool/warnings-clang.sh | 5 +++-- 6 files changed, 24 insertions(+), 33 deletions(-) diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index fa84357e4d..fa5fb02451 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -3739,7 +3739,6 @@ static int fts3IncrmergeAppend( pLeaf->key.n = 0; pLeaf->block.n = 0; - nPrefix = 0; nSuffix = nTerm; nSpace = 1; nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; diff --git a/manifest b/manifest index 183c09e20e..1b588d1a98 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sinterfaces\sto\sthe\stest_quota.c\smodule:\s\ssqlite3_quota_ftruncate(),\nsqlite3_quota_file_size(),\ssqlite3_quota_file_truesize(),\sand\nsqlite3_quota_file_mtime(). -D 2012-04-10T17:53:47.880 +C Fix\sharmless\sstatic-analysis\swarnings,\smosting\shaving\sto\sdo\swith\smemory\nleaks\sin\sthe\scommand-line\sshell.\s\sAdd\sa\sclang\sanalysis\sof\sthe\scommand-line\nshell\sto\sthe\s"warnings-clang.sh"\sscript.\s\sOther\sminor\scleanups\sto\sthe\ncommand-line\sshell\scode. +D 2012-04-11T11:38:53.434 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,7 +78,7 @@ F ext/fts3/fts3_test.c f153a121c763993e3d94cc99c012ee68d13231ae F ext/fts3/fts3_tokenizer.c 3da7254a9881f7e270ab28e2004e0d22b3212bce F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 -F ext/fts3/fts3_write.c 545c3e2add64c27b2b03f9c79619ac5e47043252 +F ext/fts3/fts3_write.c cd4af00b3b0512b4d76177a267fcaafab44cbce4 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197 @@ -182,7 +182,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 -F src/shell.c ce4d41582182b8fad3be364e2fa295b70bc342ab +F src/shell.c 6fef5d2cd1eccd0a692d5d458897d815afaea908 F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 @@ -956,7 +956,7 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 F test/zerodamage.test 0de750389990b1078bab203c712dc3fefd1d8b82 -F tool/build-shell.sh 12aa4391073a777fcb6dcc490b219a018ae98bac +F tool/build-shell.sh b64a481901fc9ffe5ca8812a2a9255b6cfb77381 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 @@ -998,9 +998,9 @@ F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a +F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 7433f2b5508ebf09d0e3e32a995f1126eaab8999 -R 85564f41a960bd198f1c0cd3cc4e501c +P 2fa9f54309aea9927fb3695a986febd4963df7d1 +R fcc323db955b3488f04a596dcdc692dc U drh -Z b7da54f2c32a033935fc1a3628198083 +Z 36fed4c702c105f246b456f165a799df diff --git a/manifest.uuid b/manifest.uuid index a6e3677ea1..083955ca72 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2fa9f54309aea9927fb3695a986febd4963df7d1 \ No newline at end of file +93a0f452a7023898ad3d62ee81b39a80477c332f \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 6aa844cfbb..e5cfec70a8 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1310,6 +1310,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); + free(zTmp); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); @@ -1338,7 +1339,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); run_table_dump_query(p, zSelect, 0); } - if( zSelect ) free(zSelect); + free(zSelect); } return 0; } @@ -2642,12 +2643,11 @@ static int process_input(struct callback_data *p, FILE *in){ /* ** Return a pathname which is the user's home directory. A -** 0 return indicates an error of some kind. Space to hold the -** resulting string is obtained from malloc(). The calling -** function should free the result. +** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ - char *home_dir = NULL; + static char *home_dir = NULL; + if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) struct passwd *pwent; @@ -2660,7 +2660,7 @@ static char *find_home_dir(void){ #if defined(_WIN32_WCE) /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() */ - home_dir = strdup("/"); + home_dir = "/"; #else #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) @@ -2716,7 +2716,6 @@ static int process_sqliterc( const char *sqliterc = sqliterc_override; char *zBuf = 0; FILE *in = NULL; - int nBuf; int rc = 0; if (sqliterc == NULL) { @@ -2727,15 +2726,8 @@ static int process_sqliterc( #endif return 1; } - nBuf = strlen30(home_dir) + 16; - zBuf = malloc( nBuf ); - if( zBuf==0 ){ - fprintf(stderr,"%s: Error: out of memory\n",Argv0); - return 1; - } - sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir); - free(home_dir); - sqliterc = (const char*)zBuf; + zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + sqliterc = zBuf; } in = fopen(sqliterc,"rb"); if( in ){ @@ -2745,7 +2737,7 @@ static int process_sqliterc( rc = process_input(p,in); fclose(in); } - free(zBuf); + sqlite3_free(zBuf); return rc; } @@ -3086,7 +3078,6 @@ int main(int argc, char **argv){ write_history(zHistory); free(zHistory); } - free(zHome); }else{ rc = process_input(&data, stdin); } diff --git a/tool/build-shell.sh b/tool/build-shell.sh index 54e8308095..8e62a71746 100644 --- a/tool/build-shell.sh +++ b/tool/build-shell.sh @@ -12,8 +12,8 @@ make sqlite3.c gcc -o sqlite3 -g -Os -I. \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_ENABLE_VFSTRACE \ - -DSQLITE_ENABLE_STAT2 \ - -DSQLITE_ENABLE_FTS3 \ + -DSQLITE_ENABLE_STAT3 \ + -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_RTREE \ -DHAVE_READLINE \ -DHAVE_USLEEP=1 \ diff --git a/tool/warnings-clang.sh b/tool/warnings-clang.sh index 51084f31a6..b0d2fb6d10 100644 --- a/tool/warnings-clang.sh +++ b/tool/warnings-clang.sh @@ -9,5 +9,6 @@ echo '************* FTS4 and RTREE ****************' scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:' echo '********** ENABLE_STAT3. THREADSAFE=0 *******' -scan-build gcc -c -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \ - -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:' +scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \ + -DSQLITE_DEBUG \ + sqlite3.c ../sqlite/src/shell.c -ldl 2>&1 | grep -v 'ANALYZE:' From a2acb0d769f23bb24d742581c32c4c2f19f3e827 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Apr 2012 23:22:37 +0000 Subject: [PATCH 27/32] Add a testcase() macro to ensure that the sqlite3AuthCheck() call inside the query flattener really is effective. FossilOrigin-Name: a134e6e739cbb27701b092b33033244feb164cdf --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 1b588d1a98..01daad2dde 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\sstatic-analysis\swarnings,\smosting\shaving\sto\sdo\swith\smemory\nleaks\sin\sthe\scommand-line\sshell.\s\sAdd\sa\sclang\sanalysis\sof\sthe\scommand-line\nshell\sto\sthe\s"warnings-clang.sh"\sscript.\s\sOther\sminor\scleanups\sto\sthe\ncommand-line\sshell\scode. -D 2012-04-11T11:38:53.434 +C Add\sa\stestcase()\smacro\sto\sensure\sthat\sthe\ssqlite3AuthCheck()\scall\sinside\nthe\squery\sflattener\sreally\sis\seffective. +D 2012-04-11T23:22:37.290 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -181,7 +181,7 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 -F src/select.c 5e0e481c7d215d3c7ca8ccae1e688aa30163c6c1 +F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 F src/shell.c 6fef5d2cd1eccd0a692d5d458897d815afaea908 F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 2fa9f54309aea9927fb3695a986febd4963df7d1 -R fcc323db955b3488f04a596dcdc692dc +P 93a0f452a7023898ad3d62ee81b39a80477c332f +R e9fd1d5d0b8f93fe215615b822bcbcda U drh -Z 36fed4c702c105f246b456f165a799df +Z 0df74aef7de935c06b3b8d7464efe846 diff --git a/manifest.uuid b/manifest.uuid index 083955ca72..96270ea3b2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93a0f452a7023898ad3d62ee81b39a80477c332f \ No newline at end of file +a134e6e739cbb27701b092b33033244feb164cdf \ No newline at end of file diff --git a/src/select.c b/src/select.c index b44220ebcf..835d9fd9cc 100644 --- a/src/select.c +++ b/src/select.c @@ -2851,7 +2851,8 @@ static int flattenSubquery( /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; - sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); + TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); + testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; /* If the sub-query is a compound SELECT statement, then (by restrictions From 2b32b9941da808792652ed8e52657e561d5caca5 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 14 Apr 2012 11:48:25 +0000 Subject: [PATCH 28/32] Fix a typo in a comment that is extracted for documentation. No changes to code. FossilOrigin-Name: e87371c5081ce28431a4c7ceaa81ff966a378c66 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 01daad2dde..1862c71eed 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stestcase()\smacro\sto\sensure\sthat\sthe\ssqlite3AuthCheck()\scall\sinside\nthe\squery\sflattener\sreally\sis\seffective. -D 2012-04-11T23:22:37.290 +C Fix\sa\stypo\sin\sa\scomment\sthat\sis\sextracted\sfor\sdocumentation.\s\sNo\schanges\sto\s\ncode. +D 2012-04-14T11:48:25.387 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -183,7 +183,7 @@ F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 F src/shell.c 6fef5d2cd1eccd0a692d5d458897d815afaea908 -F src/sqlite.h.in 11a883919b0baf4ffaa7550cfeef99be613ec2bf +F src/sqlite.h.in 4338f299fc83dada8407358d585c0e240ecb76a3 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 93a0f452a7023898ad3d62ee81b39a80477c332f -R e9fd1d5d0b8f93fe215615b822bcbcda +P a134e6e739cbb27701b092b33033244feb164cdf +R dc8223e1fbe157a1af14143d14cea055 U drh -Z 0df74aef7de935c06b3b8d7464efe846 +Z e383e3414cd7f05936f8f4b15cd51898 diff --git a/manifest.uuid b/manifest.uuid index 96270ea3b2..af2bf1e737 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a134e6e739cbb27701b092b33033244feb164cdf \ No newline at end of file +e87371c5081ce28431a4c7ceaa81ff966a378c66 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 2f9c196860..d10ddaaa20 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1542,7 +1542,7 @@ struct sqlite3_mem_methods { ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] -**
SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE **
These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** From 5adc60bab065f318044ada7d4249f25a53e9cb9e Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 14 Apr 2012 13:25:11 +0000 Subject: [PATCH 29/32] In the unix VFS, always set every open file to close-on-exec using either O_CLOEXEC at open (preferred) or FD_CLOEXEC in an ioctl after opening. Before this changes, many files were done this way, but not all. FossilOrigin-Name: 9efbeb11ae0d480a13ff1353820c12f3a8bff452 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 28 +++++++++++++++------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index 1862c71eed..c13f55ba33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sa\scomment\sthat\sis\sextracted\sfor\sdocumentation.\s\sNo\schanges\sto\s\ncode. -D 2012-04-14T11:48:25.387 +C In\sthe\sunix\sVFS,\salways\sset\severy\sopen\sfile\sto\sclose-on-exec\susing\seither\nO_CLOEXEC\sat\sopen\s(preferred)\sor\sFD_CLOEXEC\sin\san\sioctl\safter\sopening.\s\sBefore\nthis\schanges,\smany\sfiles\swere\sdone\sthis\sway,\sbut\snot\sall. +D 2012-04-14T13:25:11.842 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c F src/os.h 59beba555b65a450bd1d804220532971d4299f60 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440 -F src/os_unix.c 75eff7b41cdc9f319eb0c610c19fd9bb37093e5d +F src/os_unix.c 424d46e0edab969293c2223f09923b2178171f47 F src/os_win.c 5e9e933a412ab35de2a6506b3c6a8295b31b309e F src/pager.c 85988507fa20acc60defb834722eddf4633e4aeb F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P a134e6e739cbb27701b092b33033244feb164cdf -R dc8223e1fbe157a1af14143d14cea055 +P e87371c5081ce28431a4c7ceaa81ff966a378c66 +R 7b4651c870902ae8ed7532d13f371f85 U drh -Z e383e3414cd7f05936f8f4b15cd51898 +Z 1af9fe4892fd87b77f8c0791d9bcac7c diff --git a/manifest.uuid b/manifest.uuid index af2bf1e737..33206a76f0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e87371c5081ce28431a4c7ceaa81ff966a378c66 \ No newline at end of file +9efbeb11ae0d480a13ff1353820c12f3a8bff452 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 559d156496..c85e9b53af 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -165,8 +165,8 @@ #endif /* - ** Default permissions when creating auto proxy dir - */ +** Default permissions when creating auto proxy dir +*/ #ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS # define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 #endif @@ -512,7 +512,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){ /* ** Invoke open(). Do so multiple times, until it either succeeds or -** files for some reason other than EINTR. +** fails for some reason other than EINTR. ** ** If the file creation mode "m" is 0 then set it to the default for ** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally @@ -528,7 +528,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){ ** recover the hot journals. */ static int robust_open(const char *z, int f, mode_t m){ - int rc; + int fd; mode_t m2; mode_t origM = 0; if( m==0 ){ @@ -537,11 +537,20 @@ static int robust_open(const char *z, int f, mode_t m){ m2 = m; origM = osUmask(0); } - do{ rc = osOpen(z,f,m2); }while( rc<0 && errno==EINTR ); + do{ +#if defined(O_CLOEXEC) + fd = osOpen(z,f|O_CLOEXEC,m2); +#else + fd = osOpen(z,f,m2); +#endif + }while( fd<0 && errno==EINTR ); if( m ){ osUmask(origM); } - return rc; +#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) + if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + return fd; } /* @@ -3336,9 +3345,6 @@ static int openDirectory(const char *zFilename, int *pFd){ zDirname[ii] = '\0'; fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); if( fd>=0 ){ -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); } } @@ -5183,10 +5189,6 @@ static int unixOpen( } #endif -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif - noLock = eType!=SQLITE_OPEN_MAIN_DB; From 8c5058bbdb96a4e9a0392011ad0aa279d1a32e8b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 16 Apr 2012 17:22:30 +0000 Subject: [PATCH 30/32] Fix a bug in the command-line shell logic that attempts to continue with a ".dump" even after encountering database corruption. FossilOrigin-Name: 020b5e90f950a42299074ff770612b9e68850d95 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c13f55ba33..dd970aa637 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sunix\sVFS,\salways\sset\severy\sopen\sfile\sto\sclose-on-exec\susing\seither\nO_CLOEXEC\sat\sopen\s(preferred)\sor\sFD_CLOEXEC\sin\san\sioctl\safter\sopening.\s\sBefore\nthis\schanges,\smany\sfiles\swere\sdone\sthis\sway,\sbut\snot\sall. -D 2012-04-14T13:25:11.842 +C Fix\sa\sbug\sin\sthe\scommand-line\sshell\slogic\sthat\sattempts\sto\scontinue\swith\sa\n".dump"\seven\safter\sencountering\sdatabase\scorruption. +D 2012-04-16T17:22:30.904 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 -F src/shell.c 6fef5d2cd1eccd0a692d5d458897d815afaea908 +F src/shell.c 5d2484bea27d1fb8a733077c436482a06c1d30f2 F src/sqlite.h.in 4338f299fc83dada8407358d585c0e240ecb76a3 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P e87371c5081ce28431a4c7ceaa81ff966a378c66 -R 7b4651c870902ae8ed7532d13f371f85 +P 9efbeb11ae0d480a13ff1353820c12f3a8bff452 +R 8554990f6e5abd69d8539d60c8a20e9c U drh -Z 1af9fe4892fd87b77f8c0791d9bcac7c +Z 6fed7a84ff8fa569c38ca78c5c084864 diff --git a/manifest.uuid b/manifest.uuid index 33206a76f0..09a6bb90fb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9efbeb11ae0d480a13ff1353820c12f3a8bff452 \ No newline at end of file +020b5e90f950a42299074ff770612b9e68850d95 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index e5cfec70a8..b4c21ad38b 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1369,7 +1369,7 @@ static int run_schema_dump_query( } zQ2 = malloc( len+100 ); if( zQ2==0 ) return rc; - sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery); + sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); if( rc ){ fprintf(p->out, "/****** ERROR: %s ******/\n", zErr); From d8621b90c9caa7d7e1970e98b0c6992d414706a7 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 17 Apr 2012 09:09:33 +0000 Subject: [PATCH 31/32] Add an undocumented and possibly ephemeral ".breakpoint" command to the command-line shell, to call a no-op routine on which it is convenient to set a symbolic debugger breakpoint. FossilOrigin-Name: 8e2363ad76446e863d03ead91fd621e59d5cb495 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index dd970aa637..5d4be74e07 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\scommand-line\sshell\slogic\sthat\sattempts\sto\scontinue\swith\sa\n".dump"\seven\safter\sencountering\sdatabase\scorruption. -D 2012-04-16T17:22:30.904 +C Add\san\sundocumented\sand\spossibly\sephemeral\s".breakpoint"\scommand\sto\sthe\s\ncommand-line\sshell,\sto\scall\sa\sno-op\sroutine\son\swhich\sit\sis\sconvenient\sto\s\nset\sa\ssymbolic\sdebugger\sbreakpoint. +D 2012-04-17T09:09:33.765 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -182,7 +182,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 969ec2bc52db1b068054ecf5ddc74f244102a71d F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1 F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 -F src/shell.c 5d2484bea27d1fb8a733077c436482a06c1d30f2 +F src/shell.c 11185a9a4574f363bd4268a2780d37480ae00040 F src/sqlite.h.in 4338f299fc83dada8407358d585c0e240ecb76a3 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 9efbeb11ae0d480a13ff1353820c12f3a8bff452 -R 8554990f6e5abd69d8539d60c8a20e9c +P 020b5e90f950a42299074ff770612b9e68850d95 +R b1350dfbc2eb46aaca5347bd8a799d07 U drh -Z 6fed7a84ff8fa569c38ca78c5c084864 +Z ed107cd283f4ba98c58e464c44f875e3 diff --git a/manifest.uuid b/manifest.uuid index 09a6bb90fb..849339b16d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -020b5e90f950a42299074ff770612b9e68850d95 \ No newline at end of file +8e2363ad76446e863d03ead91fd621e59d5cb495 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index b4c21ad38b..2607e680de 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1562,6 +1562,15 @@ static void sql_trace_callback(void *pArg, const char *z){ if( f ) fprintf(f, "%s\n", z); } +/* +** A no-op routine that runs with the ".breakpoint" doc-command. This is +** a useful spot to set a debugger breakpoint. +*/ +static void test_breakpoint(void){ + static int nCall = 0; + nCall++; +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -1641,6 +1650,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){ bail_on_error = booleanValue(azArg[1]); }else + /* The undocumented ".breakpoint" command causes a call to the no-op + ** routine named test_breakpoint(). + */ + if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ + test_breakpoint(); + }else + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; From 374fdce485ab55739dfd307ac00a59ebe8ce8d25 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 17 Apr 2012 16:38:53 +0000 Subject: [PATCH 32/32] Improved handling of aggregate subqueries within an aggregate query. FossilOrigin-Name: 430bb59d798286a86c351de92c429345f016b3f0 --- manifest | 16 +++++++------- manifest.uuid | 2 +- src/expr.c | 52 ++++++++++++++++++++++++++++++++++------------ src/sqliteInt.h | 2 +- test/subquery.test | 47 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 5d4be74e07..75fe99adec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sundocumented\sand\spossibly\sephemeral\s".breakpoint"\scommand\sto\sthe\s\ncommand-line\sshell,\sto\scall\sa\sno-op\sroutine\son\swhich\sit\sis\sconvenient\sto\s\nset\sa\ssymbolic\sdebugger\sbreakpoint. -D 2012-04-17T09:09:33.765 +C Improved\shandling\sof\saggregate\ssubqueries\swithin\san\saggregate\squery. +D 2012-04-17T16:38:53.916 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -135,7 +135,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e -F src/expr.c ebb0e2b21379d4ec0c5c2c7c952784cb300c8436 +F src/expr.c 1b2383adc4391ddae38abb71fd4690a3af8efb01 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6 @@ -185,7 +185,7 @@ F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335 F src/shell.c 11185a9a4574f363bd4268a2780d37480ae00040 F src/sqlite.h.in 4338f299fc83dada8407358d585c0e240ecb76a3 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 -F src/sqliteInt.h ce7d8404f15db6cbe73cf196d3d6198aaa4e3924 +F src/sqliteInt.h c5e917c4f1453f3972b1fd0c81105dfe4f09cc32 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -713,7 +713,7 @@ F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 -F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796 +F test/subquery.test c5e0d183f1ae6251453338a465b32ae11326e0fa F test/subquery2.test edcad5c118f0531c2e21bf16a09bbb105252d4cd F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a @@ -1000,7 +1000,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 020b5e90f950a42299074ff770612b9e68850d95 -R b1350dfbc2eb46aaca5347bd8a799d07 +P 8e2363ad76446e863d03ead91fd621e59d5cb495 +R f4f12ce6163c2f6bb1a71deb9cb7039c U drh -Z ed107cd283f4ba98c58e464c44f875e3 +Z 58b2a5ebe7a572f77bef677b95126ab0 diff --git a/manifest.uuid b/manifest.uuid index 849339b16d..59d3d01d77 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e2363ad76446e863d03ead91fd621e59d5cb495 \ No newline at end of file +430bb59d798286a86c351de92c429345f016b3f0 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4751ec91bd..328de4e5ea 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3778,7 +3778,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } - }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ + }else if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 2; @@ -3815,6 +3815,41 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){ return 0; } +/* +** This is the expression callback for sqlite3FunctionUsesOtherSrc(). +** +** Determine if an expression references any table other than one of the +** tables in pWalker->u.pSrcList and abort if it does. +*/ +static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ + int i; + SrcList *pSrc = pWalker->u.pSrcList; + for(i=0; inSrc; i++){ + if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue; + } + return WRC_Abort; + }else{ + return WRC_Continue; + } +} + +/* +** Determine if any of the arguments to the pExpr Function references +** any SrcList other than pSrcList. Return true if they do. Return +** false if pExpr has no argument or has only constant arguments or +** only references tables named in pSrcList. +*/ +static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){ + Walker w; + assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); + w.xExprCallback = exprUsesOtherSrc; + w.u.pSrcList = pSrcList; + if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1; + return 0; +} + /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. @@ -3930,9 +3965,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } case TK_AGG_FUNCTION: { - /* The pNC->nDepth==0 test causes aggregate functions in subqueries - ** to be ignored */ - if( pNC->nDepth==0 ){ + if( !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ @@ -3976,15 +4009,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ - NameContext *pNC = pWalker->u.pNC; - if( pNC->nDepth==0 ){ - pNC->nDepth++; - sqlite3WalkSelect(pWalker, pSelect); - pNC->nDepth--; - return WRC_Prune; - }else{ - return WRC_Continue; - } + return WRC_Continue; } /* @@ -3997,6 +4022,7 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ */ void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; + memset(&w, 0, sizeof(w)); w.xExprCallback = analyzeAggregate; w.xSelectCallback = analyzeAggregatesInSelect; w.u.pNC = pNC; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ccffe09c2e..cb178ff97c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2011,7 +2011,6 @@ struct NameContext { u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; /* True if aggregates are seen */ u8 isCheck; /* True if resolving names in a CHECK constraint */ - int nDepth; /* Depth of subquery recursion. 1 for no recursion */ AggInfo *pAggInfo; /* Information about aggregates at this level */ NameContext *pNext; /* Next outer name context. NULL for outermost */ }; @@ -2477,6 +2476,7 @@ struct Walker { union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ + SrcList *pSrcList; /* FROM clause */ } u; }; diff --git a/test/subquery.test b/test/subquery.test index 169cedace6..0010e45ff8 100644 --- a/test/subquery.test +++ b/test/subquery.test @@ -331,6 +331,53 @@ do_test subquery-3.3.5 { } } {1 1 2 1} +# The following tests check for aggregate subqueries in an aggregate +# query. +# +do_test subquery-3.4.1 { + execsql { + CREATE TABLE t34(x,y); + INSERT INTO t34 VALUES(106,4), (107,3), (106,5), (107,5); + SELECT a.x, avg(a.y) + FROM t34 AS a + GROUP BY a.x + HAVING NOT EXISTS( SELECT b.x, avg(b.y) + FROM t34 AS b + GROUP BY b.x + HAVING avg(a.y) > avg(b.y)); + } +} {107 4.0} +do_test subquery-3.4.2 { + execsql { + SELECT a.x, avg(a.y) AS avg1 + FROM t34 AS a + GROUP BY a.x + HAVING NOT EXISTS( SELECT b.x, avg(b.y) AS avg2 + FROM t34 AS b + GROUP BY b.x + HAVING avg1 > avg2); + } +} {107 4.0} +do_test subquery-3.4.3 { + execsql { + SELECT + a.x, + avg(a.y), + NOT EXISTS ( SELECT b.x, avg(b.y) + FROM t34 AS b + GROUP BY b.x + HAVING avg(a.y) > avg(b.y)), + EXISTS ( SELECT c.x, avg(c.y) + FROM t34 AS c + GROUP BY c.x + HAVING avg(a.y) > avg(c.y)) + FROM t34 AS a + GROUP BY a.x + ORDER BY a.x; + } +} {106 4.5 0 1 107 4.0 1 0} + + #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been