From 76226dd28d79a19d9b942931866390dec6937179 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 Sep 2015 17:38:01 +0000 Subject: [PATCH 01/29] Fix over-length source code lines in where.c. No logic changes. FossilOrigin-Name: 1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 54da3e3420..cb00afceb9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Strengthen\sthe\simplementations\sof\sxShmMemoryBarrier\son\sboth\sthe\sunix\sand\nwindows\sVFSes,\sso\sthat\sthey\slikely\swork\seven\sif\sSQLITE_THREADSAFE=0\sis\sused. -D 2015-09-24T12:40:43.573 +C Fix\sover-length\ssource\scode\slines\sin\swhere.c.\s\sNo\slogic\schanges. +D 2015-09-24T17:38:01.215 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c d5eed2584542e7f3bc78ddef7809a9d76d14d811 +F src/where.c 6f7156dc7285c4ff4f625e4f4fee57a83f25f89c F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c2fcb03299f2872d7f97a540ea145519f8b2e5cc -R 48a05a5fcfc27e989d0482f8603455ad +P c6ab807b72ddfc1462f61aa91442b6fac04ace8a +R 2adfc3245dccf622041366bbd2c07bc2 U drh -Z 5529d899992d962be9e3269522b69c12 +Z 1d5bb04c383d0f49d84249f8afd90c66 diff --git a/manifest.uuid b/manifest.uuid index 8b729d0105..90d457ac4d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6ab807b72ddfc1462f61aa91442b6fac04ace8a \ No newline at end of file +1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 1e13cf0ed0..c99306fa46 100644 --- a/src/where.c +++ b/src/where.c @@ -188,7 +188,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn && (iColumn!=(-2) - || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) + || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 @@ -2580,7 +2580,7 @@ static int whereLoopAddBtree( && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ - && HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */ + && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ ){ From dae26fe518c65f26e7d256a161acfe37910f897e Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 Sep 2015 18:47:59 +0000 Subject: [PATCH 02/29] Enhance the query planner so that it is able to use indexed expressions to help fulfill an ORDER BY clause. FossilOrigin-Name: 668fc1ebaf426f9eed3ed7865e41f1023dafebfb --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 23 ++++++++++++++++++----- test/indexexpr1.test | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index cb00afceb9..e5079a39f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sover-length\ssource\scode\slines\sin\swhere.c.\s\sNo\slogic\schanges. -D 2015-09-24T17:38:01.215 +C Enhance\sthe\squery\splanner\sso\sthat\sit\sis\sable\sto\suse\sindexed\sexpressions\nto\shelp\sfulfill\san\sORDER\sBY\sclause. +D 2015-09-24T18:47:59.761 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c 6f7156dc7285c4ff4f625e4f4fee57a83f25f89c +F src/where.c 278073aabce8d2020d30dff2edb6fe9430e1762c F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -785,7 +785,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985 -F test/indexexpr1.test 203c83a05accf6f2b748834192f3564321b8c0d8 +F test/indexexpr1.test 4bce4e4b6b1a2d0c34e17d4e04f3957a3bcdc500 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c6ab807b72ddfc1462f61aa91442b6fac04ace8a -R 2adfc3245dccf622041366bbd2c07bc2 +P 1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 +R 292146e62fe1cf1653fb27c4bd570968 U drh -Z 1d5bb04c383d0f49d84249f8afd90c66 +Z 3832f12930eca538f34541b12960504f diff --git a/manifest.uuid b/manifest.uuid index 90d457ac4d..8bdf819c4f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 \ No newline at end of file +668fc1ebaf426f9eed3ed7865e41f1023dafebfb \ No newline at end of file diff --git a/src/where.c b/src/where.c index c99306fa46..e6c7728c3a 100644 --- a/src/where.c +++ b/src/where.c @@ -2421,18 +2421,25 @@ static int indexMightHelpWithOrderBy( int iCursor ){ ExprList *pOB; + ExprList *aColExpr; int ii, jj; if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); - if( pExpr->op!=TK_COLUMN ) return 0; - if( pExpr->iTable==iCursor ){ + if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; } + }else if( (aColExpr = pIndex->aColExpr)!=0 ){ + for(jj=0; jjnKeyCol; jj++){ + if( pIndex->aiColumn[jj]!=(-2) ) continue; + if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + return 1; + } + } } } return 0; @@ -3264,9 +3271,15 @@ static i8 wherePathSatisfiesOrderBy( testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; + if( iColumn>=(-1) ){ + if( pOBExpr->op!=TK_COLUMN ) continue; + if( pOBExpr->iTable!=iCur ) continue; + if( pOBExpr->iColumn!=iColumn ) continue; + }else{ + if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ + continue; + } + } if( iColumn>=0 ){ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; diff --git a/test/indexexpr1.test b/test/indexexpr1.test index 1945059f2b..e18cbd8d38 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -88,6 +88,23 @@ do_execsql_test indexexpr1-160eqp { WHERE substr(a,27,3)=='ord' AND d>=29; } {/USING INDEX t1a2/} +# ORDER BY using an indexed expression +# +do_execsql_test indexexpr1-170 { + CREATE INDEX t1alen ON t1(length(a)); + SELECT length(a) FROM t1 ORDER BY length(a); +} {20 25 27 29 38 52} +do_execsql_test indexexpr1-170eqp { + EXPLAIN QUERY PLAN + SELECT length(a) FROM t1 ORDER BY length(a); +} {/SCAN TABLE t1 USING INDEX t1alen/} +do_execsql_test indexexpr1-171 { + SELECT length(a) FROM t1 ORDER BY length(a) DESC; +} {52 38 29 27 25 20} +do_execsql_test indexexpr1-171eqp { + EXPLAIN QUERY PLAN + SELECT length(a) FROM t1 ORDER BY length(a) DESC; +} {/SCAN TABLE t1 USING INDEX t1alen/} do_execsql_test indexexpr1-200 { DROP TABLE t1; @@ -255,4 +272,24 @@ do_execsql_test indexexpr1-710 { ORDER BY +a, +x; } {1 1 | 2 2 |} +# Collating sequences on indexes of expressions +# +do_execsql_test indexexpr1-800 { + DROP TABLE IF EXISTS t8; + CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT); + CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE nocase); + INSERT INTO t8(a,b) VALUES(1,'Alice'),(2,'Bartholemew'),(3,'Cynthia'); + SELECT * FROM t8 WHERE substr(b,2,4)='ARTH' COLLATE nocase; +} {2 Bartholemew} +do_catchsql_test indexexpr1-810 { + INSERT INTO t8(a,b) VALUES(4,'BARTHMERE'); +} {1 {UNIQUE constraint failed: index 't8bx'}} +do_catchsql_test indexexpr1-820 { + DROP INDEX t8bx; + CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE rtrim); + INSERT INTO t8(a,b) VALUES(4,'BARTHMERE'); +} {0 {}} + + + finish_test From 8ffddeb7087fa263cb794244b6e6edce859e3319 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Sep 2015 01:09:27 +0000 Subject: [PATCH 03/29] Fix a problem computing affinities for indexes during skip-scan code generation when SQLITE_ENABLE_STAT4 is on. Bug introduced by check-in [1ee089a72d789002]. FossilOrigin-Name: 1350dd42d056508337b1a07ad8b1c9c97593f8d3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index e5079a39f3..e86f6aafd2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\squery\splanner\sso\sthat\sit\sis\sable\sto\suse\sindexed\sexpressions\nto\shelp\sfulfill\san\sORDER\sBY\sclause. -D 2015-09-24T18:47:59.761 +C Fix\sa\sproblem\scomputing\saffinities\sfor\sindexes\sduring\sskip-scan\scode\s\ngeneration\swhen\sSQLITE_ENABLE_STAT4\sis\son.\s\sBug\sintroduced\sby\ncheck-in\s[1ee089a72d789002]. +D 2015-09-25T01:09:27.582 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c 278073aabce8d2020d30dff2edb6fe9430e1762c +F src/where.c a7582b752d436d335bfb62f445e1c2771e7daa95 F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1c8c5380a8b45c9e04d9663c3cb8182ef3a61b81 -R 292146e62fe1cf1653fb27c4bd570968 +P 668fc1ebaf426f9eed3ed7865e41f1023dafebfb +R e89f89bb659102a73737ed43d8a4eae7 U drh -Z 3832f12930eca538f34541b12960504f +Z 28a6620004b61f128b9c9ee72c986f80 diff --git a/manifest.uuid b/manifest.uuid index 8bdf819c4f..1fe02891b6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -668fc1ebaf426f9eed3ed7865e41f1023dafebfb \ No newline at end of file +1350dd42d056508337b1a07ad8b1c9c97593f8d3 \ No newline at end of file diff --git a/src/where.c b/src/where.c index e6c7728c3a..6578900c10 100644 --- a/src/where.c +++ b/src/where.c @@ -1159,6 +1159,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ ** Return the affinity for a single column of an index. */ static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ + assert( iCol>=0 && iColnColumn ); if( !pIdx->zColAff ){ if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; } @@ -1216,8 +1217,7 @@ static int whereRangeSkipScanEst( int nLower = -1; int nUpper = p->nSample+1; int rc = SQLITE_OK; - int iCol = p->aiColumn[nEq]; - u8 aff = sqlite3IndexColumnAffinity(db, p, iCol); + u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); CollSeq *pColl; sqlite3_value *p1 = 0; /* Value extracted from pLower */ From 2679f14fd942cb103e52bf9141ec73e427dc63b0 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Sep 2015 13:42:55 +0000 Subject: [PATCH 04/29] Report an error if the number of named columns in a VIEW is different from the number of result columns in the SELECT statement that implements the VIEW. FossilOrigin-Name: 6e4ac0be2de1a16fcbb2a314504122ad95aa257e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 10 ++++++++++ test/view.test | 10 ++++++++++ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index e86f6aafd2..e784e63e3f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\scomputing\saffinities\sfor\sindexes\sduring\sskip-scan\scode\s\ngeneration\swhen\sSQLITE_ENABLE_STAT4\sis\son.\s\sBug\sintroduced\sby\ncheck-in\s[1ee089a72d789002]. -D 2015-09-25T01:09:27.582 +C Report\san\serror\sif\sthe\snumber\sof\snamed\scolumns\sin\sa\sVIEW\sis\sdifferent\nfrom\sthe\snumber\sof\sresult\scolumns\sin\sthe\sSELECT\sstatement\sthat\simplements\nthe\sVIEW. +D 2015-09-25T13:42:55.978 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -340,7 +340,7 @@ F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 36ee14d729e182cd8b6796f980b7ab3fc9bcee72 +F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42 F src/sqlite.h.in 4e06cb5fed36736242c66237991db6f3e2395eb9 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -1248,7 +1248,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test 3930ae94042d702ab15a6a0ef692cfa5c9f9b68b +F test/view.test bfdec45ad4b2ed5dd5fddbc3dcafcfca2ab23574 F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 668fc1ebaf426f9eed3ed7865e41f1023dafebfb -R e89f89bb659102a73737ed43d8a4eae7 +P 1350dd42d056508337b1a07ad8b1c9c97593f8d3 +R 9672ebd00531833a09889a78098f4f34 U drh -Z 28a6620004b61f128b9c9ee72c986f80 +Z 160c60a319774154e17ae3a2bf9d8f26 diff --git a/manifest.uuid b/manifest.uuid index 1fe02891b6..aaf3eedcfb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1350dd42d056508337b1a07ad8b1c9c97593f8d3 \ No newline at end of file +6e4ac0be2de1a16fcbb2a314504122ad95aa257e \ No newline at end of file diff --git a/src/select.c b/src/select.c index a4aaa0ecaf..f410a3b329 100644 --- a/src/select.c +++ b/src/select.c @@ -4861,7 +4861,17 @@ int sqlite3Select( struct SrcList_item *pItem = &pTabList->a[i]; Select *pSub = pItem->pSelect; int isAggSub; + Table *pTab = pItem->pTab; if( pSub==0 ) continue; + + /* Catch mismatch in the declared columns of a view and the number of + ** columns in the SELECT on the RHS */ + if( pTab->nCol!=pSub->pEList->nExpr ){ + sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", + pTab->nCol, pTab->zName, pSub->pEList->nExpr); + goto select_end; + } + isAggSub = (pSub->selFlags & SF_Aggregate)!=0; if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ /* This subquery can be absorbed into its parent. */ diff --git a/test/view.test b/test/view.test index b39487689c..891dde6579 100644 --- a/test/view.test +++ b/test/view.test @@ -161,6 +161,16 @@ do_test view-3.3.3 { do_catchsql_test view-3.3.4 { CREATE VIEW v1err(x,y DESC,z) AS SELECT a, b+c, c-b FROM t1; } {1 {syntax error after column name "y"}} +do_catchsql_test view-3.3.5 { + DROP VIEW IF EXISTS v1err; + CREATE VIEW v1err(x,y) AS SELECT a, b+c, c-b FROM t1; + SELECT * FROM v1err; +} {1 {expected 2 columns for 'v1err' but got 3}} +do_catchsql_test view-3.3.6 { + DROP VIEW IF EXISTS v1err; + CREATE VIEW v1err(w,x,y,z) AS SELECT a, b+c, c-b FROM t1; + SELECT * FROM v1err; +} {1 {expected 4 columns for 'v1err' but got 3}} ifcapable compound { do_test view-3.4 { From 68391acd5f11ec64e74eca419ec8088f26c03c5c Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Sep 2015 20:49:16 +0000 Subject: [PATCH 05/29] Fix PRAGMA integrity_check so that it works with a UNIQUE index over expressions. FossilOrigin-Name: 113181cec4db418b07640d6b1967923992efd71a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pragma.c | 4 ++-- test/indexexpr1.test | 18 +++++++++++++++++- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index e784e63e3f..c2494e6384 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Report\san\serror\sif\sthe\snumber\sof\snamed\scolumns\sin\sa\sVIEW\sis\sdifferent\nfrom\sthe\snumber\sof\sresult\scolumns\sin\sthe\sSELECT\sstatement\sthat\simplements\nthe\sVIEW. -D 2015-09-25T13:42:55.978 +C Fix\sPRAGMA\sintegrity_check\sso\sthat\sit\sworks\swith\sa\sUNIQUE\sindex\sover\nexpressions. +D 2015-09-25T20:49:16.032 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -333,7 +333,7 @@ F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083 -F src/pragma.c d71b813e67bf03f3116b9dd5164fbfd81ec673a2 +F src/pragma.c 577f70c3899ee6fc2e5a4c37158c69c1c23f71e7 F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a @@ -785,7 +785,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985 -F test/indexexpr1.test 4bce4e4b6b1a2d0c34e17d4e04f3957a3bcdc500 +F test/indexexpr1.test bbb52b5d5717d9f23853826963b0af5110009366 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1350dd42d056508337b1a07ad8b1c9c97593f8d3 -R 9672ebd00531833a09889a78098f4f34 +P 6e4ac0be2de1a16fcbb2a314504122ad95aa257e +R ddf8c16716e71dc2258fab1042b22895 U drh -Z 160c60a319774154e17ae3a2bf9d8f26 +Z 58a6b6e5eae00c6fe24fb1e13719f1e4 diff --git a/manifest.uuid b/manifest.uuid index aaf3eedcfb..4cdda680b1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6e4ac0be2de1a16fcbb2a314504122ad95aa257e \ No newline at end of file +113181cec4db418b07640d6b1967923992efd71a \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 2dcad614f1..1edc66daf8 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1524,8 +1524,8 @@ void sqlite3Pragma( int kk; for(kk=0; kknKeyCol; kk++){ int iCol = pIdx->aiColumn[kk]; - assert( iCol>=0 && iColnCol ); - if( pTab->aCol[iCol].notNull ) continue; + assert( iCol!=(-1) && iColnCol ); + if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); VdbeCoverage(v); } diff --git a/test/indexexpr1.test b/test/indexexpr1.test index e18cbd8d38..89bea1877f 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -210,7 +210,8 @@ do_execsql_test indexexpr1-400 { SELECT x, printf('ab%04xyz',x), random() FROM c; CREATE UNIQUE INDEX t3abc ON t3(CAST(a AS text), b, substr(c,1,3)); SELECT a FROM t3 WHERE CAST(a AS text)<='10' ORDER BY +a; -} {1 10} + PRAGMA integrity_check; +} {1 10 ok} do_catchsql_test indexexpr1-410 { INSERT INTO t3 SELECT * FROM t3 WHERE rowid=10; } {1 {UNIQUE constraint failed: index 't3abc'}} @@ -290,6 +291,21 @@ do_catchsql_test indexexpr1-820 { INSERT INTO t8(a,b) VALUES(4,'BARTHMERE'); } {0 {}} +# Check that PRAGMA integrity_check works correctly on a +# UNIQUE index that includes rowid and expression terms. +# +do_execsql_test indexexpr1-900 { + CREATE TABLE t9(a,b,c,d); + CREATE UNIQUE INDEX t9x1 ON t9(c,abs(d),b); + INSERT INTO t9(rowid,a,b,c,d) VALUES(1,2,3,4,5); + INSERT INTO t9(rowid,a,b,c,d) VALUES(2,NULL,NULL,NULL,NULL); + INSERT INTO t9(rowid,a,b,c,d) VALUES(3,NULL,NULL,NULL,NULL); + INSERT INTO t9(rowid,a,b,c,d) VALUES(4,5,6,7,8); + PRAGMA integrity_check; +} {ok} +do_catchsql_test indexexpr1-910 { + INSERT INTO t9(a,b,c,d) VALUES(5,6,7,-8); +} {1 {UNIQUE constraint failed: index 't9x1'}} finish_test From 2ea31b1286adb309baad799e5e82a2d28071d785 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 25 Sep 2015 23:40:01 +0000 Subject: [PATCH 06/29] Fix threads.c so that setting sqlite3FaultSim(200) using the SQLITE_TESTCTRL_FAULT_INSTALL callback causes both unix and windows worker threads to be sequential and deterministic, so that they can be tested reliably. FossilOrigin-Name: 2d867c054d6d3e1e841ba9ca524e986bc6993ac3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/threads.c | 11 ++++++++++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c2494e6384..2325407c95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sPRAGMA\sintegrity_check\sso\sthat\sit\sworks\swith\sa\sUNIQUE\sindex\sover\nexpressions. -D 2015-09-25T20:49:16.032 +C Fix\sthreads.c\sso\sthat\ssetting\ssqlite3FaultSim(200)\susing\sthe\nSQLITE_TESTCTRL_FAULT_INSTALL\scallback\scauses\sboth\sunix\sand\swindows\sworker\nthreads\sto\sbe\ssequential\sand\sdeterministic,\sso\sthat\sthey\scan\sbe\stested\nreliably. +D 2015-09-25T23:40:01.663 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -395,7 +395,7 @@ F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9 F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 -F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481 +F src/threads.c 87639bc293d470f50d48c370028511ad3e1ccfd5 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6e4ac0be2de1a16fcbb2a314504122ad95aa257e -R ddf8c16716e71dc2258fab1042b22895 +P 113181cec4db418b07640d6b1967923992efd71a +R c9cd2c770b7c10173d40a9ea442ad6dd U drh -Z 58a6b6e5eae00c6fe24fb1e13719f1e4 +Z 0fbda38735b1950a4a02ae04b92eb3a5 diff --git a/manifest.uuid b/manifest.uuid index 4cdda680b1..906e367c5d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -113181cec4db418b07640d6b1967923992efd71a \ No newline at end of file +2d867c054d6d3e1e841ba9ca524e986bc6993ac3 \ No newline at end of file diff --git a/src/threads.c b/src/threads.c index 4ce6122274..8ed2b42611 100644 --- a/src/threads.c +++ b/src/threads.c @@ -67,6 +67,10 @@ int sqlite3ThreadCreate( memset(p, 0, sizeof(*p)); p->xTask = xTask; p->pIn = pIn; + /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a + ** function that returns SQLITE_ERROR when passed the argument 200, that + ** forces worker threads to run sequentially and deterministically + ** for testing purposes. */ if( sqlite3FaultSim(200) ){ rc = 1; }else{ @@ -151,7 +155,12 @@ int sqlite3ThreadCreate( *ppThread = 0; p = sqlite3Malloc(sizeof(*p)); if( p==0 ) return SQLITE_NOMEM; - if( sqlite3GlobalConfig.bCoreMutex==0 ){ + /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a + ** function that returns SQLITE_ERROR when passed the argument 200, that + ** forces worker threads to run sequentially and deterministically + ** (via the sqlite3FaultSim() term of the conditional) for testing + ** purposes. */ + if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){ memset(p, 0, sizeof(*p)); }else{ p->xTask = xTask; From 17db155fed685c0c1d3c438c3e0e02851722e83f Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Sep 2015 01:28:46 +0000 Subject: [PATCH 07/29] Remove an assert in the windows worker-thread logic that can fail in a race condition. FossilOrigin-Name: d7bfb96092a6b812af194f32b22283a0f6a7da96 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/threads.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 2325407c95..60536e3e34 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthreads.c\sso\sthat\ssetting\ssqlite3FaultSim(200)\susing\sthe\nSQLITE_TESTCTRL_FAULT_INSTALL\scallback\scauses\sboth\sunix\sand\swindows\sworker\nthreads\sto\sbe\ssequential\sand\sdeterministic,\sso\sthat\sthey\scan\sbe\stested\nreliably. -D 2015-09-25T23:40:01.663 +C Remove\san\sassert\sin\sthe\swindows\sworker-thread\slogic\sthat\scan\sfail\sin\sa\srace\ncondition. +D 2015-09-26T01:28:46.988 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -395,7 +395,7 @@ F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9 F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 -F src/threads.c 87639bc293d470f50d48c370028511ad3e1ccfd5 +F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 113181cec4db418b07640d6b1967923992efd71a -R c9cd2c770b7c10173d40a9ea442ad6dd +P 2d867c054d6d3e1e841ba9ca524e986bc6993ac3 +R 1758ec9357330b0579141ecae96a2702 U drh -Z 0fbda38735b1950a4a02ae04b92eb3a5 +Z da76e4bf593addae8cb1880d2dd70b45 diff --git a/manifest.uuid b/manifest.uuid index 906e367c5d..ba759293c9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2d867c054d6d3e1e841ba9ca524e986bc6993ac3 \ No newline at end of file +d7bfb96092a6b812af194f32b22283a0f6a7da96 \ No newline at end of file diff --git a/src/threads.c b/src/threads.c index 8ed2b42611..251b9b7631 100644 --- a/src/threads.c +++ b/src/threads.c @@ -188,7 +188,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ assert( ppOut!=0 ); if( NEVER(p==0) ) return SQLITE_NOMEM; if( p->xTask==0 ){ - assert( p->id==GetCurrentThreadId() ); + /* assert( p->id==GetCurrentThreadId() ); */ rc = WAIT_OBJECT_0; assert( p->tid==0 ); }else{ From 539482b76a3d005364d2668213b99d63f7521735 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Sep 2015 03:23:29 +0000 Subject: [PATCH 08/29] Expand the header comment to clarify the purpose for the sqlite3MemoryBarrier() function. FossilOrigin-Name: b89495ae09aa0e9652475b2ba1943dfd87c73e07 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/mutex_unix.c | 4 +++- src/mutex_w32.c | 4 +++- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 60536e3e34..e46cf93be8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sassert\sin\sthe\swindows\sworker-thread\slogic\sthat\scan\sfail\sin\sa\srace\ncondition. -D 2015-09-26T01:28:46.988 +C Expand\sthe\sheader\scomment\sto\sclarify\sthe\spurpose\sfor\sthe\nsqlite3MemoryBarrier()\sfunction. +D 2015-09-26T03:23:29.340 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -317,8 +317,8 @@ F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4 -F src/mutex_unix.c 8cfa6e83c618d2fcae0fe63f4d2b5bb16b11a97a -F src/mutex_w32.c 2e025e6642eaf27597403690980f560d1a91f62c +F src/mutex_unix.c a94b46f3f7beba307dde1b298b0f99f9c3677a93 +F src/mutex_w32.c b483d3e5914b84c82516a6a9919582f12ef3b838 F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2d867c054d6d3e1e841ba9ca524e986bc6993ac3 -R 1758ec9357330b0579141ecae96a2702 +P d7bfb96092a6b812af194f32b22283a0f6a7da96 +R 53a860536ab1d397fede465244d51351 U drh -Z da76e4bf593addae8cb1880d2dd70b45 +Z f65cf73c8cac5f871fc434c67cdccd1a diff --git a/manifest.uuid b/manifest.uuid index ba759293c9..eab8e97c0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7bfb96092a6b812af194f32b22283a0f6a7da96 \ No newline at end of file +b89495ae09aa0e9652475b2ba1943dfd87c73e07 \ No newline at end of file diff --git a/src/mutex_unix.c b/src/mutex_unix.c index cebb96c90e..dbdaa225b3 100644 --- a/src/mutex_unix.c +++ b/src/mutex_unix.c @@ -81,7 +81,9 @@ static int pthreadMutexNotheld(sqlite3_mutex *p){ #endif /* -** Try to provide a memory barrier operation, needed for initialization only. +** Try to provide a memory barrier operation, needed for initialization +** and also for the implementation of xShmBarrier in the VFS in cases +** where SQLite is compiled without mutexes. */ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) diff --git a/src/mutex_w32.c b/src/mutex_w32.c index 90be07db2d..7d28e4defc 100644 --- a/src/mutex_w32.c +++ b/src/mutex_w32.c @@ -78,7 +78,9 @@ static int winMutexNotheld(sqlite3_mutex *p){ #endif /* -** Try to provide a memory barrier operation, needed for initialization only. +** Try to provide a memory barrier operation, needed for initialization +** and also for the xShmBarrier method of the VFS in cases when SQLite is +** compiled without mutexes (SQLITE_THREADSAFE=0). */ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) From c4cdb29a0e4dd69f2f02e27765d723cc6e8700f6 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Sep 2015 03:31:47 +0000 Subject: [PATCH 09/29] Fix the title of the documentation on sqlite3_value_subtype(). This is a comment change only. FossilOrigin-Name: b79023542458f7e839469c5e313694f1e4cf223a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index e46cf93be8..c7255365d5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Expand\sthe\sheader\scomment\sto\sclarify\sthe\spurpose\sfor\sthe\nsqlite3MemoryBarrier()\sfunction. -D 2015-09-26T03:23:29.340 +C Fix\sthe\stitle\sof\sthe\sdocumentation\son\ssqlite3_value_subtype().\s\sThis\sis\sa\ncomment\schange\sonly. +D 2015-09-26T03:31:47.786 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -342,7 +342,7 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42 -F src/sqlite.h.in 4e06cb5fed36736242c66237991db6f3e2395eb9 +F src/sqlite.h.in 02f6ed7de3a96d10bd1e6e5803e4e4b786dff014 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d7bfb96092a6b812af194f32b22283a0f6a7da96 -R 53a860536ab1d397fede465244d51351 +P b89495ae09aa0e9652475b2ba1943dfd87c73e07 +R 61d90f8d030c1e925088df624cbea8dd U drh -Z f65cf73c8cac5f871fc434c67cdccd1a +Z c6f8608e2016c08a0ff2908d96bb63fd diff --git a/manifest.uuid b/manifest.uuid index eab8e97c0a..4489ececf5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b89495ae09aa0e9652475b2ba1943dfd87c73e07 \ No newline at end of file +b79023542458f7e839469c5e313694f1e4cf223a \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 45a11e3b9c..0f7d3a21bf 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -4360,7 +4360,7 @@ int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); /* -** CAPI3REF: Obtaining SQL Values +** CAPI3REF: Finding The Subtype Of SQL Values ** METHOD: sqlite3_value ** ** The sqlite3_value_subtype(V) function returns the subtype for From 32498f132160f70ed0a45fed751f4fdb9d54db34 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Sep 2015 11:15:44 +0000 Subject: [PATCH 10/29] Fix a memory leak that can occur following a syntax error in CREATE VIEW. FossilOrigin-Name: f4704035a6134f702c00110358e36f1579e2ea78 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 3 +-- test/view.test | 5 +++++ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c7255365d5..7a27708eba 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\stitle\sof\sthe\sdocumentation\son\ssqlite3_value_subtype().\s\sThis\sis\sa\ncomment\schange\sonly. -D 2015-09-26T03:31:47.786 +C Fix\sa\smemory\sleak\sthat\scan\soccur\sfollowing\sa\ssyntax\serror\sin\sCREATE\sVIEW. +D 2015-09-26T11:15:44.897 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -285,7 +285,7 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 -F src/build.c 8a86f4203ac8a9ac0734f242a96f043edffb6018 +F src/build.c edc5a29cd55257b05be837c3613e2cade02b3e03 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b @@ -1248,7 +1248,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test bfdec45ad4b2ed5dd5fddbc3dcafcfca2ab23574 +F test/view.test 0d8935e64867ae01492347884f5cbb47f056f4c8 F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b89495ae09aa0e9652475b2ba1943dfd87c73e07 -R 61d90f8d030c1e925088df624cbea8dd +P b79023542458f7e839469c5e313694f1e4cf223a +R 5bffdcb8f106214b20b1e8dd3d8300df U drh -Z c6f8608e2016c08a0ff2908d96bb63fd +Z 606c03f040a7d5d452758b762c64cca4 diff --git a/manifest.uuid b/manifest.uuid index 4489ececf5..1d3445431b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b79023542458f7e839469c5e313694f1e4cf223a \ No newline at end of file +f4704035a6134f702c00110358e36f1579e2ea78 \ No newline at end of file diff --git a/src/build.c b/src/build.c index eee62ee151..6a9c613165 100644 --- a/src/build.c +++ b/src/build.c @@ -2082,8 +2082,7 @@ void sqlite3CreateView( if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); - sqlite3SelectDelete(db, pSelect); - return; + goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; diff --git a/test/view.test b/test/view.test index 891dde6579..0b8354a38e 100644 --- a/test/view.test +++ b/test/view.test @@ -474,6 +474,11 @@ do_test view-12.1 { CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=? } } {1 {parameters are not allowed in views}} +do_test view-12.2 { + catchsql { + CREATE VIEW v12(x) AS SELECT a FROM t1 WHERE b=? + } +} {1 {parameters are not allowed in views}} ifcapable attach { do_test view-13.1 { From 2f20e13b83f1c7bb80c61043f8d233c72d2878c2 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 26 Sep 2015 17:44:59 +0000 Subject: [PATCH 11/29] Enable adding JSON1 by appending the json1.c source file to the amalgamation and compiling with -DSQLITE_ENABLE_JSON1 FossilOrigin-Name: 33404b2029120d4aabe1e25d484871810777e934 --- Makefile.in | 5 ++++- Makefile.msc | 4 ++-- ext/misc/json1.c | 29 +++++++++++++++++------------ main.mk | 5 ++++- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/main.c | 7 +++++++ src/shell.c | 2 +- 8 files changed, 47 insertions(+), 29 deletions(-) diff --git a/Makefile.in b/Makefile.in index 424d839750..5c78abde94 100644 --- a/Makefile.in +++ b/Makefile.in @@ -544,7 +544,7 @@ FUZZDATA = \ # Extra arguments for including json1 in the build of tools # JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h -JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE +JSON1_OPT = -DSQLITE_SHELL_JSON1 -DSQLITE_CORE JSON1_SRC = $(TOP)/ext/misc/json1.c # Standard options to testfixture @@ -625,6 +625,9 @@ sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl cp tsrc/shell.c tsrc/sqlite3ext.h . +sqlite3ext.h: .target_source + cp tsrc/sqlite3ext.h . + tclsqlite3.c: sqlite3.c echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c diff --git a/Makefile.msc b/Makefile.msc index 7e69589705..678b547fed 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -390,9 +390,9 @@ CORE_LINK_OPTS = /DEF:sqlite3.def # !IFNDEF SHELL_COMPILE_OPTS !IF $(DYNAMIC_SHELL)!=0 -SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) +SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) !ELSE -SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS) +SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) !ENDIF !ENDIF diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 89b70f0838..77857f5447 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1937,19 +1937,12 @@ static sqlite3_module jsonTreeModule = { #endif /* SQLITE_OMIT_VIRTUALTABLE */ /**************************************************************************** -** The following routine is the only publically visible identifier in this -** file. Call the following routine in order to register the various SQL +** The following routines are the only publically visible identifiers in this +** file. Call the following routines in order to register the various SQL ** functions and the virtual table implemented by this file. ****************************************************************************/ -#ifdef _WIN32 -__declspec(dllexport) -#endif -int sqlite3_json_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ +int sqlite3Json1Init(sqlite3 *db){ int rc = SQLITE_OK; unsigned int i; static const struct { @@ -1987,8 +1980,6 @@ int sqlite3_json_init( { "json_tree", &jsonTreeModule }, }; #endif - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ for(i=0; i>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c +sqlite3ext.h: target_source + cp tsrc/sqlite3ext.h . + sqlite3.c-debug: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c diff --git a/manifest b/manifest index 7a27708eba..02424b2039 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Fix\sa\smemory\sleak\sthat\scan\soccur\sfollowing\sa\ssyntax\serror\sin\sCREATE\sVIEW. -D 2015-09-26T11:15:44.897 +C Enable\sadding\sJSON1\sby\sappending\sthe\sjson1.c\ssource\sfile\sto\sthe\samalgamation\nand\scompiling\swith\s-DSQLITE_ENABLE_JSON1 +D 2015-09-26T17:44:59.245 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in e1afa6fb2de2bddd50e0ddae8166c2ee9d69b301 +F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc f090cdf036f3c07fb13aa2f4494e388c0b1ed1e4 +F Makefile.msc b9054642ab305be4174d8b0433c9951c2839701d F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION ccfc4d1576dbfdeece0a4372a2e6a2e37d3e7975 @@ -195,7 +195,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e -F ext/misc/json1.c 557d6b2d0c3d26625e686a4b4ef8d4a50b8cec94 +F ext/misc/json1.c 263cac0292302b7cf7ecb2e8bd698a50d1aedecc F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc @@ -261,7 +261,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk d12601118f1d1dadebe1329a53a6d5c512b36d44 +F main.mk 151fcaba704fdeeb0a1941857ef6e1d6216732d8 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -305,7 +305,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012 F src/loadext.c f0b66d28e377fd6c6d36cc9d92df1ff251ebee44 -F src/main.c e17fcffae4306a9b8334faf3bac80d7396850b54 +F src/main.c c80ea19ec71609ccbec21f334fbcf475bb6af2fc F src/malloc.c 3a37ce6979a40f499d8cea9e9ab4e8517854d35d F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987 @@ -341,7 +341,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a -F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42 +F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 F src/sqlite.h.in 02f6ed7de3a96d10bd1e6e5803e4e4b786dff014 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b79023542458f7e839469c5e313694f1e4cf223a -R 5bffdcb8f106214b20b1e8dd3d8300df +P f4704035a6134f702c00110358e36f1579e2ea78 +R 6dd9af66a4beb7d52dbecad30f413fd3 U drh -Z 606c03f040a7d5d452758b762c64cca4 +Z 2dae51b0464af5412711a65e5f2d84bb diff --git a/manifest.uuid b/manifest.uuid index 1d3445431b..f2175fce2e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f4704035a6134f702c00110358e36f1579e2ea78 \ No newline at end of file +33404b2029120d4aabe1e25d484871810777e934 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 575cad92c5..fa374c7012 100644 --- a/src/main.c +++ b/src/main.c @@ -2896,6 +2896,13 @@ static int openDatabase( } #endif +#ifdef SQLITE_ENABLE_JSON1 + if( !db->mallocFailed && rc==SQLITE_OK){ + extern int sqlite3Json1Init(sqlite3*); + rc = sqlite3Json1Init(db); + } +#endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. diff --git a/src/shell.c b/src/shell.c index e5eb394ead..02938eb1e6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -4619,7 +4619,7 @@ int SQLITE_CDECL main(int argc, char **argv){ } data.out = stdout; -#ifdef SQLITE_ENABLE_JSON1 +#ifdef SQLITE_SHELL_JSON1 { extern int sqlite3_json_init(sqlite3*); sqlite3_auto_extension((void(*)(void))sqlite3_json_init); From 63c85a7a6607809ea0461e48820f48c34cf0689b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 28 Sep 2015 14:40:20 +0000 Subject: [PATCH 12/29] Fix a database corruption bug caused by the ONEPASS optimization added in check-in [8b93cc5937000535]. Bug detected (prior to release) by [https://www.sqlite.org/sqllogictest|sqllogictest]. Test cases to follow. FossilOrigin-Name: 9d057f52217e7ef9c3f3eb84117abe3365503f44 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 02424b2039..fb761dcc80 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sadding\sJSON1\sby\sappending\sthe\sjson1.c\ssource\sfile\sto\sthe\samalgamation\nand\scompiling\swith\s-DSQLITE_ENABLE_JSON1 -D 2015-09-26T17:44:59.245 +C Fix\sa\sdatabase\scorruption\sbug\scaused\sby\sthe\sONEPASS\soptimization\sadded\nin\scheck-in\s[8b93cc5937000535].\s\sBug\sdetected\s(prior\sto\srelease)\sby\n[https://www.sqlite.org/sqllogictest|sqllogictest].\s\sTest\scases\sto\sfollow. +D 2015-09-28T14:40:20.768 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c a7582b752d436d335bfb62f445e1c2771e7daa95 +F src/where.c f2c4905e47fe80043a0c45f374f555615da365ba F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f4704035a6134f702c00110358e36f1579e2ea78 -R 6dd9af66a4beb7d52dbecad30f413fd3 +P 33404b2029120d4aabe1e25d484871810777e934 +R 221ece26a434b0c8583fbc9c4416f571 U drh -Z 2dae51b0464af5412711a65e5f2d84bb +Z d13c27a5f9aee35d4aed34621e7033a2 diff --git a/manifest.uuid b/manifest.uuid index f2175fce2e..8c57cdd55c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -33404b2029120d4aabe1e25d484871810777e934 \ No newline at end of file +9d057f52217e7ef9c3f3eb84117abe3365503f44 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 6578900c10..dfff3ca5c4 100644 --- a/src/where.c +++ b/src/where.c @@ -4529,7 +4529,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ pIdx = pLevel->u.pCovidx; } - if( pIdx && !db->mallocFailed ){ + if( pIdx + && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable)) + && !db->mallocFailed + ){ last = sqlite3VdbeCurrentAddr(v); k = pLevel->addrBody; pOp = sqlite3VdbeGetOp(v, k); From 3169713be00b3772a472bf85554d742c7f15318d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 28 Sep 2015 15:08:28 +0000 Subject: [PATCH 13/29] Add test cases to the ONEPASS optimization corruption problem fixed by the previous check-in. FossilOrigin-Name: 5c14d447055bb337428eb1fe0a2934abee381829 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/delete4.test | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index fb761dcc80..faf2febc41 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sdatabase\scorruption\sbug\scaused\sby\sthe\sONEPASS\soptimization\sadded\nin\scheck-in\s[8b93cc5937000535].\s\sBug\sdetected\s(prior\sto\srelease)\sby\n[https://www.sqlite.org/sqllogictest|sqllogictest].\s\sTest\scases\sto\sfollow. -D 2015-09-28T14:40:20.768 +C Add\stest\scases\sto\sthe\sONEPASS\soptimization\scorruption\sproblem\sfixed\sby\sthe\nprevious\scheck-in. +D 2015-09-28T15:08:28.795 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -572,7 +572,7 @@ F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab -F test/delete4.test d9e7d553a939597b27d205b022d769469f361c1f +F test/delete4.test 3ac0b8d23689ba764c2e8b78c1b56b8f1b942fa2 F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240 F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 33404b2029120d4aabe1e25d484871810777e934 -R 221ece26a434b0c8583fbc9c4416f571 +P 9d057f52217e7ef9c3f3eb84117abe3365503f44 +R 075466467a3c577c7bea65d16a397b4e U drh -Z d13c27a5f9aee35d4aed34621e7033a2 +Z a775dc5a399b71fca215b8951f694541 diff --git a/manifest.uuid b/manifest.uuid index 8c57cdd55c..caba2b4da5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9d057f52217e7ef9c3f3eb84117abe3365503f44 \ No newline at end of file +5c14d447055bb337428eb1fe0a2934abee381829 \ No newline at end of file diff --git a/test/delete4.test b/test/delete4.test index 7334bf02ed..f3598a9496 100644 --- a/test/delete4.test +++ b/test/delete4.test @@ -98,5 +98,48 @@ do_execsql_test 3.4 { PRAGMA integrity_check; } {ok} +# Between 2015-09-14 and 2015-09-28, the following test cases would result +# in corruption (wrong # of entries in index) due to a bug in the ONEPASS +# optimization. +# +do_execsql_test 4.1 { + DROP TABLE IF EXISTS t4; + CREATE TABLE t4(col0, col1); + INSERT INTO "t4" VALUES(14, 'abcde'); + CREATE INDEX idx_t4_0 ON t4 (col1, col0); + CREATE INDEX idx_t4_3 ON t4 (col0); + DELETE FROM t4 WHERE col0=69 OR col0>7; + PRAGMA integrity_check; +} {ok} +do_execsql_test 4.2 { + DROP TABLE IF EXISTS t4; + CREATE TABLE t4(col0, col1); + INSERT INTO "t4" VALUES(14, 'abcde'); + CREATE INDEX idx_t4_3 ON t4 (col0); + CREATE INDEX idx_t4_0 ON t4 (col1, col0); + DELETE FROM t4 WHERE col0=69 OR col0>7; + PRAGMA integrity_check; +} {ok} +do_execsql_test 4.11 { + DROP TABLE IF EXISTS t4; + CREATE TABLE t4(col0, col1, pk PRIMARY KEY) WITHOUT ROWID; + INSERT INTO t4 VALUES(14, 'abcde','xyzzy'); + CREATE INDEX idx_t4_0 ON t4 (col1, col0); + CREATE INDEX idx_t4_3 ON t4 (col0); + DELETE FROM t4 WHERE col0=69 OR col0>7; + PRAGMA integrity_check; +} {ok} +do_execsql_test 4.12 { + DROP TABLE IF EXISTS t4; + CREATE TABLE t4(col0, col1, pk PRIMARY KEY) WITHOUT ROWID; + INSERT INTO t4 VALUES(14, 'abcde','xyzzy'); + CREATE INDEX idx_t4_3 ON t4 (col0); + CREATE INDEX idx_t4_0 ON t4 (col1, col0); + DELETE FROM t4 WHERE col0=69 OR col0>7; + PRAGMA integrity_check; +} {ok} + + + finish_test From 076e0f9674a9eecc59cac3c31d93bd1b79d1247e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 28 Sep 2015 15:20:58 +0000 Subject: [PATCH 14/29] Changes to allow DELETE operations on virtual tables to use the onepass strategy under some circumstances. FossilOrigin-Name: e73f919fae1833c6ffb36eddbc76d9a8d9324214 --- manifest | 23 +++++++++++++---------- manifest.uuid | 2 +- src/build.c | 2 ++ src/delete.c | 16 +++++++++++----- src/sqlite.h.in | 7 +++++++ src/where.c | 10 ++++++++++ 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index faf2febc41..d8a00a1ea3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scases\sto\sthe\sONEPASS\soptimization\scorruption\sproblem\sfixed\sby\sthe\nprevious\scheck-in. -D 2015-09-28T15:08:28.795 +C Changes\sto\sallow\sDELETE\soperations\son\svirtual\stables\sto\suse\sthe\sonepass\sstrategy\sunder\ssome\scircumstances. +D 2015-09-28T15:20:58.913 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -285,13 +285,13 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 -F src/build.c edc5a29cd55257b05be837c3613e2cade02b3e03 +F src/build.c 361f58b73aad7804f5706bf62d210bd9cd608041 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7 -F src/delete.c 371df4fc86e96efeaed3d37565aef77f956be109 +F src/delete.c b454df59d57cb3f07118dfc68821760593fcaab3 F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f @@ -342,7 +342,7 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 -F src/sqlite.h.in 02f6ed7de3a96d10bd1e6e5803e4e4b786dff014 +F src/sqlite.h.in eade8bcc0456ff4d3f7ecfbbd3c4eec117314f26 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c f2c4905e47fe80043a0c45f374f555615da365ba +F src/where.c d07fb77010949be9b96e9120b4653712bf9f74ae F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1388,7 +1388,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9d057f52217e7ef9c3f3eb84117abe3365503f44 -R 075466467a3c577c7bea65d16a397b4e -U drh -Z a775dc5a399b71fca215b8951f694541 +P 5c14d447055bb337428eb1fe0a2934abee381829 +R 3d1a8d879c965d0f75999b9c5903a435 +T *branch * vtab-onepass +T *sym-vtab-onepass * +T -sym-trunk * +U dan +Z 049fa8c468f3a0165cbcd245b0299bac diff --git a/manifest.uuid b/manifest.uuid index caba2b4da5..a16e447313 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c14d447055bb337428eb1fe0a2934abee381829 \ No newline at end of file +e73f919fae1833c6ffb36eddbc76d9a8d9324214 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 6a9c613165..c0bd81b1a0 100644 --- a/src/build.c +++ b/src/build.c @@ -192,6 +192,8 @@ void sqlite3FinishCoding(Parse *pParse){ db->aDb[iDb].pSchema->iGeneration /* P4 */ ); if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); + VdbeComment((v, + "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); } #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; inVtabLock; i++){ diff --git a/src/delete.c b/src/delete.c index c387c20bef..9c928f8d51 100644 --- a/src/delete.c +++ b/src/delete.c @@ -411,7 +411,7 @@ void sqlite3DeleteFrom( pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF ); + assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); /* Keep track of the number of rows to be deleted */ @@ -465,7 +465,7 @@ void sqlite3DeleteFrom( /* If this DELETE cannot use the ONEPASS strategy, this is the ** end of the WHERE loop */ - if( eOnePass!=ONEPASS_OFF ){ + if( eOnePass!=ONEPASS_OFF && !IsVirtual(pTab) ){ addrBypass = sqlite3VdbeMakeLabel(v); }else{ sqlite3WhereEnd(pWInfo); @@ -494,7 +494,7 @@ void sqlite3DeleteFrom( */ if( eOnePass!=ONEPASS_OFF ){ assert( nKey==nPk ); /* OP_Found will use an unpacked key */ - if( aToOpen[iDataCur-iTabCur] ){ + if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 || pTab->pSelect!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); @@ -516,7 +516,11 @@ void sqlite3DeleteFrom( sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, OE_Abort); + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); + if( eOnePass==ONEPASS_SINGLE && pParse==sqlite3ParseToplevel(pParse) ){ + pParse->isMultiWrite = 0; + } }else #endif { @@ -531,8 +535,10 @@ void sqlite3DeleteFrom( /* End of the loop over all rowids/primary-keys. */ if( eOnePass!=ONEPASS_OFF ){ - sqlite3VdbeResolveLabel(v, addrBypass); - sqlite3WhereEnd(pWInfo); + if( !IsVirtual(pTab) ){ + sqlite3VdbeResolveLabel(v, addrBypass); + sqlite3WhereEnd(pWInfo); + } }else if( pPk ){ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 0f7d3a21bf..4a1312863e 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5668,8 +5668,15 @@ struct sqlite3_index_info { double estimatedCost; /* Estimated cost of using this index */ /* Fields below are only available in SQLite 3.8.2 and later */ sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ + /* Fields below are only available in SQLite 3.8.12 and later */ + int flags; /* Mask of SQLITE_INDEX_SCAN_* flags */ }; +/* +** CAPI3REF: Virtual Table Scan Flags +*/ +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** diff --git a/src/where.c b/src/where.c index dfff3ca5c4..1175496a2a 100644 --- a/src/where.c +++ b/src/where.c @@ -2832,6 +2832,7 @@ static int whereLoopAddVirtual( pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; + pIdxInfo->flags = 0; rc = vtabBestIndex(pParse, pTab, pIdxInfo); if( rc ) goto whereLoopAddVtab_exit; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; @@ -2877,6 +2878,7 @@ static int whereLoopAddVirtual( ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; + pIdxInfo->flags &= ~SQLITE_INDEX_SCAN_UNIQUE; } } } @@ -2892,6 +2894,14 @@ static int whereLoopAddVirtual( pNew->rSetup = 0; pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); + + /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated + ** that the scan will visit at most one row. Clear it otherwise. */ + if( pIdxInfo->flags & SQLITE_INDEX_SCAN_UNIQUE ){ + pNew->wsFlags |= WHERE_ONEROW; + }else{ + pNew->wsFlags &= ~WHERE_ONEROW; + } whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); From d943b275968e38164ab0473f8688c8ef9083c0ac Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 28 Sep 2015 15:23:29 +0000 Subject: [PATCH 15/29] Update fts3 to use the onepass strategy for delete operations. FossilOrigin-Name: fffab4f70f85eeb2acbb89534064a6e397c39384 --- ext/fts3/fts3.c | 16 ++++++++++++++++ ext/fts3/fts3Int.h | 1 + ext/fts3/fts3_write.c | 13 +++++++++---- manifest | 21 +++++++++------------ manifest.uuid | 2 +- test/fts4growth.test | 4 ++-- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 6a9b507fc0..ceffb52cf4 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1517,6 +1517,19 @@ static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ #endif } +/* +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this +** extension is currently being used by a version of SQLite too old to +** support index-info flags. In that case this function is a no-op. +*/ +static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ +#if SQLITE_VERSION_NUMBER>=3008012 + if( sqlite3_libversion_number()>=3008012 ){ + pIdxInfo->flags |= SQLITE_INDEX_SCAN_UNIQUE; + } +#endif +} + /* ** Implementation of the xBestIndex method for FTS3 tables. There ** are three possible strategies, in order of preference: @@ -1607,6 +1620,9 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } } + /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ + if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); + iIdx = 1; if( iCons>=0 ){ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 981c37deee..06bcc7202e 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -264,6 +264,7 @@ struct Fts3Table { int nPendingData; /* Current bytes of pending data */ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ int iPrevLangid; /* Langid of recently inserted document */ + int bPrevDelete; /* True if last operation was a delete */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) /* State variables used for validating that the transaction control diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 4cd2aebf6a..73adbd3f91 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -860,10 +860,12 @@ static int fts3PendingTermsAdd( */ static int fts3PendingTermsDocid( Fts3Table *p, /* Full-text table handle */ + int bDelete, /* True if this op is a delete */ int iLangid, /* Language id of row being written */ sqlite_int64 iDocid /* Docid of row being written */ ){ assert( iLangid>=0 ); + assert( bDelete==1 || bDelete==0 ); /* TODO(shess) Explore whether partially flushing the buffer on ** forced-flush would provide better performance. I suspect that if @@ -871,7 +873,8 @@ static int fts3PendingTermsDocid( ** buffer was half empty, that would let the less frequent terms ** generate longer doclists. */ - if( iDocid<=p->iPrevDocid + if( iDocidiPrevDocid + || (iDocid==p->iPrevLangid && p->bPrevDelete==0) || p->iPrevLangid!=iLangid || p->nPendingData>p->nMaxPendingData ){ @@ -880,6 +883,7 @@ static int fts3PendingTermsDocid( } p->iPrevDocid = iDocid; p->iPrevLangid = iLangid; + p->bPrevDelete = bDelete; return SQLITE_OK; } @@ -1069,7 +1073,8 @@ static void fts3DeleteTerms( if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; int iLangid = langidFromSelect(p, pSelect); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); + i64 iDocid = sqlite3_column_int64(pSelect, 0); + rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ int iCol = i-1; if( p->abNotindexed[iCol]==0 ){ @@ -3512,7 +3517,7 @@ static int fts3DoRebuild(Fts3Table *p){ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); + rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ if( p->abNotindexed[iCol]==0 ){ @@ -5617,7 +5622,7 @@ int sqlite3Fts3UpdateMethod( } } if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ - rc = fts3PendingTermsDocid(p, iLangid, *pRowid); + rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); } if( rc==SQLITE_OK ){ assert( p->iPrevDocid==*pRowid ); diff --git a/manifest b/manifest index d8a00a1ea3..4c1ad66b3a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\sallow\sDELETE\soperations\son\svirtual\stables\sto\suse\sthe\sonepass\sstrategy\sunder\ssome\scircumstances. -D 2015-09-28T15:20:58.913 +C Update\sfts3\sto\suse\sthe\sonepass\sstrategy\sfor\sdelete\soperations. +D 2015-09-28T15:23:29.191 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,9 +78,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c b04b0c57761fdba2ae562d9d9ba50c7c4a95d9ea +F ext/fts3/fts3.c 52232f39bae8320c537f1d9ffd8d58b64dfaf21e F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h 601743955ac43a0e82e6828a931c07bb3b0c95ff +F ext/fts3/fts3Int.h c84125c666ee54cef6efce6ff64abb0d0e2f4535 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 @@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c 4f005f78592a1447ca96c8475ef5342ab7dbe02a +F ext/fts3/fts3_write.c 5d7857a6a454f210e4fabc2528e8a63e6ab98078 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d @@ -727,7 +727,7 @@ F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430 F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 -F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53 +F test/fts4growth.test a73eab34dd9960d10603347fc77fefe2f9322e26 F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7 @@ -1388,10 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5c14d447055bb337428eb1fe0a2934abee381829 -R 3d1a8d879c965d0f75999b9c5903a435 -T *branch * vtab-onepass -T *sym-vtab-onepass * -T -sym-trunk * +P e73f919fae1833c6ffb36eddbc76d9a8d9324214 +R 164b44f729dee0c8bb93a44bcf38cdec U dan -Z 049fa8c468f3a0165cbcd245b0299bac +Z 708fbaf265cb02c74fec8f06c877c6ce diff --git a/manifest.uuid b/manifest.uuid index a16e447313..fd2328e23a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e73f919fae1833c6ffb36eddbc76d9a8d9324214 \ No newline at end of file +fffab4f70f85eeb2acbb89534064a6e397c39384 \ No newline at end of file diff --git a/test/fts4growth.test b/test/fts4growth.test index aa5f251f95..6884922afe 100644 --- a/test/fts4growth.test +++ b/test/fts4growth.test @@ -202,11 +202,11 @@ do_test 3.1.3 { delete_doc 9 8 7 } execsql { SELECT level, idx, second(end_block) FROM x3_segdir } -} {0 0 591 0 1 65 0 2 72 0 3 76} +} {0 0 591 0 1 72 0 2 76} do_test 3.1.4 { execsql { INSERT INTO x3(x3) VALUES('optimize') } execsql { SELECT level, idx, second(end_block) FROM x3_segdir } -} {0 0 412} +} {0 0 463} do_test 3.2.1 { execsql { DELETE FROM x3 } From a722821eb53c3ba81470890201c7ac1b474bb8c3 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 28 Sep 2015 17:05:22 +0000 Subject: [PATCH 16/29] Extra information provided by .wheretrace on input flags to the query planner and on the result of sqlite3WhereOkOnePass(). FossilOrigin-Name: c5566bb39c8d9b58f77380b81a873429575c7d5c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 10 +++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index faf2febc41..6bcfc15a78 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scases\sto\sthe\sONEPASS\soptimization\scorruption\sproblem\sfixed\sby\sthe\nprevious\scheck-in. -D 2015-09-28T15:08:28.795 +C Extra\sinformation\sprovided\sby\s.wheretrace\son\sinput\sflags\sto\sthe\squery\splanner\nand\son\sthe\sresult\sof\ssqlite3WhereOkOnePass(). +D 2015-09-28T17:05:22.174 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c f2c4905e47fe80043a0c45f374f555615da365ba +F src/where.c 25d7527226d63176b3cd4880a85119cda9f83844 F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9d057f52217e7ef9c3f3eb84117abe3365503f44 -R 075466467a3c577c7bea65d16a397b4e +P 5c14d447055bb337428eb1fe0a2934abee381829 +R afaa284829583439d3c828667e0babfd U drh -Z a775dc5a399b71fca215b8951f694541 +Z 4d08d7f777c595957317ee86b8c88bc8 diff --git a/manifest.uuid b/manifest.uuid index caba2b4da5..544e794a7a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c14d447055bb337428eb1fe0a2934abee381829 \ No newline at end of file +c5566bb39c8d9b58f77380b81a873429575c7d5c \ No newline at end of file diff --git a/src/where.c b/src/where.c index dfff3ca5c4..e224d40b1e 100644 --- a/src/where.c +++ b/src/where.c @@ -87,6 +87,13 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ */ int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); +#ifdef WHERETRACE_ENABLED + if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ + sqlite3DebugPrintf("%s cursors: %d %d\n", + pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", + aiCur[0], aiCur[1]); + } +#endif return pWInfo->eOnePass; } @@ -4110,7 +4117,8 @@ WhereInfo *sqlite3WhereBegin( } /* Construct the WhereLoop objects */ - WHERETRACE(0xffff,("*** Optimizer Start ***\n")); + WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n", + wctrlFlags)); #if defined(WHERETRACE_ENABLED) if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ int i; From 0f40037eeedde464d3548f42e95adff8411d4743 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 28 Sep 2015 20:03:49 +0000 Subject: [PATCH 17/29] Also allow UPDATE on virtual tables to use the onepass strategy. FossilOrigin-Name: 1aa27d706db9b2e21737ce4b94b47ecd12c2570f --- ext/fts3/fts3_write.c | 2 +- manifest | 18 ++--- manifest.uuid | 2 +- src/update.c | 177 ++++++++++++++++++++++++------------------ test/fts3conf.test | 10 +-- test/fts4growth.test | 4 +- 6 files changed, 121 insertions(+), 92 deletions(-) diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 73adbd3f91..6b7d5ef2ae 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -874,7 +874,7 @@ static int fts3PendingTermsDocid( ** generate longer doclists. */ if( iDocidiPrevDocid - || (iDocid==p->iPrevLangid && p->bPrevDelete==0) + || (iDocid==p->iPrevDocid && p->bPrevDelete==0) || p->iPrevLangid!=iLangid || p->nPendingData>p->nMaxPendingData ){ diff --git a/manifest b/manifest index 4c1ad66b3a..db3cccbd97 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sfts3\sto\suse\sthe\sonepass\sstrategy\sfor\sdelete\soperations. -D 2015-09-28T15:23:29.191 +C Also\sallow\sUPDATE\son\svirtual\stables\sto\suse\sthe\sonepass\sstrategy. +D 2015-09-28T20:03:49.551 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c 5d7857a6a454f210e4fabc2528e8a63e6ab98078 +F ext/fts3/fts3_write.c 6f7233a06df17084d5cd968899053731bf953f94 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d @@ -399,7 +399,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f -F src/update.c eb7ab3ff2928628692a4f14be397c95f4a681d97 +F src/update.c 779319e1d52c3dfb3b870c9acd26161b464fbe27 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -690,7 +690,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c -F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de +F test/fts3conf.test 92bc4cc67f948b2f53f73c8ab0ebf4be9eee92aa F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 @@ -727,7 +727,7 @@ F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430 F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 -F test/fts4growth.test a73eab34dd9960d10603347fc77fefe2f9322e26 +F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53 F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e73f919fae1833c6ffb36eddbc76d9a8d9324214 -R 164b44f729dee0c8bb93a44bcf38cdec +P fffab4f70f85eeb2acbb89534064a6e397c39384 +R 57289d0ecbc93a6cd377511502833368 U dan -Z 708fbaf265cb02c74fec8f06c877c6ce +Z 186d4cd8527ef990e771b3fd7444e8fc diff --git a/manifest.uuid b/manifest.uuid index fd2328e23a..7d87d8a7db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fffab4f70f85eeb2acbb89534064a6e397c39384 \ No newline at end of file +1aa27d706db9b2e21737ce4b94b47ecd12c2570f \ No newline at end of file diff --git a/src/update.c b/src/update.c index 94f7a4dd99..b7071ce014 100644 --- a/src/update.c +++ b/src/update.c @@ -300,29 +300,20 @@ void sqlite3Update( if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, iDb); -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Virtual tables must be handled separately */ - if( IsVirtual(pTab) ){ - updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, - pWhere, onError); - pWhere = 0; - pTabList = 0; - goto update_cleanup; - } -#endif - /* Allocate required registers. */ - regRowSet = ++pParse->nMem; - regOldRowid = regNewRowid = ++pParse->nMem; - if( chngPk || pTrigger || hasFK ){ - regOld = pParse->nMem + 1; + if( !IsVirtual(pTab) ){ + regRowSet = ++pParse->nMem; + regOldRowid = regNewRowid = ++pParse->nMem; + if( chngPk || pTrigger || hasFK ){ + regOld = pParse->nMem + 1; + pParse->nMem += pTab->nCol; + } + if( chngKey || pTrigger || hasFK ){ + regNewRowid = ++pParse->nMem; + } + regNew = pParse->nMem + 1; pParse->nMem += pTab->nCol; } - if( chngKey || pTrigger || hasFK ){ - regNewRowid = ++pParse->nMem; - } - regNew = pParse->nMem + 1; - pParse->nMem += pTab->nCol; /* Start the view context. */ if( isView ){ @@ -345,6 +336,15 @@ void sqlite3Update( goto update_cleanup; } +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Virtual tables must be handled separately */ + if( IsVirtual(pTab) ){ + updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, + pWhere, onError); + goto update_cleanup; + } +#endif + /* Begin the database scan */ if( HasRowid(pTab) ){ @@ -685,21 +685,23 @@ update_cleanup: /* ** Generate code for an UPDATE of a virtual table. ** -** The strategy is that we create an ephemeral table that contains +** There are two possible strategies - the default and the special +** "onepass" strategy. Onepass is only used if the virtual table +** implementation indicates that pWhere may match at most one row. +** +** The default strategy is to create an ephemeral table that contains ** for each row to be changed: ** ** (A) The original rowid of that row. -** (B) The revised rowid for the row. (note1) +** (B) The revised rowid for the row. ** (C) The content of every column in the row. ** -** Then we loop over this ephemeral table and for each row in -** the ephemeral table call VUpdate. +** Then loop through the contents of this ephemeral table executing a +** VUpdate for each row. When finished, drop the ephemeral table. ** -** When finished, drop the ephemeral table. -** -** (note1) Actually, if we know in advance that (A) is always the same -** as (B) we only store (A), then duplicate (A) when pulling -** it out of the ephemeral table before calling VUpdate. +** The "onepass" strategy does not use an ephemeral table. Instead, it +** stores the same values (A, B and C above) in a register array and +** makes a single invocation of VUpdate. */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ @@ -712,65 +714,92 @@ static void updateVirtualTable( int onError /* ON CONFLICT strategy */ ){ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ - ExprList *pEList = 0; /* The result set of the SELECT statement */ - Select *pSelect = 0; /* The SELECT statement */ - Expr *pExpr; /* Temporary expression */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ - int addr; /* Address of top of loop */ - int iReg; /* First register in set passed to OP_VUpdate */ sqlite3 *db = pParse->db; /* Database connection */ const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); - SelectDest dest; + WhereInfo *pWInfo; + int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ + int regArg; /* First register in VUpdate arg array */ + int regRec; /* Register in which to assemble record */ + int regRowid; /* Register for ephem table rowid */ + int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ + int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ + int bOnePass; /* True to use onepass strategy */ + int addr; /* Address of OP_OpenEphemeral */ + NameContext sNC; - /* Construct the SELECT statement that will find the new values for - ** all updated rows. - */ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_")); - if( pRowid ){ - pEList = sqlite3ExprListAppend(pParse, pEList, - sqlite3ExprDup(db, pRowid, 0)); - } - assert( pTab->iPKey<0 ); - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ){ - pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); - }else{ - pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName); - } - pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); - } - pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); - - /* Create the ephemeral table into which the update results will - ** be stored. - */ + /* Allocate nArg registers to martial the arguments to VUpdate. Then + ** create and open the ephemeral table in which the records created from + ** these arguments will be temporarily stored. */ assert( v ); ephemTab = pParse->nTab++; + addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); + regArg = pParse->nMem + 1; + pParse->nMem += nArg; + regRec = ++pParse->nMem; + regRowid = ++pParse->nMem; - /* fill the ephemeral table - */ - sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab); - sqlite3Select(pParse, pSelect, &dest); + /* Start scanning the virtual table */ + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); + if( pWInfo==0 ) return; - /* Generate code to scan the ephemeral table and call VUpdate. */ - iReg = ++pParse->nMem; - pParse->nMem += pTab->nCol+1; - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); + /* Populate the argument registers. */ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); + if( pRowid ){ + sqlite3ExprCode(pParse, pRowid, regArg+1); + }else{ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); + } for(i=0; inCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); + if( aXRef[i]>=0 ){ + sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); + }else{ + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); + } + } + + bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + + if( bOnePass ){ + /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded + ** above. Also, if this is a top-level parse (not a trigger), clear the + ** multi-write flag so that the VM does not open a statement journal */ + sqlite3VdbeChangeToNoop(v, addr); + if( sqlite3ParseToplevel(pParse)==pParse ){ + pParse->isMultiWrite = 0; + } + }else{ + /* Create a record from the argument register contents and insert it into + ** the ephemeral table. */ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); + sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); + } + + /* End the virtual table scan */ + sqlite3WhereEnd(pWInfo); + + if( bOnePass==0 ){ + /* Begin scannning through the ephemeral table. */ + addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); + + /* Extract arguments from the current row of the ephemeral table and + ** invoke the VUpdate method. */ + for(i=0; inCol+2, iReg, pVTab, P4_VTAB); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); - /* Cleanup */ - sqlite3SelectDelete(db, pSelect); + /* End of the ephemeral table scan */ + if( bOnePass==0 ){ + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); + } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/test/fts3conf.test b/test/fts3conf.test index e91efbefbe..543270606f 100644 --- a/test/fts3conf.test +++ b/test/fts3conf.test @@ -86,11 +86,11 @@ foreach {tn sql uses constraint data} [subst { 9 "INSERT OR IGNORE $T2" 1 0 {{a b c d} {e f g h} {i j k l} z} 10 "INSERT OR REPLACE $T2" 1 0 {{a b c d} y {i j k l} z} - 11 "UPDATE OR ROLLBACK $T3" 1 1 {{a b c d} {e f g h}} - 12 "UPDATE OR ABORT $T3" 1 1 {{a b c d} {e f g h} {i j k l}} - 13 "UPDATE OR FAIL $T3" 1 1 {{a b c d} {e f g h} {i j k l}} - 14 "UPDATE OR IGNORE $T3" 1 0 {{a b c d} {e f g h} {i j k l}} - 15 "UPDATE OR REPLACE $T3" 1 0 {{a b c d} {i j k l}} + 11 "UPDATE OR ROLLBACK $T3" 0 1 {{a b c d} {e f g h}} + 12 "UPDATE OR ABORT $T3" 0 1 {{a b c d} {e f g h} {i j k l}} + 13 "UPDATE OR FAIL $T3" 0 1 {{a b c d} {e f g h} {i j k l}} + 14 "UPDATE OR IGNORE $T3" 0 0 {{a b c d} {e f g h} {i j k l}} + 15 "UPDATE OR REPLACE $T3" 0 0 {{a b c d} {i j k l}} 16 "UPDATE OR ROLLBACK $T4" 1 1 {{a b c d} {e f g h}} 17 "UPDATE OR ABORT $T4" 1 1 {{a b c d} {e f g h} {i j k l}} diff --git a/test/fts4growth.test b/test/fts4growth.test index 6884922afe..aa5f251f95 100644 --- a/test/fts4growth.test +++ b/test/fts4growth.test @@ -202,11 +202,11 @@ do_test 3.1.3 { delete_doc 9 8 7 } execsql { SELECT level, idx, second(end_block) FROM x3_segdir } -} {0 0 591 0 1 72 0 2 76} +} {0 0 591 0 1 65 0 2 72 0 3 76} do_test 3.1.4 { execsql { INSERT INTO x3(x3) VALUES('optimize') } execsql { SELECT level, idx, second(end_block) FROM x3_segdir } -} {0 0 463} +} {0 0 412} do_test 3.2.1 { execsql { DELETE FROM x3 } From 354474ad6de3a4ee43df5f83af769669513cec02 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 29 Sep 2015 10:11:26 +0000 Subject: [PATCH 18/29] Add tests for fts3 and onepass update/delete operations. Also fix a problem with onepass updates that do not affect any rows. FossilOrigin-Name: 820c804468abff692742952de670c5d906a50956 --- manifest | 17 ++--- manifest.uuid | 2 +- src/delete.c | 8 +-- src/update.c | 12 ++-- src/wherecode.c | 2 +- test/fts4onepass.test | 147 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 19 deletions(-) create mode 100644 test/fts4onepass.test diff --git a/manifest b/manifest index db3cccbd97..7c78e99294 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Also\sallow\sUPDATE\son\svirtual\stables\sto\suse\sthe\sonepass\sstrategy. -D 2015-09-28T20:03:49.551 +C Add\stests\sfor\sfts3\sand\sonepass\supdate/delete\soperations.\sAlso\sfix\sa\sproblem\swith\sonepass\supdates\sthat\sdo\snot\saffect\sany\srows. +D 2015-09-29T10:11:26.685 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7 -F src/delete.c b454df59d57cb3f07118dfc68821760593fcaab3 +F src/delete.c 174b140317915e0e8c6e2eff28158eecf95c53d8 F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f @@ -399,7 +399,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f -F src/update.c 779319e1d52c3dfb3b870c9acd26161b464fbe27 +F src/update.c 4fb82a2440bd8d66f266ada1ef31a2fcde48bd4f F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -419,7 +419,7 @@ F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba F src/where.c d07fb77010949be9b96e9120b4653712bf9f74ae F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 -F src/wherecode.c 7660e1ad16817a921b099af553f3e1349352d16f +F src/wherecode.c a87238178f8c300fd27afec54326ea8d0a18baa2 F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -736,6 +736,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849 +F test/fts4onepass.test bfca61f69c6ca74cd71e6dca12a0cdd47192fc24 F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -1388,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fffab4f70f85eeb2acbb89534064a6e397c39384 -R 57289d0ecbc93a6cd377511502833368 +P 1aa27d706db9b2e21737ce4b94b47ecd12c2570f +R 906a452cbd4322b894c4cf3888c881fe U dan -Z 186d4cd8527ef990e771b3fd7444e8fc +Z 392788408df553b8d21ff2f5c84b91d4 diff --git a/manifest.uuid b/manifest.uuid index 7d87d8a7db..673713a60e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1aa27d706db9b2e21737ce4b94b47ecd12c2570f \ No newline at end of file +820c804468abff692742952de670c5d906a50956 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 9c928f8d51..ed843c1a75 100644 --- a/src/delete.c +++ b/src/delete.c @@ -465,7 +465,7 @@ void sqlite3DeleteFrom( /* If this DELETE cannot use the ONEPASS strategy, this is the ** end of the WHERE loop */ - if( eOnePass!=ONEPASS_OFF && !IsVirtual(pTab) ){ + if( eOnePass!=ONEPASS_OFF ){ addrBypass = sqlite3VdbeMakeLabel(v); }else{ sqlite3WhereEnd(pWInfo); @@ -535,10 +535,8 @@ void sqlite3DeleteFrom( /* End of the loop over all rowids/primary-keys. */ if( eOnePass!=ONEPASS_OFF ){ - if( !IsVirtual(pTab) ){ - sqlite3VdbeResolveLabel(v, addrBypass); - sqlite3WhereEnd(pWInfo); - } + sqlite3VdbeResolveLabel(v, addrBypass); + sqlite3WhereEnd(pWInfo); }else if( pPk ){ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); diff --git a/src/update.c b/src/update.c index b7071ce014..ebf0d6c8ea 100644 --- a/src/update.c +++ b/src/update.c @@ -777,12 +777,13 @@ static void updateVirtualTable( sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); } - /* End the virtual table scan */ - sqlite3WhereEnd(pWInfo); if( bOnePass==0 ){ + /* End the virtual table scan */ + sqlite3WhereEnd(pWInfo); + /* Begin scannning through the ephemeral table. */ - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); /* Extract arguments from the current row of the ephemeral table and ** invoke the VUpdate method. */ @@ -795,11 +796,14 @@ static void updateVirtualTable( sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); - /* End of the ephemeral table scan */ + /* End of the ephemeral table scan. Or, if using the onepass strategy, + ** jump to here if the scan visited zero rows. */ if( bOnePass==0 ){ sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); + }else{ + sqlite3WhereEnd(pWInfo); } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/src/wherecode.c b/src/wherecode.c index 77b8be4bee..f9b56e7c83 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -700,8 +700,8 @@ Bitmask sqlite3WhereCodeOneLoopStart( disableTerm(pLevel, pLoop->aLTerm[j]); } } - pLevel->op = OP_VNext; pLevel->p1 = iCur; + pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite3ExprCachePop(pParse); diff --git a/test/fts4onepass.test b/test/fts4onepass.test new file mode 100644 index 0000000000..d290980dc9 --- /dev/null +++ b/test/fts4onepass.test @@ -0,0 +1,147 @@ +# 2015 Sep 27 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/fts3_common.tcl +set ::testprefix fts4onepass + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ft USING fts3; + INSERT INTO ft(rowid, content) VALUES(1, '1 2 3'); + INSERT INTO ft(rowid, content) VALUES(2, '4 5 6'); + INSERT INTO ft(rowid, content) VALUES(3, '7 8 9'); +} + +#------------------------------------------------------------------------- +# Check that UPDATE and DELETE statements that feature "WHERE rowid=?" or +# or "WHERE docid=?" clauses do not use statement journals. But that other +# DELETE and UPDATE statements do. +# +# Note: "MATCH ? AND docid=?" does use a statement journal. +# +foreach {tn sql uses} { + 1.1 { DELETE FROM ft } 1 + 1.2 { DELETE FROM ft WHERE docid=? } 0 + 1.3 { DELETE FROM ft WHERE rowid=? } 0 + 1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1 + 1.5 { DELETE FROM ft WHERE ft MATCH '1' AND docid=? } 1 + 1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1 + + 2.1 { UPDATE ft SET content='a b c' } 1 + 2.2 { UPDATE ft SET content='a b c' WHERE docid=? } 0 + 2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0 + 2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1 + 2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND docid=? } 1 + 2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1 +} { + do_test 1.$tn { sql_uses_stmt db $sql } $uses +} + +#------------------------------------------------------------------------- +# Check that putting a "DELETE/UPDATE ... WHERE rowid=?" statement in a +# trigger program does not prevent the VM from using a statement +# transaction. Even if the calling statement cannot hit a constraint. +# +do_execsql_test 2.0 { + CREATE TABLE t1(x); + + CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN + DELETE FROM ft WHERE rowid=new.x; + END; + + CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN + UPDATE ft SET content = 'a b c' WHERE rowid=old.x; + END; + + CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN + DELETE FROM ft WHERE rowid=old.x; + END; +} + +foreach {tn sql uses} { + 1 { INSERT INTO t1 VALUES(1) } 1 + 2 { DELETE FROM t1 WHERE x=4 } 1 + 3 { UPDATE t1 SET x=10 WHERE x=11 } 1 +} { + do_test 2.$tn { sql_uses_stmt db $sql } $uses +} + +#------------------------------------------------------------------------- +# Test that an "UPDATE ... WHERE rowid=?" works and does not corrupt the +# index when it strikes a constraint. Both inside and outside a +# transaction. +# +foreach {tn tcl1 tcl2} { + 1 {} {} + + 2 { + execsql BEGIN + } { + if {[sqlite3_get_autocommit db]==1} { error "transaction rolled back!" } + execsql COMMIT + } +} { + + do_execsql_test 3.$tn.0 { + DROP TABLE IF EXISTS ft2; + CREATE VIRTUAL TABLE ft2 USING fts4; + INSERT INTO ft2(rowid, content) VALUES(1, 'a b c'); + INSERT INTO ft2(rowid, content) VALUES(2, 'a b d'); + INSERT INTO ft2(rowid, content) VALUES(3, 'a b e'); + } + + eval $tcl1 + foreach {tn2 sql content} { + 1 { UPDATE ft2 SET docid=2 WHERE docid=1 } + { 1 {a b c} 2 {a b d} 3 {a b e} } + + 2 { + INSERT INTO ft2(rowid, content) VALUES(4, 'a b f'); + UPDATE ft2 SET docid=5 WHERE docid=4; + UPDATE ft2 SET docid=3 WHERE docid=5; + } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 3 { + UPDATE ft2 SET docid=3 WHERE docid=4; -- matches 0 rows + UPDATE ft2 SET docid=2 WHERE docid=3; + } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 4 { + INSERT INTO ft2(rowid, content) VALUES(4, 'a b g'); + UPDATE ft2 SET docid=-1 WHERE docid=4; + UPDATE ft2 SET docid=3 WHERE docid=-1; + } {-1 {a b g} 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 5 { + DELETE FROM ft2 WHERE rowid=451; + DELETE FROM ft2 WHERE rowid=-1; + UPDATE ft2 SET docid = 2 WHERE docid = 1; + } {1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + } { + do_catchsql_test 3.$tn.$tn2.a $sql {1 {constraint failed}} + do_execsql_test 3.$tn.$tn2.b { SELECT rowid, content FROM ft2 } $content + do_execsql_test 3.$tn.$tn2.c { + INSERT INTO ft2(ft2) VALUES('integrity-check'); + } + } + eval $tcl2 +} + +finish_test + From b3deb4ea64464a104c25984a8796eb8a6153d07a Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 29 Sep 2015 11:57:20 +0000 Subject: [PATCH 19/29] Change the name of the new sqlite3_index_info.flags field to "idxFlags". Add documentation for the same to sqlite.h.in. FossilOrigin-Name: f61203bc0fb0b62e12d6270e8d9063e445a5a252 --- ext/fts3/fts3.c | 2 +- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqlite.h.in | 22 ++++++++++++++++++++-- src/where.c | 6 +++--- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index ceffb52cf4..748faefec5 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1525,7 +1525,7 @@ static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ #if SQLITE_VERSION_NUMBER>=3008012 if( sqlite3_libversion_number()>=3008012 ){ - pIdxInfo->flags |= SQLITE_INDEX_SCAN_UNIQUE; + pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; } #endif } diff --git a/manifest b/manifest index 7c78e99294..40d38d696c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sfor\sfts3\sand\sonepass\supdate/delete\soperations.\sAlso\sfix\sa\sproblem\swith\sonepass\supdates\sthat\sdo\snot\saffect\sany\srows. -D 2015-09-29T10:11:26.685 +C Change\sthe\sname\sof\sthe\snew\ssqlite3_index_info.flags\sfield\sto\s"idxFlags".\sAdd\sdocumentation\sfor\sthe\ssame\sto\ssqlite.h.in. +D 2015-09-29T11:57:20.011 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 52232f39bae8320c537f1d9ffd8d58b64dfaf21e +F ext/fts3/fts3.c e028eb13432f108d2e22cded019fc980700e4e00 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h c84125c666ee54cef6efce6ff64abb0d0e2f4535 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -342,7 +342,7 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 -F src/sqlite.h.in eade8bcc0456ff4d3f7ecfbbd3c4eec117314f26 +F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f @@ -417,7 +417,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c d07fb77010949be9b96e9120b4653712bf9f74ae +F src/where.c 6491ebe811ee698793912f927b0fe3b662687e1b F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 F src/wherecode.c a87238178f8c300fd27afec54326ea8d0a18baa2 F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1aa27d706db9b2e21737ce4b94b47ecd12c2570f -R 906a452cbd4322b894c4cf3888c881fe +P 820c804468abff692742952de670c5d906a50956 +R 546729b46aaa02f7503bc91f6617e820 U dan -Z 392788408df553b8d21ff2f5c84b91d4 +Z 84ab7e4ab7ab149e316240ec34018bc8 diff --git a/manifest.uuid b/manifest.uuid index 673713a60e..22a29264dc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -820c804468abff692742952de670c5d906a50956 \ No newline at end of file +f61203bc0fb0b62e12d6270e8d9063e445a5a252 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4a1312863e..75e51f4b01 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5634,13 +5634,31 @@ struct sqlite3_module { ** ^The estimatedRows value is an estimate of the number of rows that ** will be returned by the strategy. ** +** The xBestIndex method may optionally populate the idxFlags field with a +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite +** assumes that the strategy may visit at most one row. +** +** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then +** SQLite also assumes that if a call to the xUpdate() method is made as +** part of the same statement to delete or update a virtual table row and the +** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback +** any database changes. In other words, if the xUpdate() returns +** SQLITE_CONSTRAINT, the database contents must be exactly as they were +** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not +** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by +** the xUpdate method are automatically rolled back by SQLite. +** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info ** structure for SQLite version 3.8.2. If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a -** value greater than or equal to 3008002. +** value greater than or equal to 3008002. Similarly, the idxFlags field +** was added for version 3.8.12. It may therefore only be used if +** sqlite3_libversion_number() returns a value greater than or equal to +** 3008012. */ struct sqlite3_index_info { /* Inputs */ @@ -5669,7 +5687,7 @@ struct sqlite3_index_info { /* Fields below are only available in SQLite 3.8.2 and later */ sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ /* Fields below are only available in SQLite 3.8.12 and later */ - int flags; /* Mask of SQLITE_INDEX_SCAN_* flags */ + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ }; /* diff --git a/src/where.c b/src/where.c index 1175496a2a..70774daea7 100644 --- a/src/where.c +++ b/src/where.c @@ -2832,7 +2832,7 @@ static int whereLoopAddVirtual( pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; - pIdxInfo->flags = 0; + pIdxInfo->idxFlags = 0; rc = vtabBestIndex(pParse, pTab, pIdxInfo); if( rc ) goto whereLoopAddVtab_exit; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; @@ -2878,7 +2878,7 @@ static int whereLoopAddVirtual( ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; - pIdxInfo->flags &= ~SQLITE_INDEX_SCAN_UNIQUE; + pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; } } } @@ -2897,7 +2897,7 @@ static int whereLoopAddVirtual( /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated ** that the scan will visit at most one row. Clear it otherwise. */ - if( pIdxInfo->flags & SQLITE_INDEX_SCAN_UNIQUE ){ + if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ pNew->wsFlags |= WHERE_ONEROW; }else{ pNew->wsFlags &= ~WHERE_ONEROW; From 4ad09719194533b38a16766d4c4562e0707f7934 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 29 Sep 2015 12:19:51 +0000 Subject: [PATCH 20/29] Fix an off-by-one error in test function fts5_decode(). FossilOrigin-Name: 3a9f076250d9559d8ea94ba44095ba3ddbc5542d --- ext/fts5/fts5_index.c | 2 +- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index b8aa52c2f8..9910c59b0a 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -5361,7 +5361,7 @@ static void fts5DecodeFunction( memset(&term, 0, sizeof(Fts5Buffer)); if( n<4 ){ - sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt"); + sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt"); goto decode_out; }else{ iRowidOff = fts5GetU16(&a[0]); diff --git a/manifest b/manifest index 6bcfc15a78..ae2961c2dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Extra\sinformation\sprovided\sby\s.wheretrace\son\sinput\sflags\sto\sthe\squery\splanner\nand\son\sthe\sresult\sof\ssqlite3WhereOkOnePass(). -D 2015-09-28T17:05:22.174 +C Fix\san\soff-by-one\serror\sin\stest\sfunction\sfts5_decode(). +D 2015-09-29T12:19:51.430 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -112,7 +112,7 @@ F ext/fts5/fts5_buffer.c 64dcaf36a3ebda9e84b7c3b8788887ec325e12a4 F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695 F ext/fts5/fts5_expr.c 667faaf14a69a5683ac383acdc8d942cf32c3f93 F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246 -F ext/fts5/fts5_index.c 4fdbc0a321e3a1d73741a623d7aea4db78d6a86d +F ext/fts5/fts5_index.c c77882ab38d698d5147cef96fa67a2121d77c0b3 F ext/fts5/fts5_main.c 53116cffeb26898832ff7700cc5ebac5fe085d32 F ext/fts5/fts5_storage.c 120f7b143688b5b7710dacbd48cff211609b8059 F ext/fts5/fts5_tcl.c 6da58d6e8f42a93c4486b5ba9b187a7f995dee37 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5c14d447055bb337428eb1fe0a2934abee381829 -R afaa284829583439d3c828667e0babfd -U drh -Z 4d08d7f777c595957317ee86b8c88bc8 +P c5566bb39c8d9b58f77380b81a873429575c7d5c +R 8c1c5df148af89b61b9ed44613e1cccf +U dan +Z c6128292281c17956918fd20bfe641c1 diff --git a/manifest.uuid b/manifest.uuid index 544e794a7a..7b46927912 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c5566bb39c8d9b58f77380b81a873429575c7d5c \ No newline at end of file +3a9f076250d9559d8ea94ba44095ba3ddbc5542d \ No newline at end of file From 94f26a1e22cc5ffc0952948d254dc1f3b7c1d142 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Sep 2015 12:32:56 +0000 Subject: [PATCH 21/29] Fix compiler warnings. FossilOrigin-Name: d1a0783854d2e9272320d9ddfa58362532f58d1a --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/update.c | 8 +++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 0e0acb1ea1..ded8386abb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schange\sinto\sthis\sbranch. -D 2015-09-29T11:59:25.306 +C Fix\scompiler\swarnings. +D 2015-09-29T12:32:56.672 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -399,7 +399,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f -F src/update.c 4fb82a2440bd8d66f266ada1ef31a2fcde48bd4f +F src/update.c e0169d20524cf3663c9c6d952e61baf3c03ae797 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f61203bc0fb0b62e12d6270e8d9063e445a5a252 c5566bb39c8d9b58f77380b81a873429575c7d5c -R bc0d8f7ab7b6ff885dd78977e4d43e2a -U dan -Z 5823814221d6aa9768fead2d22b2e0e9 +P b519c0d67a8fc39d65c17eccc9300a6187bd5661 +R 3b0dc7b7710e7cf4f943bdd9f5967b17 +U drh +Z 7521a63b646e7d2736834b9d13be676e diff --git a/manifest.uuid b/manifest.uuid index 8c0cdf89ec..eeb5e662b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b519c0d67a8fc39d65c17eccc9300a6187bd5661 \ No newline at end of file +d1a0783854d2e9272320d9ddfa58362532f58d1a \ No newline at end of file diff --git a/src/update.c b/src/update.c index ebf0d6c8ea..c90320f0b2 100644 --- a/src/update.c +++ b/src/update.c @@ -134,9 +134,9 @@ void sqlite3Update( /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ - int regOldRowid; /* The old rowid */ - int regNewRowid; /* The new rowid */ - int regNew; /* Content of the NEW.* table in triggers */ + int regOldRowid = 0; /* The old rowid */ + int regNewRowid = 0; /* The new rowid */ + int regNew = 0; /* Content of the NEW.* table in triggers */ int regOld = 0; /* Content of OLD.* table in triggers */ int regRowSet = 0; /* Rowset of rows to be updated */ int regKey = 0; /* composite PRIMARY KEY value */ @@ -507,7 +507,6 @@ void sqlite3Update( newmask = sqlite3TriggerColmask( pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); - /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/ for(i=0; inCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); @@ -727,7 +726,6 @@ static void updateVirtualTable( int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ int bOnePass; /* True to use onepass strategy */ int addr; /* Address of OP_OpenEphemeral */ - NameContext sNC; /* Allocate nArg registers to martial the arguments to VUpdate. Then ** create and open the ephemeral table in which the records created from From c149f18f4da6228c78513d164623d8accf4088a2 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Sep 2015 13:25:15 +0000 Subject: [PATCH 22/29] Create the sqlite3IsToplevel(Parse*) interface to check to see if a top-level VDBE is being coded (versus a trigger) and use that interface. FossilOrigin-Name: 59662cd2b65255a30e1a420331c07c51b644621a --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/delete.c | 2 +- src/insert.c | 2 +- src/sqliteInt.h | 2 ++ src/update.c | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index ded8386abb..353278a1a2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings. -D 2015-09-29T12:32:56.672 +C Create\sthe\ssqlite3IsToplevel(Parse*)\sinterface\sto\scheck\sto\ssee\sif\sa\stop-level\nVDBE\sis\sbeing\scoded\s(versus\sa\strigger)\sand\suse\sthat\sinterface. +D 2015-09-29T13:25:15.973 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7 -F src/delete.c 174b140317915e0e8c6e2eff28158eecf95c53d8 +F src/delete.c 46bb5e217f83af68574ccb613421485578c41ba8 F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f @@ -300,7 +300,7 @@ F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 9748a37e058256eb2ead69f028ab85ebf203ad15 +F src/insert.c 81d6bf397c05b4e8ddc4af2ff6637c113ee7e37a F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012 @@ -345,7 +345,7 @@ F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 -F src/sqliteInt.h 5afc6e50402be1e0a870f28e1cd8b32eb9db590f +F src/sqliteInt.h b6516bb2727876348b4e05aadd12237797626270 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -399,7 +399,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f -F src/update.c e0169d20524cf3663c9c6d952e61baf3c03ae797 +F src/update.c d8f0afe1a1c66b97cbd87e5236f4e71d35ab4840 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b519c0d67a8fc39d65c17eccc9300a6187bd5661 -R 3b0dc7b7710e7cf4f943bdd9f5967b17 +P d1a0783854d2e9272320d9ddfa58362532f58d1a +R a4e26d59514db031d207946929f0dada U drh -Z 7521a63b646e7d2736834b9d13be676e +Z ab43f3a6d7f071ac781590ae89cc31de diff --git a/manifest.uuid b/manifest.uuid index eeb5e662b8..906f2b5996 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d1a0783854d2e9272320d9ddfa58362532f58d1a \ No newline at end of file +59662cd2b65255a30e1a420331c07c51b644621a \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index ed843c1a75..6a512017e7 100644 --- a/src/delete.c +++ b/src/delete.c @@ -518,7 +518,7 @@ void sqlite3DeleteFrom( sqlite3VdbeChangeP5(v, OE_Abort); assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE && pParse==sqlite3ParseToplevel(pParse) ){ + if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ pParse->isMultiWrite = 0; } }else diff --git a/src/insert.c b/src/insert.c index 53b429c1f4..3ade95e4ec 100644 --- a/src/insert.c +++ b/src/insert.c @@ -260,7 +260,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){ /* This routine is never called during trigger-generation. It is ** only called from the top-level */ assert( pParse->pTriggerTab==0 ); - assert( pParse==sqlite3ParseToplevel(pParse) ); + assert( sqlite3IsToplevel(pParse) ); assert( v ); /* We failed long ago if this is not so */ for(p = pParse->pAinc; p; p = p->pNext){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 747f19b39a..b32cc21bbb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3504,6 +3504,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) +# define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) @@ -3513,6 +3514,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int); # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p +# define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 #endif diff --git a/src/update.c b/src/update.c index c90320f0b2..ba5d0380af 100644 --- a/src/update.c +++ b/src/update.c @@ -764,7 +764,7 @@ static void updateVirtualTable( ** above. Also, if this is a top-level parse (not a trigger), clear the ** multi-write flag so that the VM does not open a statement journal */ sqlite3VdbeChangeToNoop(v, addr); - if( sqlite3ParseToplevel(pParse)==pParse ){ + if( sqlite3IsToplevel(pParse) ){ pParse->isMultiWrite = 0; } }else{ From e2b7d7a0a1dd21a3fc2d9510532dfd1fb8b07382 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Sep 2015 15:50:04 +0000 Subject: [PATCH 23/29] Remove dead code, replacing with assert() statements that make sure the code really was dead. FossilOrigin-Name: 0e317dda5dfd35b742afd70dacb5bfb39aa3fc4a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/select.c | 38 +++++++++++++++----------------------- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 353278a1a2..fc874db8fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Create\sthe\ssqlite3IsToplevel(Parse*)\sinterface\sto\scheck\sto\ssee\sif\sa\stop-level\nVDBE\sis\sbeing\scoded\s(versus\sa\strigger)\sand\suse\sthat\sinterface. -D 2015-09-29T13:25:15.973 +C Remove\sdead\scode,\sreplacing\swith\sassert()\sstatements\sthat\smake\ssure\sthe\ncode\sreally\swas\sdead. +D 2015-09-29T15:50:04.571 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -340,7 +340,7 @@ F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 33230303f5f32430ee971a6fcc6a370e4a93ae1a +F src/select.c e49f4af9748c9e0cc1bf864b4190aa94841c8409 F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d1a0783854d2e9272320d9ddfa58362532f58d1a -R a4e26d59514db031d207946929f0dada +P 59662cd2b65255a30e1a420331c07c51b644621a +R cec1f3888d085a601a5cfb22d1afd716 U drh -Z ab43f3a6d7f071ac781590ae89cc31de +Z 0ae71f6c4f92a526967039eb67c1881e diff --git a/manifest.uuid b/manifest.uuid index 906f2b5996..e040f5ddfc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -59662cd2b65255a30e1a420331c07c51b644621a \ No newline at end of file +0e317dda5dfd35b742afd70dacb5bfb39aa3fc4a \ No newline at end of file diff --git a/src/select.c b/src/select.c index f410a3b329..8430a00f37 100644 --- a/src/select.c +++ b/src/select.c @@ -4221,17 +4221,9 @@ static int selectExpander(Walker *pWalker, Select *p){ */ for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ Table *pTab; - assert( pFrom->fg.isRecursive==0 || pFrom->pTab ); + assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); if( pFrom->fg.isRecursive ) continue; - if( pFrom->pTab!=0 ){ - /* This statement has already been prepared. There is no need - ** to go further. */ - assert( i==0 ); -#ifndef SQLITE_OMIT_CTE - selectPopWith(pWalker, p); -#endif - return WRC_Prune; - } + assert( pFrom->pTab==0 ); #ifndef SQLITE_OMIT_CTE if( withExpand(pWalker, pFrom) ) return WRC_Abort; if( pFrom->pTab ) {} else @@ -4523,19 +4515,19 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ struct SrcList_item *pFrom; assert( p->selFlags & SF_Resolved ); - if( (p->selFlags & SF_HasTypeInfo)==0 ){ - p->selFlags |= SF_HasTypeInfo; - pParse = pWalker->pParse; - pTabList = p->pSrc; - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ - /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->pSelect; - if( pSel ){ - while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab, pSel); - } + assert( (p->selFlags & SF_HasTypeInfo)==0 ); + p->selFlags |= SF_HasTypeInfo; + pParse = pWalker->pParse; + pTabList = p->pSrc; + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + assert( pTab!=0 ); + if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ + /* A sub-query in the FROM clause of a SELECT */ + Select *pSel = pFrom->pSelect; + if( pSel ){ + while( pSel->pPrior ) pSel = pSel->pPrior; + selectAddColumnTypeAndCollation(pParse, pTab, pSel); } } } From 65c4f591bee40949a936443ce7c21ae0cc04cf1b Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 29 Sep 2015 16:41:23 +0000 Subject: [PATCH 24/29] Ensure that the xSavepoint() virtual table method is correctly invoked if there are already open savepoints (or statement transactions) the first time a virtual table is written within a transaction. FossilOrigin-Name: 77948b5eceab92a77c39d0864ac15ad453a76fd7 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vtab.c | 2 ++ test/fts3conf.test | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ae2961c2dc..8f94f97b0e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\soff-by-one\serror\sin\stest\sfunction\sfts5_decode(). -D 2015-09-29T12:19:51.430 +C Ensure\sthat\sthe\sxSavepoint()\svirtual\stable\smethod\sis\scorrectly\sinvoked\sif\sthere\sare\salready\sopen\ssavepoints\s(or\sstatement\stransactions)\sthe\sfirst\stime\sa\svirtual\stable\sis\swritten\swithin\sa\stransaction. +D 2015-09-29T16:41:23.689 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -412,7 +412,7 @@ F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915 F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 -F src/vtab.c 2ecfe020c10e0a0c7b078203fdba2fae844744bc +F src/vtab.c 9a6d8818c8a2477ce547f064701b5e955b25d894 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 @@ -690,7 +690,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c -F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de +F test/fts3conf.test 6c7faa66bfb0e90c2c073c029c08b58ea5023922 F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 @@ -1388,7 +1388,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c5566bb39c8d9b58f77380b81a873429575c7d5c -R 8c1c5df148af89b61b9ed44613e1cccf +P 3a9f076250d9559d8ea94ba44095ba3ddbc5542d +R 756fa6b717967f5524da70e2a3635809 U dan -Z c6128292281c17956918fd20bfe641c1 +Z 7ea154fd75a363e5d81a988ffd47237f diff --git a/manifest.uuid b/manifest.uuid index 7b46927912..975366ad0c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3a9f076250d9559d8ea94ba44095ba3ddbc5542d \ No newline at end of file +77948b5eceab92a77c39d0864ac15ad453a76fd7 \ No newline at end of file diff --git a/src/vtab.c b/src/vtab.c index 041805ca49..cc293e8064 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -937,7 +937,9 @@ int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ if( rc==SQLITE_OK ){ rc = pModule->xBegin(pVTab->pVtab); if( rc==SQLITE_OK ){ + int iSvpt = db->nStatement + db->nSavepoint; addToVTrans(db, pVTab); + if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); } } } diff --git a/test/fts3conf.test b/test/fts3conf.test index e91efbefbe..25c0a48b61 100644 --- a/test/fts3conf.test +++ b/test/fts3conf.test @@ -178,4 +178,38 @@ do_execsql_test 3.8 { SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one' } {X'0200000002000000'} +#------------------------------------------------------------------------- +# Test that the xSavepoint is invoked correctly if the first write +# operation within a transaction is to a virtual table. +# +do_catchsql_test 4.1.1 { + CREATE VIRTUAL TABLE t0 USING fts4; + BEGIN; + INSERT INTO t0(rowid, content) SELECT + 1, 'abc' UNION ALL SELECT + 2, 'def' UNION ALL SELECT + 1, 'ghi'; +} {1 {constraint failed}} +do_execsql_test 4.1.2 { + COMMIT; +} +do_execsql_test 4.1.3 { + SELECT * FROM t0 WHERE t0 MATCH 'abc'; + INSERT INTO t0(t0) VALUES('integrity-check'); +} {} + +do_execsql_test 4.2.1 { + CREATE VIRTUAL TABLE t01 USING fts4; + BEGIN; + SAVEPOINT abc; + INSERT INTO t01 VALUES('a b c'); + ROLLBACK TO abc; + COMMIT; +} +do_execsql_test 4.2.2 { + SELECT * FROM t01 WHERE t01 MATCH 'b'; + INSERT INTO t01(t01) VALUES('integrity-check'); +} {} + finish_test + From 4b92f98ccc298dfcd00c323fa912a22876a4e245 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 29 Sep 2015 17:20:14 +0000 Subject: [PATCH 25/29] Use symbolic names XN_ROWID and XN_EXPR in place of the (-1) and (-2) magic numbers in Index.aiColumn[]. Add asserts to help verify that Index.aiColumn[] is always used correctly. Fix one place in FK processing where Index.aiColumn[] was not being used correctly. FossilOrigin-Name: 7d272aa62cd4cbbf4b5d04e3b918de27671e8301 --- manifest | 34 +++++++++++++++++----------------- manifest.uuid | 2 +- src/build.c | 8 ++++---- src/delete.c | 4 ++-- src/expr.c | 12 ++++++------ src/fkey.c | 11 ++++++++++- src/insert.c | 12 +++++++----- src/pragma.c | 2 +- src/sqliteInt.h | 6 ++++++ src/update.c | 2 +- src/vdbeblob.c | 2 +- src/where.c | 20 ++++++++++++-------- src/wherecode.c | 6 +++--- 13 files changed, 71 insertions(+), 50 deletions(-) diff --git a/manifest b/manifest index 35e142bdf3..cbc2fc7692 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_index_info.idxFlags\sfield,\sallowing\sxBestIndex()\simplementations\sto\sspecify\sto\sSQLite\sthat\sa\sstrategy\smay\svisit\sat\smost\sone\srow.\sAdd\ssupport\sfor\sthis\sto\sfts3/4.\sOmit\sthe\sstatement\sjournal\sfrom\svirtual\stable\sUPDATE\sand\sDELETE\soperations\sthat\sare\sguaranteed\snot\sto\saffect\smore\sthan\sone\srow. -D 2015-09-29T16:47:53.132 +C Use\ssymbolic\snames\sXN_ROWID\sand\sXN_EXPR\sin\splace\sof\sthe\s(-1)\sand\s(-2)\nmagic\snumbers\sin\sIndex.aiColumn[].\s\sAdd\sasserts\sto\shelp\sverify\sthat\nIndex.aiColumn[]\sis\salways\sused\scorrectly.\s\sFix\sone\splace\sin\sFK\sprocessing\nwhere\sIndex.aiColumn[]\swas\snot\sbeing\sused\scorrectly. +D 2015-09-29T17:20:14.958 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -285,22 +285,22 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 -F src/build.c 361f58b73aad7804f5706bf62d210bd9cd608041 +F src/build.c 0549b56722f15c146ca21f82a33838365c2031f0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7 -F src/delete.c 46bb5e217f83af68574ccb613421485578c41ba8 -F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863 +F src/delete.c 35c939eb8bacc9dd8a6715964e5f69feb8c20e44 +F src/expr.c 36381822e617cb3586d4be1af2cbc3dd5f2b84eb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f +F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0 F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 81d6bf397c05b4e8ddc4af2ff6637c113ee7e37a +F src/insert.c a9b7f200081fa1b482a4ccac05165e10371ae9e0 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012 @@ -333,7 +333,7 @@ F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083 -F src/pragma.c 577f70c3899ee6fc2e5a4c37158c69c1c23f71e7 +F src/pragma.c 234814978bcd35bce6e2874dfb2f5b5e28e7fb38 F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a @@ -345,7 +345,7 @@ F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 -F src/sqliteInt.h b6516bb2727876348b4e05aadd12237797626270 +F src/sqliteInt.h 681f38fc0decba6edcf3bad230e76fa5bf55a7bf F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -399,7 +399,7 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6 F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f -F src/update.c d8f0afe1a1c66b97cbd87e5236f4e71d35ab4840 +F src/update.c a134027f59c7eb6e63ed18e2d5dd8ef0ce7f8ff8 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 @@ -408,7 +408,7 @@ F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649 -F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a +F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6 F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915 F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 @@ -417,9 +417,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba -F src/where.c b7f928b6b8ce091f385ba5ac2394928608431550 +F src/where.c 4c4646675e794ac71e701289edefd7cd81bac844 F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647 -F src/wherecode.c a87238178f8c300fd27afec54326ea8d0a18baa2 +F src/wherecode.c a32bf1f304f6328e3eefcb82e70bd86836cff343 F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 77948b5eceab92a77c39d0864ac15ad453a76fd7 0e317dda5dfd35b742afd70dacb5bfb39aa3fc4a -R d39a034a4821b5c42018f04d74a8aeb2 -U dan -Z 28a594c5d9670d5cb6f4428303834152 +P a1d08fd3d0419da8c22355d48c6d83eed6fd7e07 +R 52625b1830d3c09e89f8505fdc133a11 +U drh +Z 6b238da064de6e3b5f5d0b4365b7caf0 diff --git a/manifest.uuid b/manifest.uuid index 2b74ea5ad5..5810842471 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a1d08fd3d0419da8c22355d48c6d83eed6fd7e07 \ No newline at end of file +7d272aa62cd4cbbf4b5d04e3b918de27671e8301 \ No newline at end of file diff --git a/src/build.c b/src/build.c index c0bd81b1a0..ea89e501dc 100644 --- a/src/build.c +++ b/src/build.c @@ -3136,7 +3136,7 @@ Index *sqlite3CreateIndex( /* Analyze the list of expressions that form the terms of the index and ** report any errors. In the common case where the expression is exactly ** a table column, store that column in aiColumn[]. For general expressions, - ** populate pIndex->aColExpr and store -2 in aiColumn[]. + ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. ** ** TODO: Issue a warning if two or more columns of the index are identical. ** TODO: Issue a warning if the table primary key is used as part of the @@ -3165,8 +3165,8 @@ Index *sqlite3CreateIndex( pListItem = &pCopy->a[i]; } } - j = -2; - pIndex->aiColumn[i] = -2; + j = XN_EXPR; + pIndex->aiColumn[i] = XN_EXPR; pIndex->uniqNotNull = 0; }else{ j = pCExpr->iColumn; @@ -3219,7 +3219,7 @@ Index *sqlite3CreateIndex( } assert( i==pIndex->nColumn ); }else{ - pIndex->aiColumn[i] = -1; + pIndex->aiColumn[i] = XN_ROWID; pIndex->azColl[i] = "BINARY"; } sqlite3DefaultRowEst(pIndex); diff --git a/src/delete.c b/src/delete.c index 6a512017e7..faef3a814e 100644 --- a/src/delete.c +++ b/src/delete.c @@ -422,7 +422,7 @@ void sqlite3DeleteFrom( /* Extract the rowid or primary key for the current row */ if( pPk ){ for(i=0; iaiColumn[i]>=(-1) ); + assert( pPk->aiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i], iPk+i); } @@ -858,7 +858,7 @@ int sqlite3GenerateIndexKey( for(j=0; jaiColumn[j]==pIdx->aiColumn[j] - && pPrior->aiColumn[j]>=(-1) + && pPrior->aiColumn[j]!=XN_EXPR ){ /* This column was already computed by the previous index */ continue; diff --git a/src/expr.c b/src/expr.c index 3141cd9dbd..b52e814f3c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2443,15 +2443,15 @@ void sqlite3ExprCodeLoadIndexColumn( int regOut /* Store the index column value in this register */ ){ i16 iTabCol = pIdx->aiColumn[iIdxCol]; - if( iTabCol>=(-1) ){ + if( iTabCol==XN_EXPR ){ + assert( pIdx->aColExpr ); + assert( pIdx->aColExpr->nExpr>iIdxCol ); + pParse->iSelfTab = iTabCur; + sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); + }else{ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, iTabCol, regOut); - return; } - assert( pIdx->aColExpr ); - assert( pIdx->aColExpr->nExpr>iIdxCol ); - pParse->iSelfTab = iTabCur; - sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); } /* diff --git a/src/fkey.c b/src/fkey.c index a087889f4c..b55e2a9813 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -252,6 +252,8 @@ int sqlite3FkLocateIndex( char *zDfltColl; /* Def. collation for column */ char *zIdxCol; /* Name of indexed column */ + if( iCol<0 ) break; /* No foreign keys against expression indexes */ + /* If the index uses a collation sequence that is different from ** the default collation sequence for the column, this index is ** unusable. Bail out early in this case. */ @@ -404,6 +406,7 @@ static void fkLookupParent( for(i=0; iaiColumn[i]+1+regData; + assert( pIdx->aiColumn[i]>=0 ); assert( aiCol[i]!=pTab->iPKey ); if( pIdx->aiColumn[i]==pTab->iPKey ){ /* The parent key is a composite key that includes the IPK column */ @@ -612,6 +615,7 @@ static void fkScanChildren( assert( pIdx!=0 ); for(i=0; inKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; + assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); @@ -931,6 +935,7 @@ void sqlite3FkCheck( if( aiCol[i]==pTab->iPKey ){ aiCol[i] = -1; } + assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Request permission to read the parent key columns. If the ** authorization callback returns SQLITE_IGNORE, behave as if any @@ -1062,7 +1067,10 @@ u32 sqlite3FkOldmask( Index *pIdx = 0; sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); if( pIdx ){ - for(i=0; inKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); + for(i=0; inKeyCol; i++){ + assert( pIdx->aiColumn[i]>=0 ); + mask |= COLUMN_MASK(pIdx->aiColumn[i]); + } } } } @@ -1185,6 +1193,7 @@ static Trigger *fkActionTrigger( iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); + assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; diff --git a/src/insert.c b/src/insert.c index 3ade95e4ec..785e57d02c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -90,11 +90,11 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ i16 x = pIdx->aiColumn[n]; if( x>=0 ){ pIdx->zColAff[n] = pTab->aCol[x].affinity; - }else if( x==(-1) ){ + }else if( x==XN_ROWID ){ pIdx->zColAff[n] = SQLITE_AFF_INTEGER; }else{ char aff; - assert( x==(-2) ); + assert( x==XN_EXPR ); assert( pIdx->aColExpr!=0 ); aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); if( aff==0 ) aff = SQLITE_AFF_BLOB; @@ -1408,13 +1408,13 @@ void sqlite3GenerateConstraintChecks( for(i=0; inColumn; i++){ int iField = pIdx->aiColumn[i]; int x; - if( iField==(-2) ){ + if( iField==XN_EXPR ){ pParse->ckBase = regNewData+1; sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); pParse->ckBase = 0; VdbeComment((v, "%s column %d", pIdx->zName, i)); }else{ - if( iField==(-1) || iField==pTab->iPKey ){ + if( iField==XN_ROWID || iField==pTab->iPKey ){ if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ x = regNewData; regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; @@ -1473,6 +1473,7 @@ void sqlite3GenerateConstraintChecks( ** store it in registers regR..regR+nPk-1 */ if( pIdx!=pPk ){ for(i=0; inKeyCol; i++){ + assert( pPk->aiColumn[i]>=0 ); x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); VdbeComment((v, "%s.%s", pTab->zName, @@ -1494,6 +1495,7 @@ void sqlite3GenerateConstraintChecks( for(i=0; inKeyCol; i++){ char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); x = pPk->aiColumn[i]; + assert( x>=0 ); if( i==(pPk->nKeyCol-1) ){ addrJump = addrUniqueOk; op = OP_Eq; @@ -1745,7 +1747,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ return 0; /* Different columns indexed */ } - if( pSrc->aiColumn[i]==(-2) ){ + if( pSrc->aiColumn[i]==XN_EXPR ){ assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, pDest->aColExpr->a[i].pExpr, -1)!=0 ){ diff --git a/src/pragma.c b/src/pragma.c index 1edc66daf8..e5e7e54a29 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1524,7 +1524,7 @@ void sqlite3Pragma( int kk; for(kk=0; kknKeyCol; kk++){ int iCol = pIdx->aiColumn[kk]; - assert( iCol!=(-1) && iColnCol ); + assert( iCol!=XN_ROWID && iColnCol ); if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); VdbeCoverage(v); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b32cc21bbb..6c9bb06f69 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1917,6 +1917,12 @@ struct Index { /* Return true if index X is a UNIQUE index */ #define IsUniqueIndex(X) ((X)->onError!=OE_None) +/* The Index.aiColumn[] values are normally positive integer. But +** there are some negative values that have special meaning: +*/ +#define XN_ROWID (-1) /* Indexed column is the rowid */ +#define XN_EXPR (-2) /* Indexed column is an expression */ + /* ** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the diff --git a/src/update.c b/src/update.c index ba5d0380af..74f247bb28 100644 --- a/src/update.c +++ b/src/update.c @@ -384,7 +384,7 @@ void sqlite3Update( if( pWInfo==0 ) goto update_cleanup; okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); for(i=0; iaiColumn[i]>=(-1) ); + assert( pPk->aiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], iPk+i); } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 2cdc3edb00..30a329189e 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -248,7 +248,7 @@ int sqlite3_blob_open( int j; for(j=0; jnKeyCol; j++){ /* FIXME: Be smarter about indexes that use expressions */ - if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==(-2) ){ + if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){ zFault = "indexed"; } } diff --git a/src/where.c b/src/where.c index 2be05a6752..af8e2f35fd 100644 --- a/src/where.c +++ b/src/where.c @@ -189,12 +189,12 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ while( pScan->iEquiv<=pScan->nEquiv ){ iCur = pScan->aiCur[pScan->iEquiv-1]; iColumn = pScan->aiColumn[pScan->iEquiv-1]; - if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0; + if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn - && (iColumn!=(-2) + && (iColumn!=XN_EXPR || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ @@ -288,7 +288,7 @@ static WhereTerm *whereScanInit( if( pIdx ){ j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; } if( pIdx && iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; @@ -727,7 +727,7 @@ static void constructAutomaticIndex( } } assert( n==nKeyCol ); - pIdx->aiColumn[n] = -1; + pIdx->aiColumn[n] = XN_ROWID; pIdx->azColl[n] = "BINARY"; /* Create the automatic index */ @@ -2242,7 +2242,9 @@ static int whereLoopAddBtreeIndex( int iCol = pProbe->aiColumn[saved_nEq]; pNew->wsFlags |= WHERE_COLUMN_EQ; assert( saved_nEq==pNew->u.btree.nEq ); - if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ + if( iCol==XN_ROWID + || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) + ){ if( iCol>=0 && pProbe->uniqNotNull==0 ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ @@ -2442,7 +2444,7 @@ static int indexMightHelpWithOrderBy( } }else if( (aColExpr = pIndex->aColExpr)!=0 ){ for(jj=0; jjnKeyCol; jj++){ - if( pIndex->aiColumn[jj]!=(-2) ) continue; + if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ return 1; } @@ -3230,7 +3232,8 @@ static i8 wherePathSatisfiesOrderBy( nKeyCol = pIndex->nKeyCol; nColumn = pIndex->nColumn; assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); - assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable)); + assert( pIndex->aiColumn[nColumn-1]==XN_ROWID + || !HasRowid(pIndex->pTable)); isOrderDistinct = IsUniqueIndex(pIndex); } @@ -3262,7 +3265,7 @@ static i8 wherePathSatisfiesOrderBy( revIdx = pIndex->aSortOrder[j]; if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; }else{ - iColumn = -1; + iColumn = XN_ROWID; revIdx = 0; } @@ -4562,6 +4565,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ if( !HasRowid(pTab) ){ Index *pPk = sqlite3PrimaryKeyIndex(pTab); x = pPk->aiColumn[x]; + assert( x>=0 ); } x = sqlite3ColumnOfIndex(pIdx, x); if( x>=0 ){ diff --git a/src/wherecode.c b/src/wherecode.c index f9b56e7c83..a6c45f0321 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -46,8 +46,8 @@ static void explainAppendTerm( */ static const char *explainIndexColumnName(Index *pIdx, int i){ i = pIdx->aiColumn[i]; - if( i==(-2) ) return ""; - if( i==(-1) ) return "rowid"; + if( i==XN_EXPR ) return ""; + if( i==XN_ROWID ) return "rowid"; return pIdx->pTable->aCol[i].zName; } @@ -514,7 +514,7 @@ static int codeAllEqualityTerms( sqlite3VdbeJumpHere(v, j); for(j=0; jaiColumn[j]==(-2) ); + testcase( pIdx->aiColumn[j]==XN_EXPR ); VdbeComment((v, "%s", explainIndexColumnName(pIdx, j))); } } From d95bb39c52915024723995f01bcdb7c0ed15caba Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 30 Sep 2015 11:19:05 +0000 Subject: [PATCH 26/29] Improve error handling in shell command ".tables". FossilOrigin-Name: 31a91ee7d32af8580a170903eb857ed9222fdb0a --- manifest | 14 ++++++------- manifest.uuid | 2 +- src/shell.c | 55 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index cbc2fc7692..0014c03a25 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\ssymbolic\snames\sXN_ROWID\sand\sXN_EXPR\sin\splace\sof\sthe\s(-1)\sand\s(-2)\nmagic\snumbers\sin\sIndex.aiColumn[].\s\sAdd\sasserts\sto\shelp\sverify\sthat\nIndex.aiColumn[]\sis\salways\sused\scorrectly.\s\sFix\sone\splace\sin\sFK\sprocessing\nwhere\sIndex.aiColumn[]\swas\snot\sbeing\sused\scorrectly. -D 2015-09-29T17:20:14.958 +C Improve\serror\shandling\sin\sshell\scommand\s".tables". +D 2015-09-30T11:19:05.250 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -341,7 +341,7 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c e49f4af9748c9e0cc1bf864b4190aa94841c8409 -F src/shell.c a11b20da4c6630e0e8f83c47ce36f717dd0422f0 +F src/shell.c dfd18e56fcb88dd79378774e9bc3246a9bd52243 F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 64350bf36833a56ad675e27392a913f417c5c308 @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a1d08fd3d0419da8c22355d48c6d83eed6fd7e07 -R 52625b1830d3c09e89f8505fdc133a11 -U drh -Z 6b238da064de6e3b5f5d0b4365b7caf0 +P 7d272aa62cd4cbbf4b5d04e3b918de27671e8301 +R 182210397719a41b40c126f91ca11c51 +U dan +Z f61744228c664ef1bbc36bc13dfb9d49 diff --git a/manifest.uuid b/manifest.uuid index 5810842471..d393ee6596 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d272aa62cd4cbbf4b5d04e3b918de27671e8301 \ No newline at end of file +31a91ee7d32af8580a170903eb857ed9222fdb0a \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 02938eb1e6..96d0ab65f7 100644 --- a/src/shell.c +++ b/src/shell.c @@ -2612,6 +2612,22 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ return 0; } +/* +** Print the current sqlite3_errmsg() value to stderr and return 1. +*/ +static int shellDatabaseError(sqlite3 *db){ + const char *zErr = sqlite3_errmsg(db); + fprintf(stderr, "Error: %s\n", zErr); + return 1; +} + +/* +** Print an out-of-memory message to stderr and return 1. +*/ +static int shellNomemError(void){ + fprintf(stderr, "Error: out of memory\n"); + return 1; +} /* ** If an input line begins with "." then invoke this routine to @@ -3713,13 +3729,17 @@ static int do_meta_command(char *zLine, ShellState *p){ int ii; open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); - if( rc ) return rc; + if( rc ) return shellDatabaseError(p->db); + + /* Create an SQL statement to query for the list of tables in the + ** main and all attached databases where the table name matches the + ** LIKE pattern bound to variable "?1". */ zSql = sqlite3_mprintf( "SELECT name FROM sqlite_master" " WHERE type IN ('table','view')" " AND name NOT LIKE 'sqlite_%%'" " AND name LIKE ?1"); - while( sqlite3_step(pStmt)==SQLITE_ROW ){ + while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1); if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue; if( strcmp(zDbName,"temp")==0 ){ @@ -3738,11 +3758,17 @@ static int do_meta_command(char *zLine, ShellState *p){ " AND name LIKE ?1", zSql, zDbName, zDbName); } } - sqlite3_finalize(pStmt); - zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + rc = sqlite3_finalize(pStmt); + if( zSql && rc==SQLITE_OK ){ + zSql = sqlite3_mprintf("%z ORDER BY 1", zSql); + if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + } sqlite3_free(zSql); - if( rc ) return rc; + if( !zSql ) return shellNomemError(); + if( rc ) return shellDatabaseError(p->db); + + /* Run the SQL statement prepared by the above block. Store the results + ** as an array of nul-terminated strings in azResult[]. */ nRow = nAlloc = 0; azResult = 0; if( nArg>1 ){ @@ -3756,17 +3782,25 @@ static int do_meta_command(char *zLine, ShellState *p){ int n2 = nAlloc*2 + 10; azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); if( azNew==0 ){ - fprintf(stderr, "Error: out of memory\n"); + rc = shellNomemError(); break; } nAlloc = n2; azResult = azNew; } azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); - if( azResult[nRow] ) nRow++; + if( 0==azResult[nRow] ){ + rc = shellNomemError(); + break; + } + nRow++; } - sqlite3_finalize(pStmt); - if( nRow>0 ){ + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ + rc = shellDatabaseError(p->db); + } + + /* Pretty-print the contents of array azResult[] to the output */ + if( rc==0 && nRow>0 ){ int len, maxlen = 0; int i, j; int nPrintCol, nPrintRow; @@ -3785,6 +3819,7 @@ static int do_meta_command(char *zLine, ShellState *p){ fprintf(p->out, "\n"); } } + for(ii=0; ii Date: Wed, 30 Sep 2015 12:59:12 +0000 Subject: [PATCH 27/29] Clear the BTCF_ValidNKey flag when putting a cursor into REQUIRESEEK state. Fix for [1b266395]. FossilOrigin-Name: a6d5e4e8693bea3739c35fe9769ac9abfb9ed056 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 2 +- test/fkey1.test | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0014c03a25..bc26811e33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\serror\shandling\sin\sshell\scommand\s".tables". -D 2015-09-30T11:19:05.250 +C Clear\sthe\sBTCF_ValidNKey\sflag\swhen\sputting\sa\scursor\sinto\sREQUIRESEEK\sstate.\sFix\sfor\s[1b266395]. +D 2015-09-30T12:59:12.171 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -282,7 +282,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 164583151135a3764672c2c25aa8e4fa06bdb12b +F src/btree.c dd877a85fc968c5f069d0cd133c6b420ec3112fa F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 F src/build.c 0549b56722f15c146ca21f82a33838365c2031f0 @@ -621,7 +621,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787 F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 -F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2 +F test/fkey1.test 13e3d48236a2b9f5c5ebd232eef9b3ab682a8a2c F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7d272aa62cd4cbbf4b5d04e3b918de27671e8301 -R 182210397719a41b40c126f91ca11c51 +P 31a91ee7d32af8580a170903eb857ed9222fdb0a +R 4a74a22a0c922f420238bb3d30a78646 U dan -Z f61744228c664ef1bbc36bc13dfb9d49 +Z 36f983bdf307cdff5171dc6e84fb5a56 diff --git a/manifest.uuid b/manifest.uuid index d393ee6596..fafa0fcdff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -31a91ee7d32af8580a170903eb857ed9222fdb0a \ No newline at end of file +a6d5e4e8693bea3739c35fe9769ac9abfb9ed056 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index c7d6fabba6..bf777aa969 100644 --- a/src/btree.c +++ b/src/btree.c @@ -661,7 +661,7 @@ static int saveCursorPosition(BtCursor *pCur){ pCur->eState = CURSOR_REQUIRESEEK; } - invalidateOverflowCache(pCur); + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast); return rc; } diff --git a/test/fkey1.test b/test/fkey1.test index 0bd4939eb5..e10781ac52 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -151,4 +151,38 @@ do_execsql_test fkey1-4.2 { PRAGMA table_info="""1"; } {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0} +#------------------------------------------------------------------------- +# +do_execsql_test fkey1-5.1 { + CREATE TABLE t11( + x INTEGER PRIMARY KEY, + parent REFERENCES t11 ON DELETE CASCADE + ); + INSERT INTO t11 VALUES (1, NULL), (2, 1), (3, 2); +} {} + +# The REPLACE part of this statement deletes the row (2, 1). Then the +# DELETE CASCADE caused by deleting that row removes the (3, 2) row. Which +# would have been the parent of the new row being inserted. Causing an +# FK violation. +# +do_catchsql_test fkey1-5.2 { + INSERT OR REPLACE INTO t11 VALUES (2, 3); +} {1 {FOREIGN KEY constraint failed}} + +# A similar test to the above. +do_execsql_test fkey1-5.3 { + CREATE TABLE Foo ( + Id INTEGER PRIMARY KEY, + ParentId INTEGER REFERENCES Foo(Id) ON DELETE CASCADE, C1 + ); + INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (1, null, 'A'); + INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 1, 'A-2-1'); + INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (3, 2, 'A-3-2'); + INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (4, 3, 'A-4-3'); +} +do_catchsql_test fkey1-5.4 { + INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3'); +} {1 {FOREIGN KEY constraint failed}} + finish_test From 9b5351d439f6a6ee07e1ea244d693eb2a96cd821 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Sep 2015 14:19:08 +0000 Subject: [PATCH 28/29] Fix an assert() in btree.c that is only true for non-corrupt databases. FossilOrigin-Name: 29f7227ff127202c53fe7c3b6558b3c101b0a7bc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index bc26811e33..9f3656c5ac 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clear\sthe\sBTCF_ValidNKey\sflag\swhen\sputting\sa\scursor\sinto\sREQUIRESEEK\sstate.\sFix\sfor\s[1b266395]. -D 2015-09-30T12:59:12.171 +C Fix\san\sassert()\sin\sbtree.c\sthat\sis\sonly\strue\sfor\snon-corrupt\sdatabases. +D 2015-09-30T14:19:08.486 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -282,7 +282,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c dd877a85fc968c5f069d0cd133c6b420ec3112fa +F src/btree.c a5a653087ae98dd743d12ae0920d5b64c5335960 F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 F src/build.c 0549b56722f15c146ca21f82a33838365c2031f0 @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 31a91ee7d32af8580a170903eb857ed9222fdb0a -R 4a74a22a0c922f420238bb3d30a78646 -U dan -Z 36f983bdf307cdff5171dc6e84fb5a56 +P a6d5e4e8693bea3739c35fe9769ac9abfb9ed056 +R d123bfb9b25dcb8cf6d4214c017e0514 +U drh +Z b7257b8e8fb8545cc0082886f7c4483e diff --git a/manifest.uuid b/manifest.uuid index fafa0fcdff..d0ec470927 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a6d5e4e8693bea3739c35fe9769ac9abfb9ed056 \ No newline at end of file +29f7227ff127202c53fe7c3b6558b3c101b0a7bc \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bf777aa969..1eae0ac5d2 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7624,7 +7624,7 @@ static int balance_nonroot( ** by smaller than the child due to the database header, and so all the ** free space needs to be up front. */ - assert( nNew==1 ); + assert( nNew==1 || CORRUPT_DB ); rc = defragmentPage(apNew[0]); testcase( rc!=SQLITE_OK ); assert( apNew[0]->nFree == From 105865acf9644a66cc73a84dde72937b83dd5315 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 30 Sep 2015 14:30:19 +0000 Subject: [PATCH 29/29] Add a corrupt database to test/fuzzdata3.db to validate the previous check-in. FossilOrigin-Name: e796c0efb6cf17444b53af75046daf7d8fa82f78 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/fuzzdata3.db | Bin 11842560 -> 11848704 bytes 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 9f3656c5ac..b92913e6d5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sin\sbtree.c\sthat\sis\sonly\strue\sfor\snon-corrupt\sdatabases. -D 2015-09-30T14:19:08.486 +C Add\sa\scorrupt\sdatabase\sto\stest/fuzzdata3.db\sto\svalidate\sthe\sprevious\ncheck-in. +D 2015-09-30T14:30:19.646 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -753,7 +753,7 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 F test/fuzzcheck.c b8eb7ee40f6d28548a0b028e0676293522f3427f F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 -F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd +F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21 F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -1389,7 +1389,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a6d5e4e8693bea3739c35fe9769ac9abfb9ed056 -R d123bfb9b25dcb8cf6d4214c017e0514 +P 29f7227ff127202c53fe7c3b6558b3c101b0a7bc +R b3d2e18288eecf437c1dfdc1db967b0d U drh -Z b7257b8e8fb8545cc0082886f7c4483e +Z 07034a5cbcc5358cdbeac30192aaba95 diff --git a/manifest.uuid b/manifest.uuid index d0ec470927..956cc32adc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -29f7227ff127202c53fe7c3b6558b3c101b0a7bc \ No newline at end of file +e796c0efb6cf17444b53af75046daf7d8fa82f78 \ No newline at end of file diff --git a/test/fuzzdata3.db b/test/fuzzdata3.db index 4ca7a23578ad0115d0003666e650c4c497146b2c..0a41fd6e37ba0b794372b5a6389978ac57664bf0 100644 GIT binary patch delta 81588 zcmcG1cU%|k#wRyw498GaF!_gc^3mh$Rw8GIEhaV1q9Bpv4#nBE& zdmJ5bbi~mKM`s*eaCF7d4MzZu?l^kj2*lA7M=u<`arD8_SDe%JYx)d#YZKrlj;uHQ z!d70(b7$)E`Tg!`R^AxsE*>l{XvcVJRlsgu5h8i4bW3(AxAbFL&aSbJ%#TM!8G5fg z(kxIc^`72|@w~Q6!o`jAJ^y0-{PKR2C5IUz<{sO^9u)P{NJ6!t zU!{w(a@Z`RxWkq z6|YV3n$D>_tQXL7Ia51?kx_Yglr9Zpcm}*APMr3phRzxd?@H3Fy96B(TW=fdVa#n#|EBf z;`~{PpjM9HrJ$fDBIxI!9f>?F-#Wo-i5)jS>-R>kjC1-&SY&6XTtJU_R4 zQ$A%)$cOxTp!7d(yfV6pkkr9%s>SYGJ$pNe^X|b=^VGedWh$=n4PJ6!dGJ(~P_+o& z34~)XAvy;;OZ=*5Fdk6X;7S$W-BEHX4-9s75w7inPpifGs9-lOzwuS5nzay>3Besb z_{r3%^RIm25=|b@`^==QZN| zTfr^dMAaS{ehQJ%IMMAy<+s5)+~*UV=jVS94izn54L-+2)n%lDsYT`W;3^*%GAzYW z!iyX$js{2uNf^HgJ`-g;x7Jme{XFRHT$RSac98#%L^;9<%{|*Yd@1yFaZYKVHBIGkyKBeuFuGW`K zoSzxurIltL;dkbRED^>|(z7ZdEet9066X0KvsG-IaIbWFfr(`ns zVhtH&;;piYPlu3+w}rfo3t`4Qaqo?gyDGk8qrs_ccgQJmYIR62mFCIS4s5m9n3c}t z)Grpx*0YI{)MN_xS9hN+=5GiYi6k5i!86z%LeJoXn%I9_H_qQ9&a(dUijYc;FkTyd zgst4&GfXaAE`@xg6Cbti(@Ns!Z<0mc55YT9^%vAp#&l%S<(0&$ycp6*I-m-@g2aaY?Wu)Dku&)H z;i3Mbl`-@po`)&)mZx@DT*fem`QrYQp-sG4AJKSWsEW;dr6|wA!EJ3(E<#?EgK%Y$ z3E|SBY=n!7vJje!P+Pb?UzCAxUeR!b&laU4oL-cM@TsC<2*(r+MVL}F2w|V11P2G# zy+!R1?kH-D@b#iL2san`BivNvhw$a1)(BUNB}JjbSwbjSEsKH?wkSfq<)$y{htR92 z55guzsO;Pvi+UlHih6=|wFotw>u*Kf5S}gSittQP7lbEyH*@H8Rl6dCc-|}uCjx4k&6i?OqHuC�gc6=C87Hn zSA7@yGDpt5Zp*Q6HJD?M`7D>j@-^~3F5(_y&q>JaJ>mXx$W11Ue^7=x5)n=h+nq}{ zLSNzY!}l3U@eazkQzRX$WOyeJ%b7xjf`&gB`CKQ_z9RIHhM&J5ihTE{obReat6xG@ z*gtx4Bc-3KB&wQ+b!fs*`Y-8QuLk1h1HwZ1iRLeLwHA;3a+uLe-0Kk*;2}D9340q> zi3>yam&@1zVV#?Z&e8JOoUkTpakGDz2WpE^VOMdhf-q0Wvt@avEUyY+dDHeHkVoUkyw2 z5?xEf4no$1yQ#%rpM<;NZjHlHZ>ptm($zBDMJ;YPg;Olrh5zcwe{UU*N-rqf%TstR z3Ogx@^C{sPiC+o|_YqZt!aI714oTtfsrdQP;lZN$!0-!rZ=VRSiN%QUL%2349JU=3 zPVe+QTodY9xEVkHB2nhb6t1L*^E<=QI&s?`{uOW^g&Re1zkm->R;@Rns{J_p785u8 z@)yZkMu^AlOcz3^Kau{%I=lFHQ) zYOU3*{Jcv9V)wHgJJ*OxCvlraG=^1LL@+>{Bgk6qBYtlp=5&z)>lCkhjUTDRM{Ofo zN#cA K}Hk~i1;^T}N#S8=>ggb%9Uv^wy{U0VSH;-J(#Qc{+P!QNPX8a=CInk^8L-`oPd009ia)e66 zHH|!k8}*5t&cv*iktGsW1xIEHz6yhvwvcPHY4&w_ zLgaN7zpRS%6{-P|S!%Iio5@W^wYBPXg78%Xi4$XhBG6t2|Zvc|l8f8+y=xW2fccio=E zyOC%jKX@yW`U9sU%e?t3FNXw*Pri%{#l5dYUUfz5|K{Duty=NYACcp6PHni^gx|>O zevjX{8|f)jUItee${W|@yur`6Hy|EwA|AY|qd`;GtQ=;2AZ~dWTp2rIZ%gJXHV(@e zEf1p@a1^{@lHH_!gC$@ zkDUw=qNtN$u1fmKl^@-@zL{v<&2T}*PV=693_Vs}&vWN@`x-L&e0BGhd`hGg&Uf}R z^x(@{EO|z(?P(Y*v9I~YS3=r}PJIk#RO}m}4mMP&*tgtG-Q7nt4>w#=F+As!(j;Dd zb!;Hz%yB%wac+~9_q~U6w|l}|L>w)GRH7}Sl0dX(W8v>_K53~CYh za>yqr12-BPvoWI5Y?vwWDgBW0Cj%wC?biOu3kJ!NuMQ17Locj9v%T0a8T_S&9$7ch zrr24>$+TkQW+j&9to1o!` zR~w=oE4Mlq^=SCgUt1d&b*D@2DK+np%+hl|?Zgf%U0Z6MT(9j=7X{SG26iC3`o|fs z@g*GBon6F}A^UbQ9@*L8DgwI%oV0uYDWhhp0lQKDvf&lRukjEM{`LVw2u}@_e7JMD z;U|8Qb&p4jS;GTfGkn8tQdxlVTW;O(L+=+P(( z5#z?++GR*m-Lgh>EfX8}7)D6!Z|>GzS}d0DH%wKre>m=XT%0^;=&fS6#gvyrCNnYh zJ;QRX>Q21`c3|RbaX~HZ{eynUT0e#v^FC9y=(YVoGeuJkeI5xopFeoGFqf;o~e?Mx*10@ z?$&b2XLS0w+zXnxnd)hkk@_8djs8O2%6OMiKhw>PqjdgPJn%DWRLosbY`F2|nac+8 zDQ}PHL7H4~1E(HSCCSZGxOWIBU}AKDajv7fPj%K1s(!|MjJcKv8(&~3LKlY^$2)p2 zR2TKFE__AvP~#=We1tmOhg-E{la1zwsG|O11VxfHFG-F%7JI9#d*cy=vslA?yNWs%#?8^AO>Bc!?*+*;sW&FV; zqch(%(l`vwRO45Y_-2eTK*QQ{_akY=qQX6U3RzYF)mzI~31c5VdYUmv(|xtND3We9 zUek58V^IWmdm3UVoDHvyfTsN_ZBdxG_O#JmVr|Nn8LN2ebYl-5I5*0RUzrpC5!rhU z>8Du4aKAA_n{u|w7%z^DNbABx;T+=%tx&BqZc*{=W@9F5EhF+~VF^xi)mGy@o_Z{M zi+FvxF$YbD9mZIZu*&$Zj`iR@UroA8_d-uWPUPlSjJf<~N$xpbu_pcnQMeHrSg!_Q ztT#XPb6y`YWwH_eq9=D6Tj=R2-|+m7BUX#T_hf6`GM+1o$!PY_ z2S64Qs!G|upMY^d74j`H|~6$WUL8Z6v<<-Pi}Z)luJw@2?oU=(wtJ)H!kS zma!FD6mC(Ii!B-Yob&NZK-3J4 zcs3-;0y#sL<79bM)MSk)94xDv617Lg_XkA{LeC*;1{2Tb0Ky7t?ASwe?;G{C#6~Dg zG>%L-${v)Gcp637Xa(x&s2)0Tc~6v=q?v@I4yjG5W;}imw)_1Aey7^~9*JBy)?R<# zsJRl~@qE;9HcoMm5Q@nJCGsBQsAZvZzx!Hd(m)rQKBVxr_2# zbZ&6AIcOH}J#nU$V%@r^Cv>b(aeb=&^{r8ZoW$j$l%6Sw-_r`@Gxo@XGV&B5rvW)r zfrRg*_MXRNr9Ko%*G#rDWb8R<^Q zg+P`lkfruW$7o8sKOrqZE><9y*du*qWKTlA0OWE7a)mvzlZ=cajB)`7ZF zL4DPpIyQPGN{D^Y6WC7PZA$cH&30tp5tMxmJf$$Yt7gk;T~Pr)dtqb{cWV~aTeE4M zx+uTlTW!FtHj9FRX=pXwIF`MN@#*CgCsW>CR+48DY+3YH6nCpkj$+Tu=pkCRm9R6J zn6n_dSYq2m&*S@cNMiT)q#+tEZHoR|+Des95Ln@ zzF|P-AH1T__#st_<;>abO=lORO>%gRFPNP6m!dXX8=cE`)x2(MCc@W8f2?)d^Kix% zF!m}K+oIPw;+=(U#%tb#nZ{bhw;?`Z6$QjGR&hVX(Xz;PmmiPDAW{C>f@aD(Tx|X# z`gx}YFPw?ab9Ag1xz3`~iRd#Ddsh)JIVFc00)J27!}Y-IC|~}QF^A{&eZrG^5o?9( z#pqiSd!PF+G@+$+DcazKlIZX{(>Q0h57$0hG+yl>X7N*nL&uAee@3rknj?7BA5l@Y zQ|!4F4JYLPwNzelV&8qfd#v#X@sm%?5H(+w7c)Wg z9c(?tYWA-oKFI@H#7t(Bt!KVKhMiP%t4lnxb<9z8QiEe|i`#xNl)u7bZaIqE-DEjY zmV;$^Sj>GLwIRNzg#ION$Kovep~jj)a^2mxfx7!g8zGelKRt%fT2t08wv?~@AZDWG zCSpIs8trQkr(4C#5TCJ%mmofE6)!@ZW);ste99{R0&%J=vNL5fD2@4YT4u-m<0$S- zjB!SKEwVgAmRHH?T_|HV$nr8--XY8DWci@Y4u9H`wH0UCUyn%^wPF6Y5%v?|pT`hn zJ1pX>I>t`WIIngrcA!*@)4J=BqIou%nk{o}GJ`xvPO0Vr#MxHyF2rZ8VkN{`vdC_g z{TOpc+_`0>_o+l5fR00`C@E>3HC7EQu{* zN+-;1rtnp(K21~d%u@QWU;QAOswIvq85^Z4#M@j@N;Rjh~lUqX8+T>=C zH8$A?GKxnT@3mT6tm1(O_j&XA?PG^&+;L5kuSxDMWyaVlQPn9HZAMQ~@NXu%+lNOR zbIQBNs?bvy5PMHl^}$7wVh2jBlO0t&xgeGr zyVqf~a3s{tW`q#Pt~R+JAz>@3TYdx!E(u^Uy~ZR#3o zip8Skzcn@-J?@ya-h9d=(=Oo`Z#t_H((c$ujP0$D{Qxc1cVi|Mq#*^q zw$u!P>|>J$LH4%E10d^da(~EPHaQ-$r%jH5>>IMj5U!N<~6|&1wrFceKe1Aa}6Ib0N34$wif8= zI5@)$?;&17^<&(t)u$`u)1SzvFVX4EU&Y}CzY|wdKmJv|VNLvTQFs+sFs>N?s+vwbCpzAV`%%j*N@G}k zNmefo-t`jMEYyaYBsQz#b9HRdBk?cTjjZLGcNwOya3y9uhD2RT6qJ?%gFJ-dPu)sA9WURty+O-Jd69CvSp;_Nx0HaVkR6vwb(h8>>*% z$j-=-&)tTjy?O>2O;;Ep-rXLbz}UWq;-%v|cEt~8`xVL96HgUv>x2oKV=zUy%@iL& z4ztPcLk_jchard9<$EF@bznH{=UI? zcd?aWnI06YzI11}Ze94^yYYkBrwRi*B_N+1|BuuYHF;)+*zJ{Y29M@>JespGX{^n> zKd;sm$JqMr9b$WH&fr?K?Hc+_#ZfjHou*==P5u(HL6$Y{UqI$Pry1Mv4J~8hCHK$D zgA?q$dP^7&X`ApVI#9Av+9!}vViV|b+>U{*5))o$!f$Nyv-RtGTbEr(sR{2$9QpS` zwVQymVF?TP{1&-4$XvbXA!@|7h=eTYHYN0Be9GDaXX-|0inTcj`6^yj;!KXeeU;}KOI6<3gl>$_KbGxjV-8LjD{1--awZVjHfSe#&cl;|uL%bxdflKX}7bqTg=kh2X5+bJ=tgrOvXs=}@EGh3OE ziy?soyjZIe=$+dyXYW@Mki8Gm*$wj9BMCcHeAgQZ!?^0hgzaT(qdpXcJLM;TJOR}} zxk!MA_hiB_m^*x5Gg0`KeC@l0?P^S$Wifj{6jMXumuuNwdz1W57QAO?LGk1%dKVtl z163(NKP6C!l$g_4f0T%>;id+O{QL@?5Q26^+2z(SoYFFMz6AXkPU-g zWwGohht2NqPka`&($xgB7Lz6uXF|S{KsA?dBGp!!M3UPjQf=j)SOPgPF;v5s#q8}X zrnXF6juYXDbcplCG~wm4-=0@9~Wvr1cVoeG@U{;$sg^ zA+T=^m@2-gL^8oHn4lY?Zn7n#GvsWW+yQcyO{VT-rcI{qWQI+q?&NTrOx?+JS(ZG! z%SR<{Md45xo{Cp3<@a`=rjHq;{8+N-d&UV(;q2!8#Ub zkJ(6=o;8?>V$-I?-(U^T{u4BDNW~~Q6&jCd$h-&Kc3KYuMA^NG=T6o^SS#6X}MIwj1q+hWHVGGKEe2ruL{C>>fHDO#jsvA^+IAdzAQRz zx_JF~Vh(O`r5*)dMe0XTc@ra7X}9SezLD5XfESI2^}T$r%0w!Y&nM#Ay~GXt#%I}D zvF$=)7IdonQyq3a5ihx8fBQ=;-rmxh{;+fcS-Pv}aWC<-j`gp1Imvd}vA@ZYubPf$ zkPG9%%O@K$8}bC3oB?^fO{N~I>{Er|sfQ{%RUuOkRrabvrXH&7RvjmKB$jvUzeO#! z`1Us;`oaA-L2f6@vHdrz#n!<7**KpnpAVPMoBD51^H;o*(8i5PdsZYB^v`T0UK`dw zUk9H#IU?i{KG9uHW4;HyYyfM2!mBZ`$Z-s1;<*l;3N|yJ_ z@&;KxBFj5u`M4|}gv@5tOTbK90zRblJzMYcY}@6Na{3HO6Ew>ZFWI+-_%4PlJJ%qW zLYBR2kg4A`)0PhEx5+L{oTq-9?8Agi{WjT&iS*4Xza^)y0&zT`N?F1;}7 zq(I)oD`|=?n_lTp*|c%eSEx|t#`mNb1#2I!mUlPSzG&dFVq45Bkua3d55aF%CFL@? zpM`v^P9kW#q%MpHX!>sx-?$_NNbCinc1xod z)xl=9+F|!JzTlIjF`Cy`JDTC=le5ulkgYyGtp_@SX0&4D^XLegZ5~w*>Im9Asvgu4 zw0cyr%B4IbDVT}is3dahnUV}lM8_qO!)jDg4<>r0B%LC6Uy`2_Pkk*(BRXXw@)&Hb zJuw<5xN3gVe17t?>_A@e>AoFgins=v;+CY=O!yZjor8uKl9*$SQQC>NbCN0~wpBI? zmHo-$d8pK}?KPM-!oLJe^r;?gbNCKDc2ZBufH~YvV^-Q4nNM)H=b{IRWo1cEG4>{p za!z0J;_lHm#B(ntjng421+n|#GQF5EOtTMWv$|ZJJ$A3_VAiS~4yIC}gIgGBFUq?{6f+pCJvoQio^51l=KI@ zK~Z02n)sA6BbSMah%6mCoAIU(`Mr-a!+6CL#))FU=_H|IhpfYc9K(aH#i8#(XV&2< zdd{CveBYGai5znwc8b|QCz&7=AJwtJeHv!GuPzTyzKjXDF3A{U{Qyr=9P0HLVf|{X$A6Ydt^TunL@~~fc#E@{N5fJFC%k+borLn|2)aYAoToGG|o@P zdX6sUC$P$|gBd5i+L%WpY-JvWu$dY26ui96BM^F+3lKIj=Oc7BWBrGh){ONZUXmH> zKRh3pvHrvJUo+N!c>ZI~BHgrF(DQY3Ji=GaaR^^F$0A%~jzL&vjz+k`9EEVnJhKu1 zO3em@#pXza&zU0-&NYW4oMjF}_>4Ie;Z$=7!pUYV`tTfY#-b0;F=j0K@El?8i!j%W zr5~PIW-R^iOgCfchvyJ8mVS5+G-K(9XRNsgLZcZAKs>|ESODS~Y{mi*&pzgPSn22) zXzqlto4F&xPUa2>+nL)V^fR|Z*uvZvp|80OLNBvFLN~J?!p3H-Nbz(uw?e2kw?yb* zZh>cU&)ghgrMVfxo93nn|1kR?Ja5(`{Kf2v@CUO8!f(v(^YHIWvm3(C&8`SPH8(-{ zKQqRyJ>D`mM!3t2K{iocH|MJPhFv=Aj6`F%LobrFpQ!JO|Iu&8hhDsd*5>|Ct9OeBVqe z4w(laeA}Fiu-u%4aId*P!Z*!{2)COPaI?>g;}9Mw#v^loy|^#J#lXdG^E&71-G zwIXCjxBm}|jy!&Ha8RopgtuQBmLyo;#h>lpn{>Q448t85lC~@Av>rdg(r3Bx|emnkz-?r zBMzY6K%iM5FzM(vD}Ob4whps3t@ryA_ru6j-TPew>90EXyH)poWX8r~_nzdTTJ}%v zOdiRA3x}_N?g_q@RYQkc)2{a z3cBubbZG$5^#gEolrx^r3U;Gv_Mc4r>oVXbs;Ksa#H;MtM1e#JW_=o108!a;z+XW2 zB_v8SPY*k!$(k~xmR%nLiyn7tpNGhK;bedjX-*UnkhidZJ+@%Xf%OP z-gvfBfLhx?CK>cJfm#C8MgeMT15K1cMFgVKzJmhP(FU3=gI*+1dw{wqKwWL17i7?8 z0--$g?5+Uyuz}XepaTR70H~J&)Y}HyA%i|55Xx82ehN^K4fL)I`kFu}iakRWpfDTg zxD2{Tpb&r}6(EBR^dmqF{o^`st0&5N&u9fB#>TiZpwJPshUItNGZ8ID+sKk<9Nv43 zEY;N%1x@kF_ufcUh7YH&5Gy^M+=6xF1|6sWXnR9_jDLMW<;GZd)IYE+zz z${`e0<0b_vry7+eqb3oG+FtnzR6#Xrw2YcVs63!XDNv)UQ3q0H$lj_oC`k@7aq!uc z-Y6#*6ASG?&#?;DxLTGsR+N;c{D#6~Jz<{!cA^41sTSK?E&SJ{d%`v|Q~p5|?h_R4InRX(Xi+WHqx_!~YT&yJ z1oC+xEed3bJyJW6kSz&m2J!_3a+*r9aPJHWo^}s_|bwf7nSoW3s`w*av2k4VFS}(pcK-z61r9^biHJ!i@Hi0 z(I|dk1@4_gcnj}RF_#F!T&N_H`PU7>Tm=7GSMSdsJ8zAjgkoMFi zQ74qCgnIixdZXSW)-JI2D_92}#(G<3ogmgeunsC%Z#|6lsm%I`SOTnf6|DCfVqwml z%MSy8MhveK>m9I;C|E}y#(F=QSoeu_7%aI$rk-;$f_2GAn>spMiB!!8-LYRu`ESL98#pI;~)R{V-Oj%t|5F zS73doV155ER+7xhA=bBG{itC5)DR0(T3xdS{RnGJBGwtODio}<4`cnAOsqM?`UR{D z3f9Gkv1ZBlT1>3-U|mwMet#INRA#Lw)^A{4QLwH)jI~B)?IhM^ux=<=Hy_5@F0Pvn==GvoRe_|ozm=EfVXS{;mP;yFDzF?CET@K8dX?~XPW_5r zFJkGyYOG+nJdD*$W(5$d5m;^tmU}}iZxtD7tZoWc zKtn7HlBK>hLnpScO^pI|CsDhC8mOT5Y>0Y5Ee^hsN-fCuh}8qEJ_=Ufhq2y~Stp3q z8?0ajE97CUMKbFrVg-Q}u3$wp#5$xFN6(~oK@6`FD-0~7f)&*eYoA(_Ury}{)_r0b zz=~C{;vUAjE3;e%gB1f-qJq``VXVu8=w2;}l>pWN1uNxYtmcD>6+oJQ!40uG zsYKT zhp|d!)_P(+0oFtXYf^nyr5<3 zD1SSJVT|LA!G9nNyhlo&gpz3rB~L$I$zXB^ogn&CpwCdyXZ{Cz6DFE`HuxvR;U`iu z9ZF^^l+5{$O3uhiu9A{xp=7>7$%6l=fJ}H?8B?}cwiXN{dg{`k|pj4d#v+>ZAX~l7{e%1*1OtZ!IXC^ZAX{G8o}!w5_Lpyd?uk98c!q+WYDl%TR;JJ9cY*8azV^JY2vq%V6Sm12;T4KRN^C~qHve-Nq z;dACW26S6m@O+}z{ zx+}fs)vssQAsBDJyoX-)9f<25#Y?)kj>=!fmF+{S;I%nQ_}#!CP~gk$@o;T56|LVM zavZLtQ-t3S{96kA+ja1I(frdPCxJgp_=CV>!#=wX%^^Fy(Ec!lJa#t;`YxbH70~x< zp`L>MG2{cS>}+lJmkw2u<>2B3c{p#LbKZ^_V81ic059R>8?TBt_+^~umm zXgy2NN1!|b7YY?UQ1BuB=E*53hTSb$gO;i7tQ&};a{n2a1U z=pn@uo`DhfmF{WQ^&vFTh>HuAL%Ta^T4C%xlE&VDWjY5vvVq=7acgJ3JRmkhm>h>K zr41y8A%2bkxhOzQ2sB6x^&Pevpq>P343N7WNT)|-Rl9FSr(rZE8bwGqAoU6)s=Hcb zu#6l`NG~9pDv+o!YmtdEvVf4jK(=ly!o#0EIF%PySEJUXhjUA!Xg5 ztfxX5nm_+1WxHf$M@d;Al=W38LmTV=r0lS)>=Y^M17#r!WvJvIsjU3-Vbo4OOYC5< zBNXh&$FMPJ!d1BbJdB*bH%Ub}R7BOPaMD&mgFf0e^m|Eux-1PqBTmQF1IF8cl>lN2 zf4!G87OejDSV=aPV_JnHruoYw%lZN9)E0~~*L}Scp&>;%{;MC@&@2*-ZNHJGY1nTh zRopz5JzWw#jz>O0Ghl9NoFPD}G~WLTkC*DBOW$mc!h#?PlaTXzY={8G7E zn@Q7*SY|>id0A4OrBayuS|Q#Zoi^N&)D_nly3= z?<6)_rFxr}qz=0QZ;6$?U1q;WY&3TDHus3DrmBj%Un=Xp8*r1zQ$)KBxy-OfTs>=} zIjx^@ASzvlO$A|Ono@k9Klwr0DmIf>e4gEw;|a%#2_L2{b<%{vs*|k`7&!|KbiM2z z=_iTMFVj9@TJ#TyRe_hg@XzqMX<&1l{r@QJHcG5I1 zXv;UarzL2Xuhv-Uj=mlw_M8jVagqm5Tzeov8FIQoXew6nDY=<~@+)#-R4ocrE zHZBWrl2^=chF02M@*XR5+@&egKIg_=J1ht-zcmrF{XhJrdfA17#m26e z*7xV{CZ?y@&(>}(=0>L%G4>L@Fk{8U*z}E#ERHuxNgvN%=FTbUlQnB$u9*7f;xN~` z+VtiiQj7Mh%ZH|`7+Wu=l4e&o6@!PR@71wa9)jFpkIX0JtMqI!=X>{dQwNR`Wlwc< zsh#`^in7-PW_2}VqSd7I6OLFgRPRAYLHax`VqeO25V4sLiq-rn^E)B>V@2kKAtsntE~del6bT1eC%K|Ncadd~K~)uTQsQx_1m0@RE3snxyf zdenI`bvaQlfckrVYISeB9(Acq-AL3+pkA#{t?p>oqrM_j_Yf6bYW>an)arh9J?a`qb)vcRlK1nR=F}m7w0QPp$5U*P~X+)SE=T zhi^qO1@-UY*rlzyUtW)TT{aWTz*J@G%zA6;bF~l46IC+TJp;E@gX&bD>f8{O-nu3k z^w#+k6%AQ$m-^Hu4N++bu~i0@Fg=NiuDiE;eX7U9sNF%uveCMghPNB^=&3pJgqYAL zW3`HT^RuIkqr}+Yj6qJCkyuqWjhcr662I}=$R^keNbBtdN>jS^OMKVdq<3h@aD%OG z@e!W!88?{L*5yAHl+j*vPt14^4eSDnwJ)eGiMm9r7?y!8j$7H{i$>!}9y}9UA}d`* zRB?SwBa_MelSF9{Miucnf!=u;)blPRjV++jpESG(kLR$(W5aZzN17U;+p;ozG7&`UvPBqv(5~!Q$P$ z_6{E9Ycj~!xrfN`1$g%)a&ysoQwH{??`7+ZZpGuli%OV4VEPL6{){S>mOA$}%O2i_ z9_*G_@0s@j!M+lxdhAc1*pmlOt{^2F(VIa zJJp%5>%_LdGP2anHbI-;m~PaG*Ux6;*w%b2W>wd$w3Ao(iOp3Rx$5f4*!Il&^Rbmo zUi#UZ9^!PPOrgd)WjT#lFK)qlVM=cHYOMv!h2_2L+%t!1uw>kVjSuM(R*YM);+jM( z7`I@-HHla+ZkcKov0U7O<<>aMuv$EGn~qG;NbGN(IS5;U1ZTdg6Pr6`=0c9m+=6e? zL}mrq($ZT#o0=J+7RF0SFQ~+ELuL?grp#gTbm^M@gJAiY+a$3)DKk@pC9#=4STk7Z zWUkI|Ce9{i8ia9JCb~#@)s02jsyUgks=Uhl5mv2PH+fv_7?n93MT$blIMN|6Mejq6 zOIMLFF>{L}dzQS@y(G<8bhBpJx>+8Xy)~m(Yb-Nu3p~k|1;{RA6bfgO!YAr=i15JN zvDIGYK&|zQTD6{XjyFAyzqvQFqu5=XIh3*S{N~1|Tk`n*nPahbS3(9RR zCY5BCY1u@9_p5sLr}x8q`k8W1A6|C7!vbV%`CA&^==6I}p}c-c__y127TX%RP%pHR zJ5+0?8ti?rVG6nM{m zoYw5d&PbBggW^4>LH%E6j?&@d2l9*Z+-k=XtV^SJX5Kn=2^NLdy(^p!-t#Gcq%tw= zZ00TrP6xZac_r`Xt1n)qiwl((i}~5#Mz*BaLFxP2MFT6|W?op4H-}bdZ4+JYXTIa8 zR>73?Z3;heqj2ab#wY2rRyY;`TIzsdK=w&?ThYZa>w6VVhp={(QYE>FU!IB;%=L;l z%vUeZxs31N)uam_yP4{fwb-!)I+rMQVmZHZZ`mP_*4!p5RMKD#c)2`GumBr)w9o3O zSq?K|X}-;jbi0mOi(MDvb}RZj#5zQ&wElWM-*dhoS!8y~+OA?Nmq)b_e%-Rp>)4BA z%9c#{_szn3_A-7m&UBu`x0uDR95eOj%N9ku%6sNgKjsAy5t`LaM+>*{^qe-WZeD^4 zV0S2Aa4KVrW+R>}mTl8>eHkKFZIiebqN7z@y;@s>wd~bJDqB@<%G!p^*FTH)RvMf2 zwsIpT!6s&HW!Ml&zB~(Uh!mKTDG06Kk_s@c_ZulJD|nO_XHiYQJ`1(<7Fd0U z0=d(^&M%XZI|=y)kh>MgJ@&}gW#oH=+y&%*1@b_hY$Goxr>5iES=4kqL9BgX9aOO1 zs?So+2rK_Ii@Mi85nX`(u7dvFW9in(U}v)akeG*@A8B*tN$&&56~T5^uYTsqQp*r*g0g|DuZAymO3>ELs}1Wr|-8zpeo z`dlfZJB{LBIR)X5W=hu>H2rrhPBJjCTG8N(Z63nvjIah*u%jawfY8#)563nvj z`K4qM!kF%#%Sin2 zw2VOLYN2LPBTGJR@O&v5N@vMK`2S%xmiI^UUhTZ!t4aTesvA@QTDMOZXv_u4F6F*r z)8AQGa(#?S$x3nWUY1UUO$8sj+llvQHiBa|2*)2on99UZx9r_2_BpZs7I(a|omK3M z8kP>5r8dpRCa$OG`W11*FWXbazO1=!iz~InY$ZGu*3}!D^X!S5Ur{VzuUsk?&O^jV zJ&6?%u~ROIKS9Jsxg`Dov6)r;79tjs)7jGyv5p)fJ6Sd$`=YqmC%csjJ3M96rtQXT ztaeeEWO;xrkInuE8=Yq$A=sHlK0gZQv0>liY{w-_Ha>2;tPaWh4;#Tkgv*a1wAQR>q2=0D*_~NCYij>N*@<0j(UhRF^CbWN#q94jf58N8 zc;Kq+3D~Kw#NUd%3enFh{*G*VjqY0^F09UOjq$9y_qFCGu6j57=}F@yRDYpCiP#4uiniLRIy4~ zJ@q_Rh)<7Xhv@KWEB7zb^rGpp>_1f4*>BH8(_v~$TX%1)8EkAWI-kfst7Dyc>N?YS z4YuGb=_HFz>J877bW}SW#s0yCLl-*xIIM16(g97IXt`*(M? zr+U;zWcx`qySaH+e*wY81m9X?`n8S?Oqhe~CqEx5j;RPNFrf%+16UHrm%)eHA|-z) z>mPhiP2LfH0-kEynx{Hhygt#Cqhqqet7f?8X?m8`PA)q?X{VT6^k{5DlzA8+@fE&v zO&E3VBu^tC({JX1FLlT#X{)%lz@(S(5*LLt1~D^-8FebDhwG~#NaMjt7#B1uNTk#B|wiIrzD>M+qj%Ypyl5K z8~puZnxF|@-Lxc#z7sMYAK=oK^s~2kFPOQnY-Xn(Ye$vfV{l>sMQJJD?VpQJ!X)hX zrSzn&XxoR!zG8ZZbuB+=dJ8?%QOS+PM;lF%*jegb({=IZCX+id*@q@~KBaq_PBh3d;6lNVU^h6YZ^b z&*bPR#mpD^W&4}s2kV-BnSHVpP;q)*+5s!EFeqc&8qb)$Uxi{(F>@TtH{E=e68 zR=5e~ms3TbKJgjA7wEE{6>gto|BA2rdE~szSPD6J@o^SceaSKdAZS4yNna zK30bvdRyk;^PQ>x!KkPPJLPodt0v@3fbUOJ5^Z08W#B}V{fRV`Vzzk$zje;p#>f#^ zVz8QaAfi3gzN6za%)a=f56I9^BCV3`mvf6XN|#fhVk(CPeEGe!&&2nsIlUUGYJbM& zbU|ApKj*#<%}yVa4IWhk55{$tQyIi=0P}Mu>iFet zIscz#q9NFTyXN)r10~98 zPb!|-6x%Z+1>(WRoU7>Izmc5Y~p6xjUnTC35(-rz= z*y$69`&^x70NNtm_=2XUF`8M(df1S;MuGMjD0tS57j#eCEe;&d8K`2jX@e%ThEC@E zp<{Dt)MuKQ@m)@glO{#&uoas&wv5RWtQ&11(yu0t6@GgETndayp1V#l)RaP9VLrup3hgJ(cd|hT4t_?u{8Kv(uCMm zVx*M2LBmS1VRJ@b5#pHpsS4jBSP+xeL3C-Hn}gDSWbOpbONd_@#cv@0#w)jlrVPJ_ z)%Fn5NEt*tTQ zaIthi?lc`+-yrT~dt65DJsn^5G0d}fwXP(`W`Gg7y*0b=+hq592YzSU{oV$XWYw6Y z&&nD1n(~UKCLQ+o)Rbh_TnOSj*7o$aUcqjkB^fmqZ$Y1aD3P~uwmuQIu532URy|Hv zoi6K_6X-2Ry2c`1PMhSn9Q7eTJ0i_fw4RcCK?M(8;X>1L{>_cCda-?4Zl;cHLGlOk zmpf&Jh()u>LR&dImxMeqKlgiV&neWF+$t26n{r(oh1;s!zaa0Ky>$>jLiarV_FEh1_R!tX!xM(n(=E`EKq5*s*Kg1kGo#(`Y+89mDTYcE3Nu z?~!)D-^cF}cE1nfcl8(S{+Ans64=^mrf2dNuI1VNK7g$Gwoo6F({Ul!Su6a`C6!_w zKos_;-LNQngv!C^J)u4=U%!#7bren&x&I<<_Xz9qNA5q2eIV3V1tiXesD9e^UETyf<>TC@BJa7pzZpgj zt1Z%uzrHZ9snhSz^(mRIc33!(N{@IM%JXvbTzS8uypPn+)X`C#w~0Qmt+pUNjW5q| z=;hGU!N0MpWfkA^U}z^1^g`Z;PU@NVB&`@wmM0jy#?fKR;73O9eTEv(9jb@^Fqpk2 z4};m)?He7|9dTaHLyvThEy8=F9r@3j^15nnKfLf<68cO#@;=wGO6!Fq zbm5Nug}WTXY8d=Jo`)Czo=~66o8+jOr*=3HPi71iyT8lp#hf0jb1I>cFK_F~_CMtP zz%>6Nt5gZ~k9iMNjp5WoDNldSF5G{j(I^I1r0mxjHC!++0v(@|6EfLe^Z z7eOT|JS++(p*`` za?;TbIyyf>N0)};f$#G*T9RLZcx)scouDJ&5jv`;f+(y(I$oA_>>(Z9prhv_bo6Q{ z9<+tgoB2N@9!E(>AawM7gpPg<>7dTZp?q48af)qGg+q2ny+ z!0>=?#3OV>HWUxi@w2SsCg})=j;KfIh;B%SlS(wcmj4Ul!3v zuQ*gU$ssIOtz65+8Xwmc3i+n+SHwBiIA$$DmWpeW|=v0S(Ue zqzGU<#&_@|R1A5Dite(CC{mFM6={!9k^T@Bk+O=xq+%FUWIjSg)a*vPi(-p|&(gxzW#Lk2ke9%ruNwz9eavO1Oy z=;iwr+}zSBZc^YPjmHt+V)VaM_=Ng@>{BWTtBH9JH!p(DzD1Qkja(tw7K*bhlRWH5 zr+e9kEw_bH+!lsA7Z!KV8l8J5);?{i&{IY{-sU(rmRE$rlyHEdz)1k&+{PdEwr zaWM}QENnJE5IXptuWj>!zT`Wftpd#By?&l4bmKW6A0vA0ZyzguCAhWX|ErQ@T_x9e zC4w(1NkU83ziK6SSW7nOD!IoiF=v&mLnWKqsl<-HCG$Nf!amkE-q4pdz8iZb6|ZEr zeZ_?yllxAP2w6I8YhX)XV^J^Wm5YZnu06+zmw{JRq^{V_QyKAj- zN}p%rieoGhp3zLjmC?1XzU$fj5*XIr!Xz?7+RuuOt{I)}?)#aM(49Js^t~jo8_KQ8 z3%IU8$90~*NrrG?Ya>P$jdvkvsw*4jq7rEuHmr1WuBSlWn&Mk0Q{$In=4JSf{y5dQ zw?rs;%E2&@R?P7A)yHWTrs%b=VwAD?rK!|=p|7iv&{L}cJN@G0&OTd#&*B_k7@dFP)iK7XDz8iD_C^p#ni74{wjmS9PBL*;KpTm=I6xfpS@}d##@#c2j zfW>0K$TgMkd)$ddk0<+j2(oSXZq4(meVWxb_=3S|S#@DFGSxTQNZPw;{8?Al68pD3 z`7J*7Io-WTzg*w1W!0#E7gH12)d6Z>Tph4mCjjvAGh9cMk} z5Q?V94*7Z`MKCq{$oHnej*nO$e!(cd_pG?)OX!!rh|J>Ifk#oarA{DA#_YEx^;_RG z(YHQ?N{_yv(hr_f=|$iE2%hb}bT|oU@EwF*a@Pjm(d7FE-+{7^3k=h6l(fNjxc2Y= z6&R%T*O^teUQ%-CXW#y^<6tX(O7)pGiPlHd4}E*mo>zQ-k_aCW^AocjXt!&=zrd4Z zxO5k;g1YTH6PMF0tuiLHPkeDjmi1D0MOLFPc2hrVcDV7KBHZ;^`Na2K;qz9Lf`&Ev zVmIuIXE1Rc4z7H(S~?Ru^DX<S_Ot+<{W;wp}B z=!b5ijX)iGFa1>%zGcfJ#7+GnkI59v#!6ANK12Uj4Y-HvPbYZHW3N^-8)1v5lu4rR z+Uo``>%8qdP58b|H^wYQulcR&+-ccNpWC2M>-*Jd*kp$JQ!C~ctuM4<1FAn~Da)6! zd@1I^d9Sdr_YlHfGD^!;2wkvhsu=EqO zqLktP2K?)7@Ncx>TT+R7={2D4VyJ%t^;R3yzjdg5if>ZB*JSi@uRQ`<(TImM&T|lGswGFPDC9An-$_ZCj6B zduwFQ$9aP`=H+KBI@J0J9dI1?*w8;NEWM*I@S~zZ`ZkDqNb_V&4_GJ}kmf;;U0v$Q z^XA)#oayM3hJ_M|Xd`LGW=vQQd1~=Q9H9;0;m76U|1OnEgqA)05j5i7(j4sJw;m81 zBW=f!6nt4R5AlxC<>t`pzYfbVj0SpoHYRP}GHrQ_rxIsa#=tUbgJs@&uzM_H@_Y=# zM2M4(ybY#hYs{e>a~i`$kd%#e8%!G=CRaK!5CcfV-DMM+_g%v1k~fy6BiGF$_Bvv( zZ0y^-4(Y~|Yqa+|GOsVE@6KJ8iPx92*AdfY2E|cDij`+q~u0`Yq6>KOLf8rePD3 z;r9i;dmH=#PvL{Hw=eq~_(vIjf8Y;pgFi%zkJH)9c$#vCg^)a(;cc)+G+~|OSQi-9 zFkp>tgEgiJ>nyMYYy{~9fjeE&Z+59bZh0*0#4=ghc(%NzP1RuI^;EN4vjN6&8Xf!F zva$NY4Bey}j};IbPwmz3f%+$C&kC>$n0!Tvp3TIkXBonamLXW}4O-Xe30I%}<7K}I z!X$R46)STa2K<9GM0o1%>d-7$I$xl(4g9)`!c5*0Bbzr%kR6SyMiJu%Gr7~$+2c1C zb=J3e9j%$7Z4EnntDsID{h+HLuAuGJYjm5r9~$&l3t>z}o9V5I(!`yQq-yJ(*nDpA z?JZy@#n~@dwxFOx+FVk`z_|sov^mW?FWp#!2FYfjaQ4%MGeAP@eLYRW{a!`}1EmNv zv6-gv^jjk`p=3+dxk>lMa%JG9Jtae<0$SB9Qf^djrq2DzF zY-DS1KU*}u8#x!{IZ)pw7~*%KR(a4C1fYOlE;@`%^aDYbq3;WL-{}EAzn=t|4=B{K zVbzT+&e(x^7J&-BtwzMa2GN($Q>pg$m=%5!?BZqkJ>++BQ{2T3l}W1z#rWaEO(p1X z+;=w88%D(WUJH=o4VW*hi z_}Jzs5~4YAD&T8B+*`c%Db7l4MHTJ(+Qh%*wDzLke3^h4ikU@jpIzqb7$H`IkNu)i{)5;Sc^bd%bQn3!{?0+KNpmI5iZBLOC}>lY7yDchf!@Rt z4)Ba4>~PWlMC?)vU+hmNI7768{yWvb6YOp}V4DAQk{q4kDGN&7LiS@sTFs}mKKjC?MTvsyPU_lq{=P{lA zpGaAwx|6sB|9tvhh5sC}rKLIDXVW_w{-)Ubs%D60Hd!1om}ckuM~SAp+wWjb_c!RZ z0)IP+ut(QDCA!zKt~GWdHCIkStdo`u`*e8K{=`V&cbN_*$43Vk5Xb-gdy$44%M4^6 zpqJ6Cm%+040Y+)TLjWVS;6Z>ZIVkMaJoNVvjP_?@i@<4DW4xVpiyoIMj1`Y=}T+i^r z^NWlTcy7(W-hso)3^zQzGH_(V!7KxD`SzDG5NvP1I|EVv_6Zp{`(Qsc9kD3(c0JN@ zn8EIkbbQ|Ka5`e;?NZYrxb5bq&&G3j`ZPQTrcWaB$NsK~wpY?U_4I7_r;o%lIej3W zGt&FuIV$}%Jo~0YMYQdf-UUy?bf&D{OlNBFcj*#5KTeCsbAK9qhBn*MBJeCt3&k@( z4e|Rn>(kJ6oA5Mr-DXJ|TRObc;HUDMvc(>9H1AzjiY;@LTE0-hby#^c!`Z5*C@X&}D! z!?dw@-b)*U=Rav|+vKk_XlmAfq=8b_zoubmoHk|l0{lzba6F%T5@z)O{V0r$rfH(` zIZRv6;loWoeaNQwd#!&u!lcnZ+6g5bZ8bA+QD@U4*(|5d`@bt3ZzHEJFgf*6vvs;! zpeL{Tj}?Xgp(fFZI$!g@BoR(%?NFUl!RBOpMre-bxt2gtwosS|>g~b|I^&N2cQ}sZ z5fH+?8rTpIho*>WI26Z|4Ab~E#Jaz6JShz)i<^Eo`~;p6ga&ZW$N)ZbDQ0eiVEQ2j z?v!@k>uqfgWNhvwUux|G;sm-z7Qik%cMj+)(0--?XCeQ3@p5xs?jEoOC$Q}Turd!0 zcn1-*^`ZrhxZsb4m!F{E-i|o(IXTd~y~_kEdj`DQ=5z%Oc zpzjU|a6<&mRuJm<0>gBi{%j%yJC%`+KwI74BL%%?cqluYk;X3v))5g0G}6|#`W>e< z(r~P{xh@>lNL$nLxA3iIUcg>~?)3_o3F<6tMYUxC?8^8VoKoSOQqviwqBx3|KO^j# zmg1xUrosgUuw^+l;Gl#YiVT>7tAcs)1-@G61;k?IRscod$1d7BlNdo-AHbktnE~L< z8_mRQJ-!I%XfYvZSYd!YNM{fjtZyrVRvlXUCwqdwaki58zdT?hV*XobaUZ|&+k$np zyMw>=Tm6oM9O*bH+DyA!_#5X`oBkHAYmNjkWu%7p`V{ZpK@Oh@*e}uPw&yqnKIFv> z0ed85Uy9!hD!Iaozu?8!18O8>=l20~kqLko|G=*XHg%3XARn5KH|g+2^>O>O9O|>?9j>1&7E{2(`A8OWY#D&Z!R37 zZ)=GHv(^QjQP8P%K_?V+Y+Yc20@Kz7Mkv79SRFZsh_*6~Q(zxBD~2v;-_sZCq6w*HY3G^C>g#(+6Sf7Rj4i&m;)&<^`Fn^h`XzSdbseD`7(ZDDPCY$!3ZI5Rg!kXN( zO_LK?lXVF|f&{v9Q{YkPs^13oCi9em<8Yk7Al;UE>U)z@ z%0MsKK>Tgf>hJ#e+gkhgb`^eiMgMTsY2YF^YLgTAt6+-7)z*#6bUnTCx%D%<(mp!_ z8?3MrY5zD8_?@u{aE7+U$qW2JA`GL_g1{#RMkCt!Z6u-t11%8&+czi#A^)=UZd!xc zy*_Z3Y!d!^GxvMWfS^VfFyGL7eD+UkCOSa1OvA-GOz(g-rQ2aH4E9 z{xI_@OYBtsNz7NwoI#h|3fu~})YI7Z4BPuzY^R{UAll8KQ0ZQ2dT*8# zurJoYAP;({S5SgLe(4kBLH6|t8ca?f@iAk2#?GWc6=;CSep!0=7BUKNX(j~iGba0n z1wrU}2PFwKWkgUC`a3J=jy}DQdvuv|B&gPy?D{QoHWdSd4jQO?C?+EtpD3kbRL~A% ztao+M>bEsXLDIjwoBE;q1X4D}vlBU< zqQ=P(!=iySX;$(V%B$B$9zy3Fz8m2K)vWo=G5t5qI6Urn=*8t32%y@1|OGq`p1)Y_`N(<&A zFrf7aTn{ROBS2#q9A!$Q9tCBiTh_s>TUy#U1+#A11+#7q4{oram%j>f0_+`}Y)OcoT$C;!_UJVY=^;0mes`>4cU=Un#B^bQ7H(EVYb1S$`pmjfRjDI;j;GJ0w^TI4>H8V3YJ|+L?qf+ELDP@{r9Ea?7Zw6R?7? z8EG9-AkbnVBoNKA57{kiYNB&UOA}q$I~7(TzF62oY7Mll9UijYsP$-ig{(Km$**?V z4Pzft4fbGR%o6ozqFnzm)m8Au#o*S z$XN)fAbs0MUg0AB;%SsDd?Iep1L!bL1^K6#7`yJP5%V1Idxl zHxV3m&uBMyFbblkHuM)%aWeEZk<_KAr!WaUfF>D+rbvV#xnK9RX0y~>pl%04zr)DX zhmPac-J2|&Dv;b76R%J9NMcQ>(R-nY{T@cldvowD@F+(iBKO(&{!h`+;D2)jX=hR|JD(RM`5CgSzb+r-@<#)v*X z6Dk9X-3r}lLH7I^I*Ul8%m1N`*FzcO87}`vP8+4m8SJ$Dww&IvU(Q@)!o}am;SvrPaQFa+_j33&hfi_% z3Wv2cdZ?pC%1ddn?$v0q{zbIdprge-v_sg~j@)UUCptoWt|i1m9U-JEK!{|G(+Wli z`3g3$?km_JyK;CEhbM4&35OSQICjN{7JM+Uxv~Q65yeZD93z9n)g0c&;o~c`>~Y|w zBsutMB+;}>61FPaQ5`{!;L8G1m*p8|L4emdJ8GV)p&91V|UYD0ST+pyPxb}Q^3)OjV$RB})Z z2XPx8@+z&v8FA&|oC`VZ%Hc`joN)GCUPw6O@VN-kdlm6wkNAe?Xm$2BI;u^;mj&Bb zpqf<#r&^SbYTn_Xnx!T*obk_+aK=AtcvoV1SMoTlg2 z2(PtZx|5XD9SeUO6b;{J(2C3r;WlQ(Y=wFn+52BeHf_8WK8NpO__yfg_VD&-E`?8H zN?|y*|8^ON&p9ZGfJ(OO`|vqLVi?hd+T05N11&R&m;^0z>h-#yx^Durn&563+-Gw+tdYh-6j-l*m zc{zt!Q>f$+hYxVLK0?czu`eWxUBp~u@P7rei1w?W&ztc&f*fbOx#oogDOkx?y|R^z zH#4LZE5X&umA8rK0~oul1yA0}$1LN3ea#C8XYR_m*j#+2!P(L7 z;OO{uCmSB@awu1tN(6-2zF_Im4$sm^K0GG6;VD^(;i=XfTFLlzCnxPGK0KkE(;7JZ z6EDBV;eR=77Ri?+j?;_7&XJtgIjrT!Ws3$6L|;wuoM zXA~!dTt|o{ks!nmnl+Kk`oZW>Nm8T;%h2CbpLkm-jLDMQu#ukY)u7_KNVr3H8AO0D zQX?_VmvGUV5g8?=P6G-$wlRx_gfp`!FA~}DWQxegfJ-77gKdliW0pro8PXVKWCqxL zXXHs^a;hwH6a+wIp*bxnj0^zwX@(7cH76g?$ca$nBNec!){nEJWj^7{fN&;qj|JJc zcqLp**YF!%_jP0sKX;_Kf5*Y3d7P?f z>HSE5QNT&Vc80{59I%R-E_7r=f}19+qu{LQ^a?}rr*=r}bwlDDg(2yn@r*hJ8Vrg8 z4W>qIHm4PtQOsYpB&wMPQ=&kFWl?*q$iAgf=<=GV-Ou_OlA?++ofk#1>8xb$YWtoC z+$NF~FqF-iQGP(FeyaMNQAr?i{JVX~txhp!^ysdrMoZo2PT(h+vMY)??@sY5DtQ&> zqRM1+%gHDols822$>1>hB_tlxOyV81;w(A}Z|SonHjQC=r-Mf;0+Sh|_xEQ;N#gU2 z67Bro6V2J)Sx4h*jK-rh(rDyS-tsqZs!8;C1M>QVsH1SPMl=7QQ8c5sb2L&h!%sI? z(<>U=FEtj?3$WP`z1@P;^kkrC^a1QU^eO1yq=8L{uC^ex9?^&cnis7d5PeF$qNk#= zh0%;Z=SE|&!lPRe7WYTYk7nE%6`d?=?MR4=zGJE*cPd_JB6kKu>o>4q7(FsOiqEO& zJ@Bb+WEGc3*JA$i!5R|vx~M%R^^`NQS=rEpMoFZ?@|TRxissRIk%Q9#89<(y6}lk{ z*9}>DH0DGEMXuo=1$wbEdKdN#B3JRDan%jY&S(rxsOD5ObI%>+R5=&D%8JB&ADsqu zHkwW48@$+X)u)#9v~1Nd5YB1U6f5$U!K#C>kXL9H(gm8&R}YBE+;b|RH2tFW0>vZ|AmboyqX5nb|jRzCJ>XGgKU+HI>k$w}@|_mOQJ zNrzW$wW5m;ui6HTGpkgVQ+t6d{lU0qfoGg5kYkTyNMqsF)`~ipSSISsVs{!dXWcCL$77?B+Cvr8ikEyZt6u|Mh4OC4jK z;Uer6`;9TFU#{+}9voXo_O4QYLSr3b(}6WSc8{Fy8yq_Wnud2QmkM32UrfEOHm^jz zuH1@!ihA6+I4E`&oCr`1cG0@2u}D#e!2K791TFm><2d~$=_KR4SkTW(6BYY`F*$}i z63E#>vHgf7DR#G*ltli%qnJV;4~}In#dWdFrI^TQR1iB&px$+{`_b_dUQAf=US3?t zix0$pYC%r#i5-S@JeEzLr?$>c$Cg>rice$Na(E@S&Vn5HBz8KH+>8B(`!Nab)cTm7 z_&L@Czdz)^-(|m>#f>IObCNZ*@m?%blI3w)Qcr#fso#7xQgbWyDN^4^W{lc(DkC&b z0h`60kRadLiwJEU=LqACXbC+{D}K8!z$Bl_CV6*JHXEXNigx}xImU&{5J=Y5`z1Y? z@hUx_qG#Mw!co`!nXLJ6y1K@}ROIg2=Puu)W3hbCX-^n-o%@V16uZu2v{=Uv5Czg( zHc*=qKi)9SA+$QirU{fT7o>TikDgOC(De^Xp7ej2`-RXun$tJ-_D zb_Nu@gi3|4Mx~;5sbon$7_@pK!ipJ{*xdA`OQx;fDk7}-MH4|MapF0t7Bxwn)gTqo zM6LESrG7!HH={r6R!_yI@!aGYq+AhXPU{q_nciB0Ub1e-(dmV&51`-xqlnqh3Rm^1 z)!)(Y_VWIpUj4oW`QVe)6N#i@wN`l0$7~oOS5`C2x?wdF6c0IkkHhkKEy+H83CTWt zHIjYaF3GsiIL!zKmx5V5Tnb;jkXB4#qf-0$K!Kj09Pcd3zJicgtP>umARy}7osnO+ zGb6uYA8MYFW8$HleA~{1d{d<32F8Dg2{|=>a%VdA_4sTFJ?|4AE~iu8jaLGWiw~32 zH&?~0B*Idy=ps*Y;htzHD&>LUu{}OV!zY4jic!aS)J1mIXsJKUnu^{o1 z7ZtE3cX^)1-w>Q5knhX#x@uVvZm%`pSdg!Vx#^SoKNR-#?xi&aUD!tXUAp1Yn%N>f ze}7G~oPehWlKMMqWHj&28U%!$H&0k6r;9r#tO49RAyrP7_DF~Y?3J)lPJPEF!~veq z;W-?RNZ25!J}VMdqkL1sdO2OPAt7EO#A%0#Jl>k1-|oPKJ~J>>+?mkMWLVM8u)qzy zWOKqXM1(u8C`;2>&)Y${LSQ($$|6bRNFNuU;p1al{S7Yww)M6D8N)!~GNm;`4M z+6hp)l5kK$=~oF;VLn|?h%zO|7blOTbw4Mt_3B~5Y)j%D;OR(X?k8lRK)#l*Gme{H z!U<`w!U>{d`tv7F24@DgFfX9<%-8M^h0GVuo@GgFd*L#tPNs}ghc?=;#loDb8NRj= z0kb@oz;!KKMklRh%jkr)Y#Cj`;e{NIf5!WaCo6fgIPtR z&aTZCg%4hVP*sVHjWSJjglb@fI;?rPcBLs@`S)5ChT0_Yumw35tv2DGf%29ZhWJ&Z zME09=V!S0?+bwZD;L(ZHg1qOLI2nptBJ-AxNMx)tD{&Wg4F}EXK;E0qehW<8X+`z~ zB*Lgl0@^ddUh5KJi|tNKoQ=a#i7gh>eyC2ozLG>O=l%H-l3sr`lHO>Sq%yLbB+f>Z zJV*-5q976B96o~=dNM(@;(3Bd%XuM5oS>GBpuu2~M8q2Yp*fy-+L)Z)p9q`rbmCSk z@|RZ;-}FR$%az32+AqKfpSab6Y`>hikcbai>0pGg92ApM+W0tSNuOHL^|GY3Ag)u= zSmRvf2tTs@LE<9#S(B2D=z0hK)9@r$W9G=|OuYIgeT2K;@SDytAWLFPp?4D2E3&$D$=wI`Ae2=vL)EKY1H+4@`3l7kXO4{SZ%Gr~Pyt(Riv!8cUw5$GPvq*>^+ zi2`EPb6CM~;y&HONIkHiUu(ZR?YsocR7bx7O5C5nFq>S?V&z$FWtM);}X zBZ>NF#b|Y)0(;cn3bwR`DmL(@^=f~1fjp+vbe;lnijpYBhsNYYfWiafSy9u8>|CtC zCZ|$SV?}mmGq76m$bxk%f*^_+-nnfGc;{BOH?T|?^rm-x6egm86z0#-jGd75jT@4I z3M{5x|9GOQ4d(AWr>O`PW47cGMK_7iLn{tqFyURaAdZqc#js%2 z6#XPD>AKT;D*ac1LlqlXxF^m}+*5oZArd)a*~4+aE#u9BO(wyZ_)b_6o+t!djX~a< z>^YVoUKzpQHd%eyXSzX@AuNWy#{RTs>G<}sC6PQ{nyjSh(&U*kp%=YmlGIriy(3${XhO2aLab0K8hlTQisbDLx{LwbHh@I}2_l6}Su|{74CuS(|?pkC<-wkH3U!0lTjb(asDt&s|Ya4L0QK6mXo5_GX zGp$<5GB(T>=u=ekdO_u_-z*e5aG_96ZvLX+d!XOT$kFtW@#JQ=tS)p>znobDr2)x( zM5!x_i~T#=(}^H1c5-v0Dg;>x+OxGi+rnwvGh`rQMshYI^4->?*sdi78$eHT+`-+G zaX{auQCy|FMdhB+MH-)wyhMr|W-Wwy>rQ5&V4?Tqq;O0)EbJ3%(3&myuZ9Uuq&Hue zyh?(g6(%JKq+|xYl$z{}5#N@a)qLw{DU=ppdOb542b6ZUBOgsfdOSgWT%aElhSHB- zEKKeuvLta%dsxTw1X@s<93l#PpXo5n%H+1j6d(M3R9c-JXe796CB=cACYk-)c4`~T zO6as3{~aVx6zV>VXqTTWLNv`1ZzT;poQ!Nqk~7KUv}-8AX%$uL;I(^3KXK}_$Z6&c za5|(@exzAaiRg5=eLcMcJ^o4Zc<2RJlAWcrXMOTdkk8kXk&diW=c3n$(_=*?{ph=7 zFRTK$lGQR=cp-V56xMCBlL>urBiRs5GE6Dpi~FKB`o<_a=}vMk%vST1WK$$r_j#fy zqmLX@HcM%-Ns6Zo_HW7zId$!kvWMBfDR0ZE+t`%d%>L!@91cgM%#zdoD^hkc`!~f$ zPDgJ@DFa-QvQ$pTZcZr$d^ly9oO)3! zf4a!%8;?`+P++rextvbwvW~TIz&eD=d-q$1Q2Fzd*Coj5yw}&I0QOm@kkf_lu1f?Q zw=PyrXRcb83Rtx+UQXv^ty>ScW?iD3F4(?K0r#iK!Mas|e^{3(r-9$CL$v+* zzt7EZuA$Q!5APd875%^70%iy76MH&@`_r**gQIx#ze(yi4wch^~rL&=&kj01iC+fmneA2+VyLJS;*f~^SA2O zr^xBMyVob6{L}T!k?`^Qc)&k%oQoXiK8Npc*nGn#IbGIqLkw_wZ^)3-fF2v70DEm9 za?;akyLC&;(V@8;j#$wHb2s!vn<6$muw>pk3;KIv@;~s#ZrbqJlK!x9gNPq1HVl?@ zQfA?pV)u1fz3^O{)q{4e-0-2;lCyzctJ?4%&Uuw>xR1AwZs^#B{5dSQ1HC;g`5Fq& zZa^UH-ETKs0eoYFRTmPT0=~TaCohm~MCR|?l8p?}VI$rw|3_g&|FPTnI|_zuH0naU z$AG}U58B9DHf^KWg)DIkG9bSu=60gDmu|dfRds&pMzQLA!p1J-LRF5nZa{K3{$fRc z%-ty9r(GMnRGr@e)%pC%jR?G{-?7oS>iqxM-xoHXwX^vBt$rz~?lZA|H& znW?V$ZF%Y^mUK%<>IlH=Q`PcZZ`-akJ2`bK#-ubg8?L5*G7U(N#oKM#3=CUw==p;{ zpuzi6BY^xxDjUqtQrTc$O=S%GODbd7N2zSU|4U^9Zn=qhraEt8o+-CY%rn(z6Z1?> z+{C<5<2EsG)S^v{i56^POccF|vEj;1jOj8rDdbY8WqMw@AKLb(*<({!3oB7b7jD_a zX4273tK}?G!hkM(j~ATX6ep*%zS*=9Ki=5HPO5Z?kUpf4)@{k#0=J` z@foa9i+K40ULKwCpJlV-(u)2QnZc$;W(M1}NXuZm7L^&nayoHKh8pnEj37Ck@LmQ1 zd^RIcPRDm{1z2quyW706)(}IqClb88r_Lh^Q(><-Jy>I3*ASGmim72{KPkJ{#lTGyeOuH`h zPGrVaz`HWFq_n30?8sz|KbhHTROIx>|78m3^o2}}K|5+(_xN^}^J|%Fpg?udsV_zu z(Bu-H*5sginur7{18&*-F>@`m4caIyd~NR@2ceck%#UZQXqhy|M?xGwn%x1*ad+t1 zC$ib)k5@Chiw7lHSjV9mjcC@{%tUfDD2St`Q1jE-A4_sC&URwP6jaD4nXDJw51}N& zCdRKr_w_rwWc7sV=1w9U;sdp68&sw`L6(RwZFsS2F@$71$c(||MF{!zq7xrxegMVE zIxCUsBLCxtFw-qAH7nzZZPbeHo0`=MZ1twGdzKOjuD9IJdK0g+{VoVJ$2coODrC?Z z(wHcL#+qlPGpFhd=lD7aIhGJKjfn19_UxTyG}$^!fvbmdXAH%ah4xv0847)v0u`j+ zUA1$5R&Sc^k`*qptIE6Qytro$B&u&#wvfwuHkZERnpKUSP0F%k=~maWZ`HK1^T)*7 zlaqt8#tQkZx$AMnKNyO#9K_-rGgS zYqlBSquD)SYQD%>(f#(*R*TkIL4;G;w;0h2n^~M&G2I)VtBd2NLWH|@q+h&`Zwn*o z#o1ZiMEd0W>|+-6gKx7zu!}dcama5mBFfrxo>bww(x#J!I16sAP)LY)FZ(8eqo=63 z6{g6ysOL=n{zc(N-LGWtHWEhDOJ`BL>=DYP+TK>&%Jz|n&a&pdAv?|5#%$(;HdAV+ z?s%GdKRaF&4BF{Wra(6eN~F;rtL0>8qn#bH#xM)RNz`{{-|x_tl>=z3krGqHnDOpd zI?hD-Ar$dm>{Cr1vr*h<@fNHacgB&!n3Jv_)6n}syf~XS^Dwl1=ZcD7UgEhUoS$~{+=xS&}g^khe?n?i5LQ|~vG z=@N3@Px&Q7%VGpXi|t~1lep60kE7?K2_O{ z1Hjqkg${stB^&_bo^b#e(CKPriD0Z}@<2EvoEBh$(}zU)#E3rFq-6HqHswTpIw?oV zG?86Orj^uk_@t6)D<3JDwsJwa!!p;&)`(`GS5C$7H!8KudT)VlxUFRSqo%56y*@sT zsp~GPYkyCp|tQCbL}r zA&D7b5}O<6}wbri^M)smHUi+^FgGlqBC6_tYYTdCKc1C-&Qewx_a+r42;`k{_XBv83PWy_H^Ok40nTqRjn*CdBx(VCb)ry!SMJv2VYBe@t zZZo%YenR%DC%HKW&s!3!a(=L)UsmO?)#t;U+m^IGB+C@=4>=DkDQrm@;JTu+j72Ee7iQ$zKxKT8^&8-zT&?A2Nb0-B8PLXn zT(*EJPzw%jA$Aw$-(3_G=89eDC6fCXa2<#D0Is_5X>OOQ3!lJwc;V+<=$^0xJCTcj zC_2!_ySZ0k7v9ZfjWW+;%WtPVw*2b&C0zv?2*Ud`FU(vo}0&(

Us=S%b^ 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 Cyq8P> delta 81167 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