]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a new ORDER BY optimization that bypasses ORDER BY terms that are
authordrh <drh@noemail.net>
Fri, 14 Jun 2013 02:51:48 +0000 (02:51 +0000)
committerdrh <drh@noemail.net>
Fri, 14 Jun 2013 02:51:48 +0000 (02:51 +0000)
constrained by == and IS NULL terms of the WHERE clause.

FossilOrigin-Name: b920bb70bb009b7c54e7667544c9810c5ee25e19

manifest
manifest.uuid
src/where.c
test/orderby5.test [new file with mode: 0644]

index a5722835d20c3a6d486c5dc4e4d07723603343ee..ed857f034afc3f6958b1a495a7ba2b9c49496d83 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C An\sindex\smight\sbe\suseful\sfor\sORDER\sBY\sif\sany\sindexed\scolumn\sis\sin\sthe\nORDER\sBY\sclause,\snot\sjust\sthe\sfirst\sindexed\scolumn.
-D 2013-06-13T17:58:08.642
+C Add\sa\snew\sORDER\sBY\soptimization\sthat\sbypasses\sORDER\sBY\sterms\sthat\sare\nconstrained\sby\s==\sand\sIS\sNULL\sterms\sof\sthe\sWHERE\sclause.
+D 2013-06-14T02:51:48.285
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
-F src/where.c ba5f6766cfc7fcee945d45120cbb6e39a881b8e0
+F src/where.c 7d406cca2f60afbbfb57470f0d4981798bccf6e8
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -695,6 +695,7 @@ F test/orderby1.test 9b524aff9147288da43a6d7ddfdcff47fa2303c6
 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
+F test/orderby5.test 02eca502a0f97c77ce383b0dfa17e99c6a107b8d
 F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
 F test/pager1.test 16b649c8f0b38d446acbcff8a7bf055a9be43276
 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -1095,7 +1096,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P e8b7ea8202c443bfc8a978588c7d2cfaa14a8fea
-R 20475a52b4ff0eaa6499f9e0ae4a1e9c
+P ade473b5ae3fe2162b0ec29731d8e864a9301e07
+R eae0305c76446978c9d6694aa033807b
 U drh
-Z f8930bf04903145489a941260cbef3e2
+Z 288ef6a3a068d55d460d1b487a44477a
index 1431942f12f75c3d1ba0d13284272e0d84a60a0a..ade080fb5234ab4d11e9b20dc61d71cd2148f443 100644 (file)
@@ -1 +1 @@
-ade473b5ae3fe2162b0ec29731d8e864a9301e07
\ No newline at end of file
+b920bb70bb009b7c54e7667544c9810c5ee25e19
\ No newline at end of file
index d702668aab4c51c1d64ba6ad651ff569157fbd72..2163ee7a56183d3adedaec5341d15b97fb8c656d 100644 (file)
@@ -4891,7 +4891,7 @@ static int wherePathSatisfiesOrderBy(
   Bitmask obSat = 0;    /* Mask of ORDER BY terms satisfied so far */
   Bitmask obDone;       /* Mask of all ORDER BY terms */
   Bitmask orderDistinctMask;  /* Mask of all well-ordered loops */
-  
+  Bitmask ready;              /* Mask of inner loops */
 
   /*
   ** We say the WhereLoop is "one-row" if it generates no more than one
@@ -4931,10 +4931,39 @@ static int wherePathSatisfiesOrderBy(
   isOrderDistinct = 1;
   obDone = MASKBIT(nOrderBy)-1;
   orderDistinctMask = 0;
+  ready = 0;
   for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
+    if( iLoop>0 ) ready |= pLoop->maskSelf;
     pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
     assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
     iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
+
+    /* Mark off any ORDER BY term X that is a column in the table of
+    ** the current loop for which there is term in the WHERE
+    ** clause of the form X IS NULL or X=? that reference only outer
+    ** loops.
+    */
+    for(i=0; i<nOrderBy; i++){
+      if( MASKBIT(i) & obSat ) continue;
+      pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+      if( pOBExpr->op!=TK_COLUMN ) continue;
+      if( pOBExpr->iTable!=iCur ) continue;
+      pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
+                       ~ready, WO_EQ|WO_ISNULL, 0);
+      if( pTerm==0 ) continue;
+      if( pOBExpr->iColumn>=0 ){
+        const char *z1, *z2;
+        pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        z1 = pColl->zName;
+        pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        z2 = pColl->zName;
+        if( sqlite3StrICmp(z1, z2)!=0 ) continue;
+      }
+      obSat |= MASKBIT(i);
+    }
+
     if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
       if( pLoop->wsFlags & WHERE_IPK ){
         pIndex = 0;
@@ -5066,7 +5095,7 @@ static int wherePathSatisfiesOrderBy(
         }
       }
     }
-  }
+  } /* End the loop over all WhereLoops from outer-most down to inner-most */
   if( obSat==obDone ) return 1;
   if( !isOrderDistinct ) return 0;
   if( isLastLoop ) return 1;
diff --git a/test/orderby5.test b/test/orderby5.test
new file mode 100644 (file)
index 0000000..5bae5db
--- /dev/null
@@ -0,0 +1,97 @@
+# 2013-06-14
+#
+# 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 regression tests for SQLite library.  The
+# focus of this file is testing that the optimizations that disable
+# ORDER BY clauses work correctly
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set ::testprefix orderby5
+
+# Generate test data for a join.  Verify that the join gets the
+# correct answer.
+#
+do_execsql_test 1.1 {
+  CREATE TABLE t1(a,b,c);
+  CREATE INDEX t1bc ON t1(b,c);
+
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT a, b, c FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.2.1 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT a, c, b FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.2.2 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT a, c, b FROM t1 WHERE a='xyz' COLLATE nocase;
+} {/B-TREE/}
+do_execsql_test 1.2.3 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT a COLLATE nocase, c, b FROM t1 WHERE a='xyz';
+} {/B-TREE/}
+do_execsql_test 1.2.4 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT a COLLATE nocase, c, b FROM t1 WHERE a='xyz' COLLATE nocase;
+} {~/B-TREE/}
+do_execsql_test 1.3 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT b, a, c FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.4 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT b, c, a FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.5 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT c, a, b FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.6 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT c, b, a FROM t1 WHERE a=0;
+} {~/B-TREE/}
+do_execsql_test 1.7 {
+  EXPLAIN QUERY PLAN
+  SELECT DISTINCT c, b, a FROM t1 WHERE +a=0;
+} {/B-TREE/}
+do_execsql_test 2.1 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY a, b, c;
+} {~/B-TREE/}
+do_execsql_test 2.2 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE +a=0 ORDER BY a, b, c;
+} {/B-TREE/}
+do_execsql_test 2.3 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY b, a, c;
+} {~/B-TREE/}
+do_execsql_test 2.4 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY b, c, a;
+} {~/B-TREE/}
+do_execsql_test 2.5 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY a, c, b;
+} {/B-TREE/}
+do_execsql_test 2.6 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY c, a, b;
+} {/B-TREE/}
+do_execsql_test 2.7 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM t1 WHERE a=0 ORDER BY c, b, a;
+} {/B-TREE/}
+
+
+finish_test