From: drh Date: Fri, 29 Jul 2005 19:43:58 +0000 (+0000) Subject: Fix problems caused by over-agressive optimization of ORDER BY in joins. X-Git-Tag: version-3.6.10~3588 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=943af3cda113716b176b1b367416ddd33b1e495a;p=thirdparty%2Fsqlite.git Fix problems caused by over-agressive optimization of ORDER BY in joins. Lots more testing needed. (CVS 2571) FossilOrigin-Name: 1a4e526d46280970b43505a5c8a4090767c63043 --- diff --git a/manifest b/manifest index de784c780b..a8bba663bd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sauthentication\sso\sthat\sit\sworks\swith\sAS\saliases.\s\sTicket\s#1338.\s(CVS\s2570) -D 2005-07-29T15:36:15 +C Fix\sproblems\scaused\sby\sover-agressive\soptimization\sof\sORDER\sBY\sin\sjoins.\nLots\smore\stesting\sneeded.\s(CVS\s2571) +D 2005-07-29T19:43:58 F Makefile.in 22ea9c0fe748f591712d8fe3c6d972c6c173a165 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -85,7 +85,7 @@ F src/vdbeapi.c 7f392f0792d1258c958083d7de9eae7c3530c9a6 F src/vdbeaux.c 3732a86566a6be4da4c606e9334baf3fd98667af F src/vdbefifo.c b8805850afe13b43f1de78d58088cb5d66f88e1e F src/vdbemem.c da8e8d6f29dd1323f782f000d7cd120027c9ff03 -F src/where.c c65782be9fff4fd95e4e652f815bbcfd36d5656f +F src/where.c 7f59d0ed3b0b647b24f4cdce4a0623d2303dbbd9 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6 @@ -226,7 +226,7 @@ F test/vacuum2.test 5d77e98c458bcdbeecc6327de5107179ba1aa095 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/view.test 3c79232a2ee45918c62a0cf90411525899404a76 F test/where.test b6ab0f64adc5fbb4259f284b19da6cd9aeadc711 -F test/where2.test 6e8c3369e315a609b207734f57a49e21ed838c04 +F test/where2.test 3432fc9c24af9120df65a9a4cc8dad3bb9285633 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/lemon.c c88936c67f6411608db8fa4254d254f509fa40f6 F tool/lempar.c f0c30abcae762a7d1eb37cd88b2232ab8dd625fb @@ -289,7 +289,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b -P d23c8bf81e508722e92ff1b9c8bc98dc026a31f2 -R 89fca4783590df7d7e0576ccf5089241 +P cc7ae73ed01f0b89e31dd8de48b913bbd83887b8 +R f7ec03dd4f33cee2f3fa1b70964a7b5e U drh -Z 77e1dbb5cac3156585c14519c38ecffb +Z d383af4bb27f70288e32f2b965c3944b diff --git a/manifest.uuid b/manifest.uuid index fb2b2aa486..723a5bf124 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cc7ae73ed01f0b89e31dd8de48b913bbd83887b8 \ No newline at end of file +1a4e526d46280970b43505a5c8a4090767c63043 \ No newline at end of file diff --git a/src/where.c b/src/where.c index b6b80c5390..6d4db13f6f 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.157 2005/07/29 15:10:18 drh Exp $ +** $Id: where.c,v 1.158 2005/07/29 19:43:58 drh Exp $ */ #include "sqliteInt.h" @@ -171,6 +171,7 @@ struct ExprMaskSet { #define WHERE_IDX_ONLY 0x0800 /* Use index only - omit table */ #define WHERE_ORDERBY 0x1000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x2000 /* Scan in reverse order */ +#define WHERE_UNIQUE 0x4000 /* Selects no more than one row */ /* ** Initialize a preallocated WhereClause structure. @@ -641,14 +642,6 @@ static int isSortingIndex( nTerm = pOrderBy->nExpr; assert( nTerm>0 ); - /* A UNIQUE index that is fully specified is always a sorting - ** index. - */ - if( pIdx->onError!=OE_None && nEqCol==pIdx->nColumn ){ - *pbRev = 0; - return 1; - } - /* Match terms of the ORDER BY clause against columns of ** the index. */ @@ -795,9 +788,8 @@ static double bestIndex( if( pTerm->operator & WO_EQ ){ /* Rowid== is always the best pick. Look no further. Because only ** a single row is generated, output is always in sorted order */ - *pFlags = WHERE_ROWID_EQ; + *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE; *pnEq = 1; - if( pOrderBy ) *pFlags |= WHERE_ORDERBY; TRACE(("... best is rowid\n")); return 0.0; }else if( (pExpr = pTerm->pExpr)->pList!=0 ){ @@ -886,6 +878,10 @@ static double bestIndex( } cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier); nEq = i; + if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0 + && nEq==pProbe->nColumn ){ + flags |= WHERE_UNIQUE; + } TRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost)); /* Look for range constraints @@ -1262,6 +1258,7 @@ WhereInfo *sqlite3WhereBegin( struct SrcList_item *pTabItem; /* A single entry from pTabList */ WhereLevel *pLevel; /* A single level in the pWInfo list */ int iFrom; /* First unused FROM clause element */ + int andFlags; /* AND-ed combination of all wc.a[].flags */ /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask @@ -1324,6 +1321,7 @@ WhereInfo *sqlite3WhereBegin( notReady = ~(Bitmask)0; pTabItem = pTabList->a; pLevel = pWInfo->a; + andFlags = ~0; for(i=iFrom=0, pLevel=pWInfo->a; inSrc; i++, pLevel++){ Index *pIdx; /* Index for FROM table at pTabItem */ int flags; /* Flags asssociated with pIdx */ @@ -1359,9 +1357,10 @@ WhereInfo *sqlite3WhereBegin( break; } } - if( bestFlags & WHERE_ORDERBY ){ + if( (bestFlags & WHERE_ORDERBY)!=0 ){ *ppOrderBy = 0; } + andFlags &= bestFlags; pLevel->flags = bestFlags; pLevel->pIdx = pBest; pLevel->nEq = bestNEq; @@ -1376,6 +1375,13 @@ WhereInfo *sqlite3WhereBegin( pLevel->iFrom = bestJ; } + /* If the total query only selects a single row, then the ORDER BY + ** clause is irrelevant. + */ + if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){ + *ppOrderBy = 0; + } + /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ diff --git a/test/where2.test b/test/where2.test index b4b4d952b5..efeb03c49e 100644 --- a/test/where2.test +++ b/test/where2.test @@ -12,7 +12,7 @@ # focus of this file is testing the use of indices in WHERE clauses # based on recent changes to the optimizer. # -# $Id: where2.test,v 1.3 2005/07/29 15:10:19 drh Exp $ +# $Id: where2.test,v 1.4 2005/07/29 19:43:59 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -223,7 +223,6 @@ do_test where2-6.4 { SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w } } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}} -if 0 { ##### FIX ME ##### do_test where2-6.5 { queryplan { SELECT b.* FROM t1 a, t1 b @@ -238,7 +237,6 @@ do_test where2-6.6 { ORDER BY +b.w } } {1 0 4 4 2 1 9 10 sort a i1w b i1zyx} -}