From 399c7e21e4d7e7f82a7f93fbf25f3a06675cea13 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Apr 2017 17:18:45 +0000 Subject: [PATCH 01/15] An initial attempt to optimize VIEWs that occur as the right operand of a LEFT JOIN. This particular check-in does not work correctly because it does not deal with the case of columns in the VIEW that return non-NULL even when all columns in the table of the VIEW are NULL because of the LEFT JOIN. FossilOrigin-Name: 1838a59c8a1c151bd6fc822b0ffef661803cf0e4704c917e74a04567b81740b9 --- manifest | 17 +++++++++------- manifest.uuid | 2 +- src/select.c | 55 ++++++++++++++++++++++++++++----------------------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 6a6c5eab16..a7b73eecdf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sUSE_FULLWARN=1\sthe\sdefault\sfor\sMSVC\sand\sfix\sharmless\scompiler\swarnings. -D 2017-04-14T14:50:34.600 +C An\sinitial\sattempt\sto\soptimize\sVIEWs\sthat\soccur\sas\sthe\sright\soperand\sof\sa\nLEFT\sJOIN.\s\sThis\sparticular\scheck-in\sdoes\snot\swork\scorrectly\sbecause\sit\sdoes\nnot\sdeal\swith\sthe\scase\sof\scolumns\sin\sthe\sVIEW\sthat\sreturn\snon-NULL\seven\swhen\nall\scolumns\sin\sthe\stable\sof\sthe\sVIEW\sare\sNULL\sbecause\sof\sthe\sLEFT\sJOIN. +D 2017-04-14T17:18:45.647 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -401,7 +401,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 4588dcfb0fa430012247a209ba08e17904dd32ec7690e9cb6c85e0ef012b0518 +F src/select.c 52b29bdeaa4cf317a981b6e8d0a15ec9c16372a738ede51c2a285c03fc69d036 F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d F src/sqlite.h.in 40233103e3e4e10f8a63523498d0259d232e42aba478e2d3fb914799185aced6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1571,7 +1571,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5159cb8f2bcfb1f7114786ba23082d2b91a26e3a7ddfae75f8bd362792949d5e -R 3270eeed59983be191492d424a0b906b -U mistachkin -Z edc8ddb73a9c8e57e014e4878b2c6186 +P 6bf673767b8e5cedef1acff795cbe524fab8db2525c06424db4e038934a33936 +R 8dfa3ca7454fc6936bedb04ccf47ee12 +T *branch * left-join-view +T *sym-left-join-view * +T -sym-trunk * +U drh +Z 5ef873863ca7134987a034a627c04882 diff --git a/manifest.uuid b/manifest.uuid index 39cfc39f28..f881b041a7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6bf673767b8e5cedef1acff795cbe524fab8db2525c06424db4e038934a33936 \ No newline at end of file +1838a59c8a1c151bd6fc822b0ffef661803cf0e4704c917e74a04567b81740b9 \ No newline at end of file diff --git a/src/select.c b/src/select.c index d7ba1f8068..8e952d5a8a 100644 --- a/src/select.c +++ b/src/select.c @@ -3154,6 +3154,7 @@ static int multiSelectOrderBy( typedef struct SubstContext { Parse *pParse; /* The parsing context */ int iTable; /* Replace references to this table */ + int iNewTable; /* New table number, or -1 */ ExprList *pEList; /* Replacement expressions */ } SubstContext; @@ -3179,6 +3180,9 @@ static Expr *substExpr( Expr *pExpr /* Expr in which substitution occurs */ ){ if( pExpr==0 ) return 0; + if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){ + pExpr->iRightJoinTable = pSubst->iNewTable; + } if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; @@ -3285,7 +3289,13 @@ static void substSelect( ** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ** ** (3) The subquery is not the right operand of a left outer join -** (Originally ticket #306. Strengthened by ticket #3300) +** or (3b) the subquery is not a join and (3c) does not contain any +** result-set columns that could be non-NULL even if columns of the +** subquery table are NULL. +** to be more restrictive - disallowing subquery if it was the +** right operand of a left join. See tickets #306 and #3300. Relaxed +** to allow simple subqueries as the right operand of a left join +** on 2017-04-14.) ** ** (4) The subquery is not DISTINCT. ** @@ -3403,6 +3413,8 @@ static int flattenSubquery( SrcList *pSubSrc; /* The FROM clause of the subquery */ ExprList *pList; /* The result set of the outer query */ int iParent; /* VDBE cursor number of the pSub result set temp table */ + int iNewParent = -1;/* Replacement table for iParent */ + int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ int i; /* Loop counter */ Expr *pWhere; /* The WHERE clause */ struct SrcList_item *pSubitem; /* The subquery */ @@ -3429,7 +3441,7 @@ static int flattenSubquery( return 0; /* Restriction (2b) */ } } - + pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, @@ -3467,10 +3479,9 @@ static int flattenSubquery( return 0; /* Restriction (23) */ } - /* OBSOLETE COMMENT 1: - ** Restriction 3: If the subquery is a join, make sure the subquery is - ** not used as the right operand of an outer join. Examples of why this - ** is not allowed: + /* + ** If the subquery is the right operand of a LEFT JOIN, then the + ** subquery may not be a join itself. Example of why this is not allowed: ** ** t1 LEFT OUTER JOIN (t2 JOIN t3) ** @@ -3480,27 +3491,15 @@ static int flattenSubquery( ** ** which is not at all the same thing. ** - ** OBSOLETE COMMENT 2: - ** Restriction 12: If the subquery is the right operand of a left outer - ** join, make sure the subquery has no WHERE clause. - ** An examples of why this is not allowed: - ** - ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 - ** - ** But the t2.x>0 test will always fail on a NULL row of t2, which - ** effectively converts the OUTER JOIN into an INNER JOIN. - ** - ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE: - ** Ticket #3300 shows that flattening the right term of a LEFT JOIN - ** is fraught with danger. Best to avoid the whole thing. If the - ** subquery is the right term of a LEFT JOIN, then do not flatten. + ** See also tickets #306 and #3300. */ if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ - return 0; + isLeftJoin = 1; + if( pSubSrc->nSrc>1 ){ + return 0; /* Restriction (3b) */ + } + /* TBD: Deal with the case of result-set expressions that are non-NULL even + ** when the RHS table of a LEFT JOIN is NULL. */ } /* Restriction 17: If the sub-query is a compound SELECT, then it must @@ -3709,6 +3708,7 @@ static int flattenSubquery( sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); pSrc->a[i+iFrom] = pSubSrc->a[i]; + iNewParent = pSubSrc->a[i].iCursor; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } pSrc->a[iFrom].fg.jointype = jointype; @@ -3754,6 +3754,9 @@ static int flattenSubquery( pSub->pOrderBy = 0; } pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); + if( isLeftJoin ){ + setJoinExpr(pWhere, iNewParent); + } if( subqueryIsAgg ){ assert( pParent->pHaving==0 ); pParent->pHaving = pParent->pWhere; @@ -3770,6 +3773,7 @@ static int flattenSubquery( SubstContext x; x.pParse = pParse; x.iTable = iParent; + x.iNewTable = iNewParent; x.pEList = pSub->pEList; substSelect(&x, pParent, 0); } @@ -3878,6 +3882,7 @@ static int pushDownWhereTerms( pNew = sqlite3ExprDup(pParse->db, pWhere, 0); x.pParse = pParse; x.iTable = iCursor; + x.iNewTable = iCursor; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); From 31d6fd5507ce0f7299a64eb20026ffa3e376b9f8 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 14 Apr 2017 19:03:10 +0000 Subject: [PATCH 02/15] Add the TK_IF_NULL_ROW opcode to deal with non-NULL result columns in the result set of a view or subquery on the RHS of a LEFT JOIN that gets flattened. FossilOrigin-Name: 3a5860d86fadcf924316707918bf283d26c53b1473e5e67f5cff59d18c2a7742 --- manifest | 27 ++++++++++++--------------- manifest.uuid | 2 +- src/expr.c | 11 +++++++++++ src/parse.y | 34 +++++++++++++++++----------------- src/select.c | 31 +++++++++++++++++-------------- src/treeview.c | 5 +++++ src/vdbe.c | 17 +++++++++++++++++ src/where.c | 2 ++ tool/addopcodes.tcl | 1 + 9 files changed, 83 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index a7b73eecdf..155f797a31 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C An\sinitial\sattempt\sto\soptimize\sVIEWs\sthat\soccur\sas\sthe\sright\soperand\sof\sa\nLEFT\sJOIN.\s\sThis\sparticular\scheck-in\sdoes\snot\swork\scorrectly\sbecause\sit\sdoes\nnot\sdeal\swith\sthe\scase\sof\scolumns\sin\sthe\sVIEW\sthat\sreturn\snon-NULL\seven\swhen\nall\scolumns\sin\sthe\stable\sof\sthe\sVIEW\sare\sNULL\sbecause\sof\sthe\sLEFT\sJOIN. -D 2017-04-14T17:18:45.647 +C Add\sthe\sTK_IF_NULL_ROW\sopcode\sto\sdeal\swith\snon-NULL\sresult\scolumns\sin\sthe\nresult\sset\sof\sa\sview\sor\ssubquery\son\sthe\sRHS\sof\sa\sLEFT\sJOIN\sthat\sgets\sflattened. +D 2017-04-14T19:03:10.224 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -354,7 +354,7 @@ F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c -F src/expr.c f6914d6d06c9a1e488f49cd51a0ef12d8073231e9c1a25c4c821262686cadcbf +F src/expr.c f10e35dc50be4c8f82eb99bf5d8530229d1d60957cc3c9473ffe584d0444087c F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174 @@ -390,7 +390,7 @@ F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa -F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105 +F src/parse.y 0513387ce02fea97897d8caef82d45f347818593f24f1bdc48e0c530a8af122d F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc @@ -401,7 +401,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 52b29bdeaa4cf317a981b6e8d0a15ec9c16372a738ede51c2a285c03fc69d036 +F src/select.c bf8ab605e49717c222136380453cfb7eda564f8e500d5ff6a01341ea59fefe80 F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d F src/sqlite.h.in 40233103e3e4e10f8a63523498d0259d232e42aba478e2d3fb914799185aced6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -462,13 +462,13 @@ F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5 -F src/treeview.c b92d57c1ac59f4a3f6b189506921a2b48098f6f4d6afd0b715bc2815ef6af092 +F src/treeview.c 6cf8d7fe9e63fae57dad1bb57f6615e14eac0c527e43d868e805042cae8ed1f7 F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182 F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569 -F src/vdbe.c 808fda3d50f544120d27c731449b524b4ec8f8b0f734b228831078f0ba53ecb9 +F src/vdbe.c ef0fd44a2b4f70e006d050a98c6f563e19293d683975a95287668340764f99f1 F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848 F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860 @@ -482,7 +482,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791 -F src/where.c 1d14e18f32231fa7969e718e7b60ef749b0065e2a7e1b6b00883b20732d280f1 +F src/where.c e02cbd8a830d36e48b1640d0c7b49526322e35fa800c729c17c5d63712a01275 F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681 F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745 @@ -1483,7 +1483,7 @@ F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 -F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189 +F tool/addopcodes.tcl edbd53806bf20e25af2373ad0c091be4385081c1aa1813b916bf093f94ed8380 F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x @@ -1571,10 +1571,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6bf673767b8e5cedef1acff795cbe524fab8db2525c06424db4e038934a33936 -R 8dfa3ca7454fc6936bedb04ccf47ee12 -T *branch * left-join-view -T *sym-left-join-view * -T -sym-trunk * +P 1838a59c8a1c151bd6fc822b0ffef661803cf0e4704c917e74a04567b81740b9 +R c4158b7e84d910d8bf443bd31845d425 U drh -Z 5ef873863ca7134987a034a627c04882 +Z 30ed19e82c986c3025ce3aa1a6102ed4 diff --git a/manifest.uuid b/manifest.uuid index f881b041a7..bf413e2eb0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1838a59c8a1c151bd6fc822b0ffef661803cf0e4704c917e74a04567b81740b9 \ No newline at end of file +3a5860d86fadcf924316707918bf283d26c53b1473e5e67f5cff59d18c2a7742 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index ad17c5f229..873911633f 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3889,6 +3889,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } + case TK_IF_NULL_ROW: { + int addrINR; + addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); + sqlite3ExprCachePush(pParse); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + sqlite3ExprCachePop(pParse); + sqlite3VdbeJumpHere(v, addrINR); + sqlite3VdbeChangeP3(v, addrINR, inReg); + break; + } + /* ** Form A: ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END diff --git a/src/parse.y b/src/parse.y index ef9d3dd0ec..522c805482 100644 --- a/src/parse.y +++ b/src/parse.y @@ -193,6 +193,23 @@ columnlist ::= columnlist COMMA columnname carglist. columnlist ::= columnname carglist. columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} +// The following directive causes tokens ABORT, AFTER, ASC, etc. to +// fallback to ID if they will not parse as their original value. +// This obviates the need for the "id" nonterminal. +// +%fallback ID + ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW + CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR + IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN + QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW + ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT +%ifdef SQLITE_OMIT_COMPOUND_SELECT + EXCEPT INTERSECT UNION +%endif SQLITE_OMIT_COMPOUND_SELECT + REINDEX RENAME CTIME_KW IF + . +%wildcard ANY. + // Define operator precedence early so that this is the first occurrence // of the operator tokens in the grammer. Keeping the operators together // causes them to be assigned integer values that are close together, @@ -222,23 +239,6 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} // %token_class id ID|INDEXED. -// The following directive causes tokens ABORT, AFTER, ASC, etc. to -// fallback to ID if they will not parse as their original value. -// This obviates the need for the "id" nonterminal. -// -%fallback ID - ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW - CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR - IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN - QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW - ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT -%ifdef SQLITE_OMIT_COMPOUND_SELECT - EXCEPT INTERSECT UNION -%endif SQLITE_OMIT_COMPOUND_SELECT - REINDEX RENAME CTIME_KW IF - . -%wildcard ANY. - // And "ids" is an identifer-or-string. // diff --git a/src/select.c b/src/select.c index 8e952d5a8a..3def13618e 100644 --- a/src/select.c +++ b/src/select.c @@ -3154,7 +3154,8 @@ static int multiSelectOrderBy( typedef struct SubstContext { Parse *pParse; /* The parsing context */ int iTable; /* Replace references to this table */ - int iNewTable; /* New table number, or -1 */ + int iNewTable; /* New table number */ + int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ ExprList *pEList; /* Replacement expressions */ } SubstContext; @@ -3189,12 +3190,20 @@ static Expr *substExpr( }else{ Expr *pNew; Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; + Expr ifNullRow; assert( pSubst->pEList!=0 && pExpr->iColumnpEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ sqlite3 *db = pSubst->pParse->db; + if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){ + memset(&ifNullRow, 0, sizeof(ifNullRow)); + ifNullRow.op = TK_IF_NULL_ROW; + ifNullRow.pLeft = pCopy; + ifNullRow.iTable = pSubst->iNewTable; + pCopy = &ifNullRow; + } pNew = sqlite3ExprDup(db, pCopy, 0); if( pNew && (pExpr->flags & EP_FromJoin) ){ pNew->iRightJoinTable = pExpr->iRightJoinTable; @@ -3288,14 +3297,8 @@ static void substSelect( ** FROM-clause subquery that is a candidate for flattening. (2b is ** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ** -** (3) The subquery is not the right operand of a left outer join -** or (3b) the subquery is not a join and (3c) does not contain any -** result-set columns that could be non-NULL even if columns of the -** subquery table are NULL. -** to be more restrictive - disallowing subquery if it was the -** right operand of a left join. See tickets #306 and #3300. Relaxed -** to allow simple subqueries as the right operand of a left join -** on 2017-04-14.) +** (3) The subquery is not the right operand of a LEFT JOIN +** or the subquery is not itself a join. ** ** (4) The subquery is not DISTINCT. ** @@ -3307,7 +3310,7 @@ static void substSelect( ** DISTINCT. ** ** (7) The subquery has a FROM clause. TODO: For subqueries without -** A FROM clause, consider adding a FROM close with the special +** A FROM clause, consider adding a FROM clause with the special ** table sqlite_once that consists of a single row containing a ** single NULL. ** @@ -3491,15 +3494,13 @@ static int flattenSubquery( ** ** which is not at all the same thing. ** - ** See also tickets #306 and #3300. + ** See also tickets #306, #350, and #3300. */ if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ isLeftJoin = 1; if( pSubSrc->nSrc>1 ){ - return 0; /* Restriction (3b) */ + return 0; /* Restriction (3) */ } - /* TBD: Deal with the case of result-set expressions that are non-NULL even - ** when the RHS table of a LEFT JOIN is NULL. */ } /* Restriction 17: If the sub-query is a compound SELECT, then it must @@ -3774,6 +3775,7 @@ static int flattenSubquery( x.pParse = pParse; x.iTable = iParent; x.iNewTable = iNewParent; + x.isLeftJoin = isLeftJoin; x.pEList = pSub->pEList; substSelect(&x, pParent, 0); } @@ -3883,6 +3885,7 @@ static int pushDownWhereTerms( x.pParse = pParse; x.iTable = iCursor; x.iNewTable = iCursor; + x.isLeftJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); diff --git a/src/treeview.c b/src/treeview.c index e4f3d781ba..fc188256f9 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -470,6 +470,11 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); break; } + case TK_IF_NULL_ROW: { + sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); + break; + } default: { sqlite3TreeViewLine(pView, "op=%d", pExpr->op); break; diff --git a/src/vdbe.c b/src/vdbe.c index a990afb11d..cd3d08a140 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2429,6 +2429,23 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ break; } +/* Opcode: IfNullRow P1 P2 P3 * * +** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2 +** +** Check the cursor P1 to see if it is currently pointing at a NULL row. +** If it is, then set register P3 to NULL and jump immediately to P2. +** If P1 is not on a NULL row, then fall through without making any +** changes. +*/ +case OP_IfNullRow: { /* jump */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + if( p->apCsr[pOp->p1]->nullRow ){ + sqlite3VdbeMemSetNull(aMem + pOp->p3); + goto jump_to_p2; + } + break; +} + /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX ** diff --git a/src/where.c b/src/where.c index 38183d6849..5c5652f058 100644 --- a/src/where.c +++ b/src/where.c @@ -4976,6 +4976,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; + }else if( pOp->opcode==OP_IfNullRow ){ + pOp->p1 = pLevel->iIdxCur; } } } diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index a6c58f1a25..308ddcb6bd 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -39,6 +39,7 @@ set extras { REGISTER VECTOR SELECT_COLUMN + IF_NULL_ROW ASTERISK SPAN SPACE From b65b3e429afce35f9bb99788391ca8bfbab339f6 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 16 Apr 2017 22:08:31 +0000 Subject: [PATCH 03/15] Add the anycollseq.c loadable extension in etc/misc FossilOrigin-Name: d7b9813cb17615c3d00afd6994a4309d6d48c8e924b6cd813c543e1fa65c7719 --- ext/misc/anycollseq.c | 58 +++++++++++++++++++++++++++++++++++++++++++ manifest | 12 ++++----- manifest.uuid | 2 +- 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 ext/misc/anycollseq.c diff --git a/ext/misc/anycollseq.c b/ext/misc/anycollseq.c new file mode 100644 index 0000000000..27b7049d5f --- /dev/null +++ b/ext/misc/anycollseq.c @@ -0,0 +1,58 @@ +/* +** 2017-04-16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements a run-time loadable extension to SQLite that +** registers a sqlite3_collation_needed() callback to register a fake +** collating function for any unknown collating sequence. The fake +** collating function works like BINARY. +** +** This extension can be used to load schemas that contain one or more +** unknown collating sequences. +*/ +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#include + +static int anyCollFunc( + void *NotUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1 Date: Sun, 16 Apr 2017 22:41:49 +0000 Subject: [PATCH 04/15] In the showwal command-line tool, for unix builds, if the auxiliary argument is of the form "Ntruncate" where "N" is a frame number, then truncate the WAL file after the N-th frame. FossilOrigin-Name: 90015df30655d884ecf7ae61e588824696954252dc6b1a5f78cf2de8cb236104 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/showwal.c | 9 +++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 8bb03a4eb8..7660e6380e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sanycollseq.c\sloadable\sextension\sin\setc/misc -D 2017-04-16T22:08:31.808 +C In\sthe\sshowwal\scommand-line\stool,\sfor\sunix\sbuilds,\sif\sthe\nauxiliary\sargument\sis\sof\nthe\sform\s"Ntruncate"\swhere\s"N"\sis\sa\sframe\snumber,\sthen\struncate\sthe\sWAL\nfile\safter\sthe\sN-th\sframe. +D 2017-04-16T22:41:49.287 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -1530,7 +1530,7 @@ F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818 F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9 -F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977 +F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda @@ -1573,7 +1573,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 89f9e4363aa19f306e55f749c442eae2f8994f6a47c65e645a79b308b450d5e5 -R 7e7a9c3544574aec28a263899284e68c +P d7b9813cb17615c3d00afd6994a4309d6d48c8e924b6cd813c543e1fa65c7719 +R 8c1cbe1045ee7677fda3e059322e3580 U drh -Z ee9d941ffe6bc63689ac0fdb0270a043 +Z aa5715d42d381110f91b49a6f98fcf69 diff --git a/manifest.uuid b/manifest.uuid index 380e051165..14a8d9cd9b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d7b9813cb17615c3d00afd6994a4309d6d48c8e924b6cd813c543e1fa65c7719 \ No newline at end of file +90015df30655d884ecf7ae61e588824696954252dc6b1a5f78cf2de8cb236104 \ No newline at end of file diff --git a/tool/showwal.c b/tool/showwal.c index 33cc21896b..b214a288eb 100644 --- a/tool/showwal.c +++ b/tool/showwal.c @@ -12,6 +12,7 @@ #if !defined(_MSC_VER) #include +#include #else #include #endif @@ -579,6 +580,14 @@ int main(int argc, char **argv){ decode_btree_page(a, iStart, hdrSize, zLeft+1); free(a); continue; +#if !defined(_MSC_VER) + }else if( zLeft && strcmp(zLeft,"truncate")==0 ){ + /* Frame number followed by "truncate" truncates the WAL file + ** after that frame */ + off_t newSize = 32 + iStart*(pagesize+24); + truncate(argv[1], newSize); + continue; +#endif }else{ iEnd = iStart; } From 6887e8facd4907f87505eaa830e093f3d19edf8d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Apr 2017 13:18:42 +0000 Subject: [PATCH 05/15] Fix the ".column" output mode in the command-line shell so that it correctly counts and formats multi-byte UTF characters. FossilOrigin-Name: f508aff8d1782abdff4d03726ae098607a0ee6cfd2e35b130097ee5043e98960 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c | 50 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 7660e6380e..e78a637233 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sshowwal\scommand-line\stool,\sfor\sunix\sbuilds,\sif\sthe\nauxiliary\sargument\sis\sof\nthe\sform\s"Ntruncate"\swhere\s"N"\sis\sa\sframe\snumber,\sthen\struncate\sthe\sWAL\nfile\safter\sthe\sN-th\sframe. -D 2017-04-16T22:41:49.287 +C Fix\sthe\s".column"\soutput\smode\sin\sthe\scommand-line\sshell\sso\sthat\sit\scorrectly\ncounts\sand\sformats\smulti-byte\sUTF\scharacters. +D 2017-04-17T13:18:42.048 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -403,7 +403,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 4588dcfb0fa430012247a209ba08e17904dd32ec7690e9cb6c85e0ef012b0518 -F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d +F src/shell.c 21b79c0e1b93f8e35fd7b4087d6ba438326c3d7e285d0dd51dfd741475f858a1 F src/sqlite.h.in 40233103e3e4e10f8a63523498d0259d232e42aba478e2d3fb914799185aced6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 @@ -1573,7 +1573,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d7b9813cb17615c3d00afd6994a4309d6d48c8e924b6cd813c543e1fa65c7719 -R 8c1cbe1045ee7677fda3e059322e3580 +P 90015df30655d884ecf7ae61e588824696954252dc6b1a5f78cf2de8cb236104 +R f3fe31d09ab4f188db4ba42e5036f494 U drh -Z aa5715d42d381110f91b49a6f98fcf69 +Z b0a62e79cb4eb34b7f5f7cf838722768 diff --git a/manifest.uuid b/manifest.uuid index 14a8d9cd9b..a92b1214ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90015df30655d884ecf7ae61e588824696954252dc6b1a5f78cf2de8cb236104 \ No newline at end of file +f508aff8d1782abdff4d03726ae098607a0ee6cfd2e35b130097ee5043e98960 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 8341d828c1..15c88061c2 100644 --- a/src/shell.c +++ b/src/shell.c @@ -427,6 +427,36 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ } #endif +/* +** Output string zUtf to stream pOut as w characters. If w is negative, +** then right-justify the text. W is the width in UTF-8 characters, not +** in bytes. This is different from the %*.*s specification in printf +** since with %*.*s the width is measured in bytes, not characters. +*/ +static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ + int i; + int n; + int aw = w<0 ? -w : w; + char zBuf[1000]; + if( aw>sizeof(zBuf)/3 ) aw = sizeof(zBuf)/3; + for(i=n=0; zUtf[i]; i++){ + if( (zUtf[i]&0xc0)!=0x80 ){ + n++; + if( n==aw ){ + do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); + break; + } + } + } + if( n>=aw ){ + utf8_printf(pOut, "%.*s", i, zUtf); + }else if( w<0 ){ + utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); + }else{ + utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); + } +} + /* ** Determines if a string is a number of not. @@ -1878,13 +1908,8 @@ static int shell_callback( p->actualWidth[i] = w; } if( showHdr ){ - if( w<0 ){ - utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], - i==nArg-1 ? rowSep : " "); - }else{ - utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], - i==nArg-1 ? rowSep : " "); - } + utf8_width_print(p->out, w, azCol[i]); + utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " "); } } if( showHdr ){ @@ -1920,15 +1945,8 @@ static int shell_callback( } p->iIndent++; } - if( w<0 ){ - utf8_printf(p->out,"%*.*s%s",-w,-w, - azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? rowSep : " "); - }else{ - utf8_printf(p->out,"%-*.*s%s",w,w, - azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? rowSep : " "); - } + utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue); + utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " "); } break; } From ddf4747053877cd8d3050c668b3c36ab97157850 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Apr 2017 13:38:09 +0000 Subject: [PATCH 06/15] Improve coverage of code in fts3. FossilOrigin-Name: 1a08a836fa919524216a16faf5212eebc9ad788c9e15463b68b0576dfccd4387 --- ext/fts3/fts3.c | 105 +++++++++++++++++++++-------------------- manifest | 24 +++++----- manifest.uuid | 2 +- test/fts3aa.test | 7 +++ test/fts3corrupt3.test | 42 +++++++++++++++++ test/fts3fault.test | 12 +++-- test/fts4langid.test | 8 +++- test/permutations.test | 1 + 8 files changed, 132 insertions(+), 69 deletions(-) create mode 100644 test/fts3corrupt3.test diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 6f059bc95d..40ce6ec27a 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1219,65 +1219,66 @@ static int fts3InitVtab( break; } } - if( iOpt==SizeofArray(aFts4Opt) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); - rc = SQLITE_ERROR; - }else{ - switch( iOpt ){ - case 0: /* MATCHINFO */ - if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); - rc = SQLITE_ERROR; - } - bNoDocsize = 1; - break; + switch( iOpt ){ + case 0: /* MATCHINFO */ + if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ + sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); + rc = SQLITE_ERROR; + } + bNoDocsize = 1; + break; - case 1: /* PREFIX */ - sqlite3_free(zPrefix); - zPrefix = zVal; - zVal = 0; - break; + case 1: /* PREFIX */ + sqlite3_free(zPrefix); + zPrefix = zVal; + zVal = 0; + break; - case 2: /* COMPRESS */ - sqlite3_free(zCompress); - zCompress = zVal; - zVal = 0; - break; + case 2: /* COMPRESS */ + sqlite3_free(zCompress); + zCompress = zVal; + zVal = 0; + break; - case 3: /* UNCOMPRESS */ - sqlite3_free(zUncompress); - zUncompress = zVal; - zVal = 0; - break; + case 3: /* UNCOMPRESS */ + sqlite3_free(zUncompress); + zUncompress = zVal; + zVal = 0; + break; - case 4: /* ORDER */ - if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) - && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) - ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); - rc = SQLITE_ERROR; - } - bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); - break; + case 4: /* ORDER */ + if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) + && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) + ){ + sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); + rc = SQLITE_ERROR; + } + bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); + break; - case 5: /* CONTENT */ - sqlite3_free(zContent); - zContent = zVal; - zVal = 0; - break; + case 5: /* CONTENT */ + sqlite3_free(zContent); + zContent = zVal; + zVal = 0; + break; - case 6: /* LANGUAGEID */ - assert( iOpt==6 ); - sqlite3_free(zLanguageid); - zLanguageid = zVal; - zVal = 0; - break; + case 6: /* LANGUAGEID */ + assert( iOpt==6 ); + sqlite3_free(zLanguageid); + zLanguageid = zVal; + zVal = 0; + break; - case 7: /* NOTINDEXED */ - azNotindexed[nNotindexed++] = zVal; - zVal = 0; - break; - } + case 7: /* NOTINDEXED */ + azNotindexed[nNotindexed++] = zVal; + zVal = 0; + break; + + default: + assert( iOpt==SizeofArray(aFts4Opt) ); + sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); + rc = SQLITE_ERROR; + break; } sqlite3_free(zVal); } diff --git a/manifest b/manifest index e78a637233..101001412b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\s".column"\soutput\smode\sin\sthe\scommand-line\sshell\sso\sthat\sit\scorrectly\ncounts\sand\sformats\smulti-byte\sUTF\scharacters. -D 2017-04-17T13:18:42.048 +C Improve\scoverage\sof\scode\sin\sfts3. +D 2017-04-17T13:38:09.238 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -70,7 +70,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 f0d5de1bc2155ba7cd7c0c1a751779a3a8857fa34d5c12f3b233a23fa2e79ea2 +F ext/fts3/fts3.c a05d3acd671a2b5a76adcc5d01c05d93c18a7f6e8f0a8595d0dd12cdde4c9969 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -752,7 +752,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654 F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0 -F test/fts3aa.test 6c263a6f8845205ee02550981a94c2e8dc1e7058 +F test/fts3aa.test 8bf242c0a59867ac2fb0cd5b9f71dabb3cbe9c18a859f61f6e0853d52e483183 F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63 F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49 @@ -777,6 +777,7 @@ F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c F test/fts3conf.test 60317efd562080e198b5bdc9fcd222ce32cf01d7 F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba +F test/fts3corrupt3.test d371712ce1ddaa09f8fa59b6bd8d6512210be3c09855554ebc8b882fb69a929a F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7 F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708 F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963 @@ -789,7 +790,7 @@ F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3 F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 -F test/fts3fault.test da49627b280b210ebc6657f76344c7851f10ce66 +F test/fts3fault.test 268e9589f44f49d6694ef39a293f0e0f80c6230fb01cc6f34325412acceb99ae F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da @@ -814,7 +815,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d -F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d +F test/fts4langid.test 89a107d36710dc3f44dab0861a784ffab967bd1f32c8d700b031748b9d2703c6 F test/fts4lastrowid.test fa5e157955a3121615ef3e16ff5196e96c9e1e64 F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 @@ -1030,7 +1031,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test af720e7d139e7e5417341d0f0eef2b911c0b067852138dc2f5b6a451b5725118 +F test/permutations.test cb5e80dd5a00ad3e1f2ecbd5d78d8345c7f47c554b5409d4f242afcc6afcbdf5 F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed @@ -1573,7 +1574,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 90015df30655d884ecf7ae61e588824696954252dc6b1a5f78cf2de8cb236104 -R f3fe31d09ab4f188db4ba42e5036f494 -U drh -Z b0a62e79cb4eb34b7f5f7cf838722768 +P f508aff8d1782abdff4d03726ae098607a0ee6cfd2e35b130097ee5043e98960 +Q +9fe229cdf3d4684f4feb0dea0ca14aebd028e64f9be8c3ec9435cf2103aad2bd +R 1f0577dbe9b73d480704c675ac83362f +U dan +Z 3f6cd808adfc219b5f58b1c64aa88fca diff --git a/manifest.uuid b/manifest.uuid index a92b1214ce..4011dda1b7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f508aff8d1782abdff4d03726ae098607a0ee6cfd2e35b130097ee5043e98960 \ No newline at end of file +1a08a836fa919524216a16faf5212eebc9ad788c9e15463b68b0576dfccd4387 \ No newline at end of file diff --git a/test/fts3aa.test b/test/fts3aa.test index 08d825dd17..7c4cb99910 100644 --- a/test/fts3aa.test +++ b/test/fts3aa.test @@ -244,4 +244,11 @@ do_execsql_test 8.5 { } {} +do_execsql_test 9.1 { + CREATE VIRTUAL TABLE t9 USING fts4(a, "", '---'); +} +do_execsql_test 9.2 { + CREATE VIRTUAL TABLE t10 USING fts3(<, b, c); +} + finish_test diff --git a/test/fts3corrupt3.test b/test/fts3corrupt3.test new file mode 100644 index 0000000000..48d68fade2 --- /dev/null +++ b/test/fts3corrupt3.test @@ -0,0 +1,42 @@ +# 2010 October 27 +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# Test that the FTS3 extension does not crash when it encounters a +# corrupt data structure on disk. +# + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# If SQLITE_ENABLE_FTS3 is not defined, omit this file. +ifcapable !fts3 { finish_test ; return } + +set ::testprefix fts3corrupt3 + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts3; + BEGIN; + INSERT INTO t1 VALUES('one'); + INSERT INTO t1 VALUES('one'); + INSERT INTO t1 VALUES('one'); + COMMIT; +} +do_execsql_test 1.1 { + SELECT quote(root) from t1_segdir; +} {X'00036F6E6509010200010200010200'} +do_execsql_test 1.2 { + UPDATE t1_segdir SET root = X'00036F6E650EFFFFFFFFFFFFFFFFFFFFFFFF0200'; +} +do_catchsql_test 1.3 { + SELECT rowid FROM t1 WHERE t1 MATCH 'one' +} {0 -1} + + + + +finish_test diff --git a/test/fts3fault.test b/test/fts3fault.test index 7d94332059..2622e47136 100644 --- a/test/fts3fault.test +++ b/test/fts3fault.test @@ -18,8 +18,6 @@ set ::testprefix fts3fault # If SQLITE_ENABLE_FTS3 is not defined, omit this file. ifcapable !fts3 { finish_test ; return } -if 0 { - # Test error handling in the sqlite3Fts3Init() function. This is the # function that registers the FTS3 module and various support functions # with SQLite. @@ -160,8 +158,6 @@ do_faultsim_test 7.3 -prep { } -} - proc mit {blob} { set scan(littleEndian) i* set scan(bigEndian) I* @@ -234,4 +230,12 @@ do_faultsim_test 9.1 -prep { faultsim_test_result {0 {{0 0 20 39 0 0 64 2}}} } +do_faultsim_test 10.1 -prep { + faultsim_delete_and_reopen +} -body { + execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, languageid=d) } +} -test { + faultsim_test_result {0 {}} +} + finish_test diff --git a/test/fts4langid.test b/test/fts4langid.test index fdb1876be8..9954acd718 100644 --- a/test/fts4langid.test +++ b/test/fts4langid.test @@ -14,7 +14,6 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -set ::testprefix fts4content # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts3 { @@ -341,6 +340,13 @@ do_test_query1 3.3.4 {"zero one" OR "one two"} { or_merge_lists [rowid_list "zero one"] [rowid_list "one two"] } +do_execsql_test 3.4 { + CREATE TABLE t8c(a, b); + CREATE VIRTUAL TABLE t8 USING fts4(content=t8c, languageid=langid); + INSERT INTO t8(docid, a, b) VALUES(-1, 'one two three', 'x y z'); + SELECT docid FROM t8 WHERE t8 MATCH 'one x' AND langid=0 +} {-1} + #------------------------------------------------------------------------- # Test cases 4.* # diff --git a/test/permutations.test b/test/permutations.test index 628e7ba44e..e4da7207f0 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -265,6 +265,7 @@ test_suite "fts3" -prefix "" -description { fts4incr.test fts4langid.test fts4lastrowid.test fts4merge2.test fts4merge4.test fts4merge.test fts4noti.test fts4onepass.test fts4opt.test fts4unicode.test + fts3corrupt3.test } test_suite "fts5" -prefix "" -description { From 624edacf6a0a08f7538d7593f146287f62c959be Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Apr 2017 16:07:25 +0000 Subject: [PATCH 07/15] Further improvements to test coverage in fts3. FossilOrigin-Name: 352413eed469802665e7d2c17b7fe6e3a0b0b2209ce45bdc85fd4243cec50ea6 --- ext/fts3/fts3.c | 13 +++-- manifest | 23 ++++---- manifest.uuid | 2 +- test/fts3aa.test | 1 - test/fts3corrupt3.test | 23 ++++++++ test/fts3fault2.test | 18 ++++++ test/fts3misc.test | 124 +++++++++++++++++++++++++++++++++++++++++ test/permutations.test | 1 + 8 files changed, 187 insertions(+), 18 deletions(-) create mode 100644 test/fts3misc.test diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 40ce6ec27a..9cafd8e591 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -372,8 +372,8 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ } /* -** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a -** 32-bit integer before it is returned. +** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to +** a non-negative 32-bit integer before it is returned. */ int sqlite3Fts3GetVarint32(const char *p, int *pi){ u32 a; @@ -389,7 +389,9 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){ GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3); GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4); a = (a & 0x0FFFFFFF ); - *pi = (int)(a | ((u32)(*p & 0x0F) << 28)); + *pi = (int)(a | ((u32)(*p & 0x07) << 28)); + assert( 0==(a & 0x80000000) ); + assert( *pi>=0 ); return 5; } @@ -1847,7 +1849,8 @@ static int fts3ScanInteriorNode( isFirstTerm = 0; zCsr += fts3GetVarint32(zCsr, &nSuffix); - if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){ + assert( nPrefix>=0 && nSuffix>=0 ); + if( &zCsr[nSuffix]>zEnd ){ rc = FTS_CORRUPT_VTAB; goto finish_scan; } @@ -2657,7 +2660,7 @@ int sqlite3Fts3FirstFilter( fts3ColumnlistCopy(0, &p); } - while( p Date: Mon, 17 Apr 2017 18:02:41 +0000 Subject: [PATCH 08/15] Fix a problem in "PRAGMA foreign_key_check" in handling a WITHOUT ROWID child table with an INTEGER PRIMARY KEY parent key. Also, if an FK violation is detected in a WITHOUT ROWID child table, do not try to read and return the rowid. The third column returned by "PRAGMA foreign_key_check" in this case (WITHOUT ROWID child table) is now always set to NULL. FossilOrigin-Name: 690870bd7b2e607b7992c4496c9f08c29eb72a36af002c606fd7aa3dcf94a2a4 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/pragma.c | 10 +++++++--- test/fkey5.test | 23 +++++++++++++++++++++++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index bffc8069fb..b80db914a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\stest\scoverage\sin\sfts3. -D 2017-04-17T16:07:25.320 +C Fix\sa\sproblem\sin\s"PRAGMA\sforeign_key_check"\sin\shandling\sa\sWITHOUT\sROWID\schild\ntable\swith\san\sINTEGER\sPRIMARY\sKEY\sparent\skey.\sAlso,\sif\san\sFK\sviolation\sis\ndetected\sin\sa\sWITHOUT\sROWID\schild\stable,\sdo\snot\stry\sto\sread\sand\sreturn\sthe\nrowid.\sThe\sthird\scolumn\sreturned\sby\s"PRAGMA\sforeign_key_check"\sin\sthis\scase\n(WITHOUT\sROWID\schild\stable)\sis\snow\salways\sset\sto\sNULL. +D 2017-04-17T18:02:41.447 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -395,7 +395,7 @@ F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc -F src/pragma.c 220474f113cade6a6b5bacd3e3a65eca339acbee804128bc5db13a9cad55fba5 +F src/pragma.c 943f71f762d8c7ab5a7b00641308cb9cd5effeddc3c709f0303e394ca8c21228 F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921 F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 @@ -708,7 +708,7 @@ F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4 F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d -F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a +F test/fkey5.test 67eac5be27ab6c80b1131ed7a060d0df5df748a0cb51600db495221a0e70b732 F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c @@ -1575,8 +1575,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1a08a836fa919524216a16faf5212eebc9ad788c9e15463b68b0576dfccd4387 -Q +e00aa665903d2328bab3f192ad364e43d5d8483509671626d8ef5384b305557f -R e503b12d92602617090d73924f6d0603 +P 352413eed469802665e7d2c17b7fe6e3a0b0b2209ce45bdc85fd4243cec50ea6 +R 46f0a9ecba377acfe7b4e03c3b9e97dc U dan -Z 3da6b7e6b10076610ce2d669ba020b22 +Z a6a806ccfe0a8fddda7afe6e73d07801 diff --git a/manifest.uuid b/manifest.uuid index 0945f8bf91..fa5e7a216c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -352413eed469802665e7d2c17b7fe6e3a0b0b2209ce45bdc85fd4243cec50ea6 \ No newline at end of file +690870bd7b2e607b7992c4496c9f08c29eb72a36af002c606fd7aa3dcf94a2a4 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 7f0b683f13..45b190fbd8 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1333,8 +1333,8 @@ void sqlite3Pragma( int iKey = pFK->aCol[0].iFrom; assert( iKey>=0 && iKeynCol ); if( iKey!=pTab->iPKey ){ - sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); - sqlite3ColumnDefault(v, pTab, iKey, regRow); + sqlite3ExprCodeGetColumnOfTable( + v, pTab, 0, pFK->aCol[0].iFrom, regRow); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); @@ -1355,7 +1355,11 @@ void sqlite3Pragma( VdbeCoverage(v); } } - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1); + } sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); sqlite3VdbeResolveLabel(v, addrOk); diff --git a/test/fkey5.test b/test/fkey5.test index b9e1fc2eec..690983460d 100644 --- a/test/fkey5.test +++ b/test/fkey5.test @@ -388,5 +388,28 @@ do_execsql_test 9.4 { PRAGMA foreign_key_check(k2); } {k2 3 s1 0} +#------------------------------------------------------------------------- +# Test using a WITHOUT ROWID table as the child table with an INTEGER +# PRIMARY KEY as the parent key. +# +reset_db +do_execsql_test 10.1 { + CREATE TABLE p30 (id INTEGER PRIMARY KEY); + CREATE TABLE IF NOT EXISTS c30 ( + line INTEGER, + master REFERENCES p30(id), + PRIMARY KEY(master) + ) WITHOUT ROWID; + + INSERT INTO p30 (id) VALUES (1); + INSERT INTO c30 (master, line) VALUES (1, 999); +} +do_execsql_test 10.2 { + PRAGMA foreign_key_check; +} +do_execsql_test 10.3 { + INSERT INTO c30 VALUES(45, 45); + PRAGMA foreign_key_check; +} {c30 {} p30 0} finish_test From 4bee5599c0cce4d3e100ce4e07e8ab09548a9084 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Apr 2017 18:42:33 +0000 Subject: [PATCH 09/15] Consolidate two branches of code in the "PRAGMA foreign_key_check" implementation. FossilOrigin-Name: 69f51f838abcf57b35e41f7a10fbb45f56536f93825aac865debc3c8315930be --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/pragma.c | 50 ++++++++++++++++++++++++------------------------- test/fkey5.test | 12 ++++++++++++ 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index b80db914a6..626df9e1b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\s"PRAGMA\sforeign_key_check"\sin\shandling\sa\sWITHOUT\sROWID\schild\ntable\swith\san\sINTEGER\sPRIMARY\sKEY\sparent\skey.\sAlso,\sif\san\sFK\sviolation\sis\ndetected\sin\sa\sWITHOUT\sROWID\schild\stable,\sdo\snot\stry\sto\sread\sand\sreturn\sthe\nrowid.\sThe\sthird\scolumn\sreturned\sby\s"PRAGMA\sforeign_key_check"\sin\sthis\scase\n(WITHOUT\sROWID\schild\stable)\sis\snow\salways\sset\sto\sNULL. -D 2017-04-17T18:02:41.447 +C Consolidate\stwo\sbranches\sof\scode\sin\sthe\s"PRAGMA\sforeign_key_check"\nimplementation. +D 2017-04-17T18:42:33.368 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -395,7 +395,7 @@ F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc -F src/pragma.c 943f71f762d8c7ab5a7b00641308cb9cd5effeddc3c709f0303e394ca8c21228 +F src/pragma.c 2362670a9d28b71708aecb2b9b10b3f7be71f4c950961c07e81dc400e3ce6371 F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921 F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 @@ -708,7 +708,7 @@ F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4 F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d -F test/fkey5.test 67eac5be27ab6c80b1131ed7a060d0df5df748a0cb51600db495221a0e70b732 +F test/fkey5.test 19a9b73bafd78323c37fc883dba060191541503d6094f8aea67fe94d33118e20 F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c @@ -1575,7 +1575,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 352413eed469802665e7d2c17b7fe6e3a0b0b2209ce45bdc85fd4243cec50ea6 -R 46f0a9ecba377acfe7b4e03c3b9e97dc +P 690870bd7b2e607b7992c4496c9f08c29eb72a36af002c606fd7aa3dcf94a2a4 +R 19c8be4cdee10493f553df8030d2fc52 U dan -Z a6a806ccfe0a8fddda7afe6e73d07801 +Z 1848b8fa31243e1c51d1bf2e158fcffc diff --git a/manifest.uuid b/manifest.uuid index fa5e7a216c..7995338c75 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -690870bd7b2e607b7992c4496c9f08c29eb72a36af002c606fd7aa3dcf94a2a4 \ No newline at end of file +69f51f838abcf57b35e41f7a10fbb45f56536f93825aac865debc3c8315930be \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 45b190fbd8..945fd2d4a7 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1329,32 +1329,32 @@ void sqlite3Pragma( assert( x==0 ); } addrOk = sqlite3VdbeMakeLabel(v); - if( pParent && pIdx==0 ){ - int iKey = pFK->aCol[0].iFrom; - assert( iKey>=0 && iKeynCol ); - if( iKey!=pTab->iPKey ){ - sqlite3ExprCodeGetColumnOfTable( - v, pTab, 0, pFK->aCol[0].iFrom, regRow); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); - } - sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); - sqlite3VdbeGoto(v, addrOk); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - }else{ - for(j=0; jnCol; j++){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, - aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); - } - if( pParent ){ - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, - sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); - VdbeCoverage(v); - } + + /* Generate code to read the child key values into registers + ** regRow..regRow+n. If any of the child key values are NULL, this + ** row cannot cause an FK violation. Jump directly to addrOk in + ** this case. */ + for(j=0; jnCol; j++){ + int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom; + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j); + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); } + + /* Generate code to query the parent index for a matching parent + ** key. If a match is found, jump to addrOk. */ + if( pIdx ){ + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, + sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); + VdbeCoverage(v); + }else if( pParent ){ + int jmp = sqlite3VdbeCurrentAddr(v)+2; + sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v); + sqlite3VdbeGoto(v, addrOk); + assert( pFK->nCol==1 ); + } + + /* Generate code to report an FK violation to the caller. */ if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); }else{ diff --git a/test/fkey5.test b/test/fkey5.test index 690983460d..e9bb47f895 100644 --- a/test/fkey5.test +++ b/test/fkey5.test @@ -412,4 +412,16 @@ do_execsql_test 10.3 { PRAGMA foreign_key_check; } {c30 {} p30 0} +#------------------------------------------------------------------------- +# Test "foreign key mismatch" errors. +# +reset_db +do_execsql_test 11.0 { + CREATE TABLE tt(y); + CREATE TABLE c11(x REFERENCES tt(y)); +} +do_catchsql_test 11.1 { + PRAGMA foreign_key_check; +} {1 {foreign key mismatch - "c11" referencing "tt"}} + finish_test From e2bc6552fe50c6f6cb3189c40e23de329c9c3802 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Apr 2017 20:50:34 +0000 Subject: [PATCH 10/15] Do not allow a Mem object to be both NULL and some other type at the same time. FossilOrigin-Name: e698db1956bb3aba32cd3ec633ec20f5d19b1a10bc68d3772903bca3c87ee158 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 3 ++- src/vdbemem.c | 4 ++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 626df9e1b2..d198802313 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Consolidate\stwo\sbranches\sof\scode\sin\sthe\s"PRAGMA\sforeign_key_check"\nimplementation. -D 2017-04-17T18:42:33.368 +C Do\snot\sallow\sa\sMem\sobject\sto\sbe\sboth\sNULL\sand\ssome\sother\stype\sat\sthe\ssame\stime. +D 2017-04-17T20:50:34.840 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -469,13 +469,13 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569 -F src/vdbe.c 808fda3d50f544120d27c731449b524b4ec8f8b0f734b228831078f0ba53ecb9 +F src/vdbe.c 51c6e166aa208882f28647c2fe59b71326b401f5a45bd5a2f1d3054aa08b33fd F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848 F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860 F src/vdbeaux.c 6b3f6ce909e206d4c918988b13b7fa687e92b4471d137e0f2a37edac80ec60be F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9 -F src/vdbemem.c 3122f5a21064198c10ee1b4686937aab27d5395712d9af905b7fa1affc47a453 +F src/vdbemem.c 2c70f8f5de6c71fb99a22c5b83be9fab5c47cdd8e279fa44a8c00cfed06d7e89 F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790 @@ -1575,7 +1575,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 690870bd7b2e607b7992c4496c9f08c29eb72a36af002c606fd7aa3dcf94a2a4 -R 19c8be4cdee10493f553df8030d2fc52 -U dan -Z 1848b8fa31243e1c51d1bf2e158fcffc +P 69f51f838abcf57b35e41f7a10fbb45f56536f93825aac865debc3c8315930be +R 64888a299504d2f3a6ae0f4b59c9c8bb +U drh +Z cefc6e2d5ac1cd873685a6b283e84cfc diff --git a/manifest.uuid b/manifest.uuid index 7995338c75..1d21d6cd2b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -69f51f838abcf57b35e41f7a10fbb45f56536f93825aac865debc3c8315930be \ No newline at end of file +e698db1956bb3aba32cd3ec633ec20f5d19b1a10bc68d3772903bca3c87ee158 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index a990afb11d..ebd304ecb6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -486,6 +486,7 @@ static void registerTrace(int iReg, Mem *p){ printf("REG[%d] = ", iReg); memTracePrint(p); printf("\n"); + sqlite3VdbeCheckMemInvariants(p); } #endif @@ -1151,7 +1152,7 @@ case OP_Null: { /* out2 */ case OP_SoftNull: { assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); pOut = &aMem[pOp->p1]; - pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined; + pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null; break; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 4f57893767..e95a8d1b9d 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -40,6 +40,10 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ /* Cannot be both MEM_Int and MEM_Real at the same time */ assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); + /* Cannot be both MEM_Null and some other type */ + assert( (p->flags & MEM_Null)==0 || + (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob))==0 ); + /* The szMalloc field holds the correct memory allocation size */ assert( p->szMalloc==0 || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) ); From cfcca0276503c33211e6f02bc6fe8c75319a8d53 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 17 Apr 2017 23:23:17 +0000 Subject: [PATCH 11/15] Defer checking for null in the comparison operators, since that is an uncommon case. FossilOrigin-Name: 5684525613961fed9db6a4d10dbe25521201b24f08e011df3a20ac895316957d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d198802313..e5b734be03 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sa\sMem\sobject\sto\sbe\sboth\sNULL\sand\ssome\sother\stype\sat\sthe\ssame\stime. -D 2017-04-17T20:50:34.840 +C Defer\schecking\sfor\snull\sin\sthe\scomparison\soperators,\ssince\sthat\sis\san\nuncommon\scase. +D 2017-04-17T23:23:17.393 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -469,7 +469,7 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569 -F src/vdbe.c 51c6e166aa208882f28647c2fe59b71326b401f5a45bd5a2f1d3054aa08b33fd +F src/vdbe.c 11604e6c5d350a2c3b820130246c894de5a97d675a16f9825e88839fb9282eb3 F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848 F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860 @@ -1575,7 +1575,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 69f51f838abcf57b35e41f7a10fbb45f56536f93825aac865debc3c8315930be -R 64888a299504d2f3a6ae0f4b59c9c8bb +P e698db1956bb3aba32cd3ec633ec20f5d19b1a10bc68d3772903bca3c87ee158 +R d9474093122e32538bb559c220a1d671 U drh -Z cefc6e2d5ac1cd873685a6b283e84cfc +Z 5309f4dbe4f5abfd0a4417ec6708da32 diff --git a/manifest.uuid b/manifest.uuid index 1d21d6cd2b..23a0f3fc6d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e698db1956bb3aba32cd3ec633ec20f5d19b1a10bc68d3772903bca3c87ee158 \ No newline at end of file +5684525613961fed9db6a4d10dbe25521201b24f08e011df3a20ac895316957d \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index ebd304ecb6..8f0777e69d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1495,7 +1495,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ type2 = numericType(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; - if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (type1 & type2 & MEM_Int)!=0 ){ iA = pIn1->u.i; iB = pIn2->u.i; @@ -1519,6 +1518,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ } pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); + }else if( (flags & MEM_Null)!=0 ){ + goto arithmetic_result_is_null; }else{ bIntint = 0; fp_math: From bda00fbdb780e0b9da88493fccd04f7205453242 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Apr 2017 05:49:23 +0000 Subject: [PATCH 12/15] Refactor the fts3ColumnMethod() function so that all branches can be covered. FossilOrigin-Name: e47fdb493bd76d85f6f05771ee7a0b3ee31b1eb05839a60d2bdb47149ac692d8 --- ext/fts3/fts3.c | 53 +++++++++++++++++++++++++++---------------------- manifest | 15 +++++++------- manifest.uuid | 2 +- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 9cafd8e591..4f611d6f55 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3340,33 +3340,38 @@ static int fts3ColumnMethod( /* The column value supplied by SQLite must be in range. */ assert( iCol>=0 && iCol<=p->nColumn+2 ); - if( iCol==p->nColumn+1 ){ - /* This call is a request for the "docid" column. Since "docid" is an - ** alias for "rowid", use the xRowid() method to obtain the value. - */ - sqlite3_result_int64(pCtx, pCsr->iPrevId); - }else if( iCol==p->nColumn ){ - /* The extra column whose name is the same as the table. - ** Return a blob which is a pointer to the cursor. */ - sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); - }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ - sqlite3_result_int64(pCtx, pCsr->iLangid); - }else{ - /* The requested column is either a user column (one that contains - ** indexed data), or the language-id column. */ - rc = fts3CursorSeek(0, pCsr); + switch( iCol-p->nColumn ){ + case 0: + /* The special 'table-name' column */ + sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT); + sqlite3_result_subtype(pCtx, SQLITE_BLOB); + break; - if( rc==SQLITE_OK ){ - if( iCol==p->nColumn+2 ){ - int iLangid = 0; - if( p->zLanguageid ){ - iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1); - } - sqlite3_result_int(pCtx, iLangid); - }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ + case 1: + /* The docid column */ + sqlite3_result_int64(pCtx, pCsr->iPrevId); + break; + + case 2: + if( pCsr->pExpr ){ + sqlite3_result_int64(pCtx, pCsr->iLangid); + break; + }else if( p->zLanguageid==0 ){ + sqlite3_result_int(pCtx, 0); + break; + }else{ + iCol = p->nColumn; + /* fall-through */ + } + + default: + /* A user column. Or, if this is a full-table scan, possibly the + ** language-id column. Seek the cursor. */ + rc = fts3CursorSeek(0, pCsr); + if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){ sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); } - } + break; } assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); diff --git a/manifest b/manifest index e5b734be03..a1cf5d40b5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Defer\schecking\sfor\snull\sin\sthe\scomparison\soperators,\ssince\sthat\sis\san\nuncommon\scase. -D 2017-04-17T23:23:17.393 +C Refactor\sthe\sfts3ColumnMethod()\sfunction\sso\sthat\sall\sbranches\scan\sbe\scovered. +D 2017-04-18T05:49:23.863 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -70,7 +70,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 1db0b7086d187a0d10d2a5a7fd5c05336216d2f0dba4af76aca38e5d806bb0d0 +F ext/fts3/fts3.c 1f7f2b23b187177fb059d6e0ea4a2e55866babd5241a2774d13cf3d6d76e2168 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -1575,7 +1575,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e698db1956bb3aba32cd3ec633ec20f5d19b1a10bc68d3772903bca3c87ee158 -R d9474093122e32538bb559c220a1d671 -U drh -Z 5309f4dbe4f5abfd0a4417ec6708da32 +P 5684525613961fed9db6a4d10dbe25521201b24f08e011df3a20ac895316957d +Q +dd3217c38b507211d5102d00e3775e50e828762f6bcc97b1b087af11fd780f46 +R b7de56fa30910635d209a73e85c14a35 +U dan +Z cc71176235299a67f61f3d9016204954 diff --git a/manifest.uuid b/manifest.uuid index 23a0f3fc6d..f16a0ec833 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5684525613961fed9db6a4d10dbe25521201b24f08e011df3a20ac895316957d \ No newline at end of file +e47fdb493bd76d85f6f05771ee7a0b3ee31b1eb05839a60d2bdb47149ac692d8 \ No newline at end of file From 0027e98b857025facf3fdb09522146fde859a806 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Apr 2017 13:50:00 +0000 Subject: [PATCH 13/15] Use sqlite3_table_column_metadata() instead of a SELECT statement to check for the existence of a %_stat table in fts3. This leads to smaller and easier to test code. FossilOrigin-Name: dc2a48020a3c856a8b4cfa2309c290f0508b991e92cc0e4de680d19aae7872fc --- ext/fts3/fts3.c | 16 +++++----------- manifest | 16 ++++++++-------- manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 4f611d6f55..2027e34e42 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3451,17 +3451,11 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){ static int fts3SetHasStat(Fts3Table *p){ int rc = SQLITE_OK; if( p->bHasStat==2 ){ - const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'"; - char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName); - if( zSql ){ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); - rc = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat; - } - sqlite3_free(zSql); + char *zTbl = sqlite3_mprintf("%s_stat", p->zName); + if( zTbl ){ + int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0); + sqlite3_free(zTbl); + p->bHasStat = (res==SQLITE_OK); }else{ rc = SQLITE_NOMEM; } diff --git a/manifest b/manifest index 89c0690ce5..9e4a174eb1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\soptimizations\sof\sviews\sas\sthe\sright\soperand\sof\sa\sLEFT\sJOIN. -D 2017-04-18T11:20:19.836 +C Use\ssqlite3_table_column_metadata()\sinstead\sof\sa\sSELECT\sstatement\sto\scheck\sfor\nthe\sexistence\sof\sa\s%_stat\stable\sin\sfts3.\sThis\sleads\sto\ssmaller\sand\seasier\sto\ntest\scode. +D 2017-04-18T13:50:00.349 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -70,7 +70,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 1f7f2b23b187177fb059d6e0ea4a2e55866babd5241a2774d13cf3d6d76e2168 +F ext/fts3/fts3.c 43dbd764899650e6ee32336fdca2646e2157df7eaf5767693338e30bbfdb0220 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -1575,8 +1575,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e47fdb493bd76d85f6f05771ee7a0b3ee31b1eb05839a60d2bdb47149ac692d8 3a5860d86fadcf924316707918bf283d26c53b1473e5e67f5cff59d18c2a7742 -R 78f4667b0ada8932854ad0b3e309cd92 -T +closed 3a5860d86fadcf924316707918bf283d26c53b1473e5e67f5cff59d18c2a7742 -U drh -Z 119f88583d52d19e6e97c926524fc3c2 +P 41c27bc0ff1d3135cdb6273ede4595f5bb0c0e1e1d470ea1633cb525674cf431 +Q +86e7aa7bf18345d7b441e5531fedb9d6cd1d73a886058c08b8ef4d9bcdce59d5 +R 4fb545dcbfffcc885ec5f2ba82a6abb0 +U dan +Z 7fd413bdcf275f7c0ed7ce06ea528b64 diff --git a/manifest.uuid b/manifest.uuid index 560bf633fe..875b1cfcb0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -41c27bc0ff1d3135cdb6273ede4595f5bb0c0e1e1d470ea1633cb525674cf431 \ No newline at end of file +dc2a48020a3c856a8b4cfa2309c290f0508b991e92cc0e4de680d19aae7872fc \ No newline at end of file From a059e99ca8068c26b27aa5b26db5ef6e1d91a472 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 19 Apr 2017 07:33:52 +0000 Subject: [PATCH 14/15] Further modifications and test cases to improve test coverage of fts3. FossilOrigin-Name: ea8a0d2ce0cb1ca3f4f18c72fb780d1c26792799acc87e6726f9eaccf2f178bf --- ext/fts3/fts3.c | 13 ++++++----- manifest | 18 +++++++-------- manifest.uuid | 2 +- test/fts3fault2.test | 54 ++++++++++++++++++++++++++++++++++++++++++++ test/fts3misc.test | 52 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 16 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 2027e34e42..ec5f110920 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3960,7 +3960,7 @@ int sqlite3Fts3Init(sqlite3 *db){ #endif /* Create the virtual table wrapper around the hash-table and overload - ** the two scalar functions. If this is successful, register the + ** the four scalar functions. If this is successful, register the ** module with sqlite. */ if( SQLITE_OK==rc @@ -4543,7 +4543,7 @@ static int fts3EvalIncrPhraseNext( ** one incremental token. In which case the bIncr flag is set. */ assert( p->bIncr==1 ); - if( p->nToken==1 && p->bIncr ){ + if( p->nToken==1 ){ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, &pDL->iDocid, &pDL->pList, &pDL->nList ); @@ -4776,6 +4776,7 @@ static void fts3EvalTokenCosts( ** the number of overflow pages consumed by a record B bytes in size. */ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ + int rc = SQLITE_OK; if( pCsr->nRowAvg==0 ){ /* The average document size, which is required to calculate the cost ** of each doclist, has not yet been determined. Read the required @@ -4815,11 +4816,10 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz); assert( pCsr->nRowAvg>0 ); rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ) return rc; } *pnPage = pCsr->nRowAvg; - return SQLITE_OK; + return rc; } /* @@ -5169,7 +5169,8 @@ static void fts3EvalNextRow( pExpr->iDocid = pLeft->iDocid; pExpr->bEof = (pLeft->bEof || pRight->bEof); if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ - if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){ + assert( pRight->eType==FTSQUERY_PHRASE ); + if( pRight->pPhrase->doclist.aAll ){ Fts3Doclist *pDl = &pRight->pPhrase->doclist; while( *pRc==SQLITE_OK && pRight->bEof==0 ){ memset(pDl->pList, 0, pDl->nList); @@ -5198,7 +5199,7 @@ static void fts3EvalNextRow( if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ fts3EvalNextRow(pCsr, pLeft, pRc); - }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){ + }else if( pLeft->bEof || iCmp>0 ){ fts3EvalNextRow(pCsr, pRight, pRc); }else{ fts3EvalNextRow(pCsr, pLeft, pRc); diff --git a/manifest b/manifest index 9e4a174eb1..a3f279f409 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\ssqlite3_table_column_metadata()\sinstead\sof\sa\sSELECT\sstatement\sto\scheck\sfor\nthe\sexistence\sof\sa\s%_stat\stable\sin\sfts3.\sThis\sleads\sto\ssmaller\sand\seasier\sto\ntest\scode. -D 2017-04-18T13:50:00.349 +C Further\smodifications\sand\stest\scases\sto\simprove\stest\scoverage\sof\sfts3. +D 2017-04-19T07:33:52.121 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -70,7 +70,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 43dbd764899650e6ee32336fdca2646e2157df7eaf5767693338e30bbfdb0220 +F ext/fts3/fts3.c aba99577b605d8d9df62daa4463f0f89dcbd2805ae2d7d361104f522648d74be F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -791,12 +791,12 @@ F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8 F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3 F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 F test/fts3fault.test 268e9589f44f49d6694ef39a293f0e0f80c6230fb01cc6f34325412acceb99ae -F test/fts3fault2.test 0e38e9ccd5b13a9b9ac9b66dff24534f998279a0dd21a991115b0dafaaa88b46 +F test/fts3fault2.test 536bbe01fe2946ec24b063a5eee813e8fd90354a6ca0b8f941d299c405edd17e F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a -F test/fts3misc.test 744c53bde5969f4c22e9fb4c11cd3a2fc6c2edfb4c254919fd425663b1781137 +F test/fts3misc.test 8a4996e62af47165822770ab6ce1550fa2eb46ac58122a7bc4667775b95cfc84 F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 @@ -1575,8 +1575,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 41c27bc0ff1d3135cdb6273ede4595f5bb0c0e1e1d470ea1633cb525674cf431 -Q +86e7aa7bf18345d7b441e5531fedb9d6cd1d73a886058c08b8ef4d9bcdce59d5 -R 4fb545dcbfffcc885ec5f2ba82a6abb0 +P dc2a48020a3c856a8b4cfa2309c290f0508b991e92cc0e4de680d19aae7872fc +Q +36bfef8778c9f493c711d317e6831b048a992a5181ac8ca93bc85ebcd27da3c5 +R 02520d892c38a2ba5d5b628278b7ff8f U dan -Z 7fd413bdcf275f7c0ed7ce06ea528b64 +Z a14baf958f8e5420b98f8d2e39f6512b diff --git a/manifest.uuid b/manifest.uuid index 875b1cfcb0..e1a9acd6bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc2a48020a3c856a8b4cfa2309c290f0508b991e92cc0e4de680d19aae7872fc \ No newline at end of file +ea8a0d2ce0cb1ca3f4f18c72fb780d1c26792799acc87e6726f9eaccf2f178bf \ No newline at end of file diff --git a/test/fts3fault2.test b/test/fts3fault2.test index 3094568a3f..e4f292042c 100644 --- a/test/fts3fault2.test +++ b/test/fts3fault2.test @@ -190,6 +190,60 @@ do_faultsim_test 7.1 -faults oom* -body { faultsim_test_result {0 {1 2}} } +#------------------------------------------------------------------------- +# Inject faults into a opening an existing fts3 table that has been +# upgraded to add an %_stat table. +# +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE t8 USING fts3; + INSERT INTO t8 VALUES('the quick brown fox'); + INSERT INTO t8 VALUES('jumped over the'); + INSERT INTO t8 VALUES('lazy dog'); + INSERT INTO t8(t8) VALUES('automerge=8'); + SELECT name FROM sqlite_master WHERE name LIKE 't8%'; +} { + t8 t8_content t8_segments t8_segdir t8_stat +} +faultsim_save_and_close + +do_faultsim_test 8.1 -faults oom* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO t8 VALUES('one two three') } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 8.2 -faults oom* -prep { + faultsim_restore_and_reopen +} -body { + execsql { ALTER TABLE t8 RENAME TO t8ii } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +reset_db +set chunkconfig [fts3_configure_incr_load 1 1] +do_execsql_test 9.0 { + PRAGMA page_size = 512; + CREATE VIRTUAL TABLE t9 USING fts3; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50 + ) + INSERT INTO t9 SELECT 'one two three' FROM s; +} + +do_faultsim_test 8.2 -faults io* -body { + execsql { SELECT count(*) FROM t9 WHERE t9 MATCH '"one two three"' } +} -test { + faultsim_test_result {0 50} +} + +eval fts3_configure_incr_load $chunkconfig + + finish_test diff --git a/test/fts3misc.test b/test/fts3misc.test index 15da2fb419..69eb4e36fc 100644 --- a/test/fts3misc.test +++ b/test/fts3misc.test @@ -102,6 +102,7 @@ do_execsql_test 2.5 { 181 182 183 184 185 186 187 188 189 190 191 198 199 } +#------------------------------------------------------------------------- # Range constraints on the docid using non-integer values. # do_execsql_test 2.6 { @@ -120,5 +121,56 @@ do_execsql_test 2.8 { 29 30 31 34 35 38 39 42 43 46 47 48 } +#------------------------------------------------------------------------- +# Phrase query tests. +# +do_execsql_test 3.1.1 { + CREATE VIRTUAL TABLE t3 USING fts3; + INSERT INTO t3 VALUES('a b c'); + INSERT INTO t3 VALUES('d e f'); + INSERT INTO t3 VALUES('a b d'); + INSERT INTO t3 VALUES('1 2 3 4 5 6 7 8 9 10 11'); +} +do_execsql_test 3.1.2 { + SELECT * FROM t3 WHERE t3 MATCH '"a b x y"' ORDER BY docid DESC +} +do_execsql_test 3.1.3 { + SELECT * FROM t3 WHERE t3 MATCH '"a b c" OR "a b x y"' ORDER BY docid DESC +} {{a b c}} +do_execsql_test 3.1.4 { + SELECT * FROM t3 WHERE t3 MATCH '"a* b* x* a*"' +} +do_execsql_test 3.1.5 { + SELECT rowid FROM t3 WHERE t3 MATCH '"2 3 4 5 6 7 8 9"' +} {4} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + PRAGMA page_size = 512; + CREATE VIRTUAL TABLE t4 USING fts4; + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<8000 ) + INSERT INTO t4 SELECT 'a b c a b c a b c' FROM s; +} +do_execsql_test 4.1 { + SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' +} {8000} +do_execsql_test 4.2 { + SELECT quote(value) from t4_stat where id=0 +} {X'C03EC0B204C0A608'} +do_execsql_test 4.3 { + UPDATE t4_stat SET value = X'C03EC0B204C0A60800' WHERE id=0; +} +do_catchsql_test 4.4 { + SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' +} {1 {database disk image is malformed}} +do_execsql_test 4.5 { + UPDATE t4_stat SET value = X'00C03EC0B204C0A608' WHERE id=0; +} +do_catchsql_test 4.6 { + SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' +} {1 {database disk image is malformed}} + finish_test From dc62daca866006c4afa4c32c405d1a327dc7334f Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 19 Apr 2017 13:25:45 +0000 Subject: [PATCH 15/15] Further improvements to coverage of fts3 module. FossilOrigin-Name: 6b21d0fdebdccfaf63590d9ca9a279c22b8baec07c1a669b9f617f25bd857384 --- ext/fts3/fts3.c | 66 +++++++++++++++++++++------------------------- manifest | 16 +++++------ manifest.uuid | 2 +- test/fts3misc.test | 52 ++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 45 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index ec5f110920..26b0b00bcd 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3562,18 +3562,16 @@ static int fts3FunctionArg( sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ - Fts3Cursor *pRet; - if( sqlite3_value_type(pVal)!=SQLITE_BLOB - || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) - ){ + int rc = SQLITE_OK; + if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){ + *ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal); + }else{ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); sqlite3_free(zErr); - return SQLITE_ERROR; + rc = SQLITE_ERROR; } - memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *)); - *ppCsr = pRet; - return SQLITE_OK; + return rc; } /* @@ -5291,7 +5289,6 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ */ if( *pRc==SQLITE_OK && pExpr->eType==FTSQUERY_NEAR - && pExpr->bEof==0 && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) ){ Fts3Expr *p; @@ -5300,42 +5297,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ + assert( p->pRight->pPhrase->doclist.nList>0 ); nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; - if( nTmp==0 ){ + aTmp = sqlite3_malloc(nTmp*2); + if( !aTmp ){ + *pRc = SQLITE_NOMEM; res = 0; }else{ - aTmp = sqlite3_malloc(nTmp*2); - if( !aTmp ){ - *pRc = SQLITE_NOMEM; - res = 0; - }else{ - char *aPoslist = p->pPhrase->doclist.pList; - int nToken = p->pPhrase->nToken; + char *aPoslist = p->pPhrase->doclist.pList; + int nToken = p->pPhrase->nToken; - for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ - Fts3Phrase *pPhrase = p->pRight->pPhrase; - int nNear = p->nNear; - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - - aPoslist = pExpr->pRight->pPhrase->doclist.pList; - nToken = pExpr->pRight->pPhrase->nToken; - for(p=pExpr->pLeft; p && res; p=p->pLeft){ - int nNear; - Fts3Phrase *pPhrase; - assert( p->pParent && p->pParent->pLeft==p ); - nNear = p->pParent->nNear; - pPhrase = ( - p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase - ); - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } + for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ + Fts3Phrase *pPhrase = p->pRight->pPhrase; + int nNear = p->nNear; + res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); } - sqlite3_free(aTmp); + aPoslist = pExpr->pRight->pPhrase->doclist.pList; + nToken = pExpr->pRight->pPhrase->nToken; + for(p=pExpr->pLeft; p && res; p=p->pLeft){ + int nNear; + Fts3Phrase *pPhrase; + assert( p->pParent && p->pParent->pLeft==p ); + nNear = p->pParent->nNear; + pPhrase = ( + p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase + ); + res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); + } } + + sqlite3_free(aTmp); } return res; diff --git a/manifest b/manifest index a3f279f409..4ba5cabb77 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\smodifications\sand\stest\scases\sto\simprove\stest\scoverage\sof\sfts3. -D 2017-04-19T07:33:52.121 +C Further\simprovements\sto\scoverage\sof\sfts3\smodule. +D 2017-04-19T13:25:45.345 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -70,7 +70,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 aba99577b605d8d9df62daa4463f0f89dcbd2805ae2d7d361104f522648d74be +F ext/fts3/fts3.c 10fc22119e3d91997eb5820d96ff709ca7c61b6f767e09b360b986b897ad74c6 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -796,7 +796,7 @@ F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a -F test/fts3misc.test 8a4996e62af47165822770ab6ce1550fa2eb46ac58122a7bc4667775b95cfc84 +F test/fts3misc.test f481128013b9555babdf3bc04c58ab59d59bebc24b5f780f50342b9ffe05b547 F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 @@ -1575,8 +1575,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dc2a48020a3c856a8b4cfa2309c290f0508b991e92cc0e4de680d19aae7872fc -Q +36bfef8778c9f493c711d317e6831b048a992a5181ac8ca93bc85ebcd27da3c5 -R 02520d892c38a2ba5d5b628278b7ff8f +P ea8a0d2ce0cb1ca3f4f18c72fb780d1c26792799acc87e6726f9eaccf2f178bf +Q +6417c1bbeceaea88ec1972149a1afc74fc40a677c1447160e53dbf4ba0930c42 +R 14e4aea31c2fb4851be140b478cd2183 U dan -Z a14baf958f8e5420b98f8d2e39f6512b +Z e5cfee329765f9813d3e00bb36cba8b5 diff --git a/manifest.uuid b/manifest.uuid index e1a9acd6bf..2d3577ec63 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea8a0d2ce0cb1ca3f4f18c72fb780d1c26792799acc87e6726f9eaccf2f178bf \ No newline at end of file +6b21d0fdebdccfaf63590d9ca9a279c22b8baec07c1a669b9f617f25bd857384 \ No newline at end of file diff --git a/test/fts3misc.test b/test/fts3misc.test index 69eb4e36fc..0d003bd324 100644 --- a/test/fts3misc.test +++ b/test/fts3misc.test @@ -172,5 +172,57 @@ do_catchsql_test 4.6 { SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"' } {1 {database disk image is malformed}} +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t5 USING fts4; + INSERT INTO t5 VALUES('a x x x x b x x x x c'); + INSERT INTO t5 VALUES('a x x x x b x x x x c'); + INSERT INTO t5 VALUES('a x x x x b x x x x c'); +} +do_execsql_test 5.1 { + SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/4 c' +} {1 2 3} +do_execsql_test 5.2 { + SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/3 b NEAR/4 c' +} {} +do_execsql_test 5.3 { + SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/3 c' +} {} +do_execsql_test 5.4 { + SELECT rowid FROM t5 WHERE t5 MATCH 'y NEAR/4 b NEAR/4 c' +} {} +do_execsql_test 5.5 { + SELECT rowid FROM t5 WHERE t5 MATCH 'x OR a NEAR/3 b NEAR/3 c' +} {1 2 3} +do_execsql_test 5.5 { + SELECT rowid FROM t5 WHERE t5 MATCH 'x OR y NEAR/3 b NEAR/3 c' +} {1 2 3} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE t6 USING fts4; + + BEGIN; + WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000) + INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s; + + INSERT INTO t6 VALUES('x x x x x x x x x x x A'); + INSERT INTO t6 VALUES('x x x x x x x x x x x B'); + INSERT INTO t6 VALUES('x x x x x x x x x x x A'); + INSERT INTO t6 VALUES('x x x x x x x x x x x B'); + + WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000) + INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s; + COMMIT; +} +breakpoint +do_execsql_test 6.1 { + SELECT rowid FROM t6 WHERE t6 MATCH 'b OR "x a"' +} {50001 50002 50003 50004} + finish_test