]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix problems caused by over-agressive optimization of ORDER BY in joins.
authordrh <drh@noemail.net>
Fri, 29 Jul 2005 19:43:58 +0000 (19:43 +0000)
committerdrh <drh@noemail.net>
Fri, 29 Jul 2005 19:43:58 +0000 (19:43 +0000)
Lots more testing needed. (CVS 2571)

FossilOrigin-Name: 1a4e526d46280970b43505a5c8a4090767c63043

manifest
manifest.uuid
src/where.c
test/where2.test

index de784c780b3f560a8f41d1322f927906e6ab2628..a8bba663bd9d78158b2596ca53c86d46fb1e9976 100644 (file)
--- 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
index fb2b2aa486dd92ecd68c7c80ff40fc4f61bafd44..723a5bf124aa20eb87782f3ddd8ccb041d03447f 100644 (file)
@@ -1 +1 @@
-cc7ae73ed01f0b89e31dd8de48b913bbd83887b8
\ No newline at end of file
+1a4e526d46280970b43505a5c8a4090767c63043
\ No newline at end of file
index b6b80c5390960d3b8e0a859475ba44e97e3c05dc..6d4db13f6fe928be0da25888a72600534ad25b04 100644 (file)
@@ -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; i<pTabList->nSrc; 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.
   */
index b4b4d952b58712b6c6904aff5ebf605de4e8581e..efeb03c49e9cf13b0161c501a9245b9c96c11f39 100644 (file)
@@ -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}
-}