]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure ON clause terms of a LEFT JOIN are not used with an index on the
authordrh <drh@noemail.net>
Wed, 26 Mar 2008 14:56:34 +0000 (14:56 +0000)
committerdrh <drh@noemail.net>
Wed, 26 Mar 2008 14:56:34 +0000 (14:56 +0000)
right table of the join.  Ticket #3015. (CVS 4919)

FossilOrigin-Name: 3fafa562593b51d38f58e7a691c193d34a812a05

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

index 5df67c98ecfafd7d55e020d5cf9d7773d5316c5e..5af571e16025719534c4e2a61cffb5dfdb553a18 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Comment\schange\son\sthe\sprevious\scheck-in.\s\sNo\schanges\sto\scode.\s(CVS\s4918)
-D 2008-03-26T12:50:15
+C Make\ssure\sON\sclause\sterms\sof\sa\sLEFT\sJOIN\sare\snot\sused\swith\san\sindex\son\sthe\nright\stable\sof\sthe\sjoin.\s\sTicket\s#3015.\s(CVS\s4919)
+D 2008-03-26T14:56:35
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
 F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
 F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af
 F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
-F src/where.c f18bac2f87c965811727be1be05deeaf5229fcd0
+F src/where.c 7aeeec6731dc2f423e6a77ff2964bc3c38985625
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test d12210212bada2bde6d5aeb90969b86c1aa977d2
@@ -537,6 +537,7 @@ F test/where2.test 7012c0ad022a54430dd22c98288d3f4d6599dbcf
 F test/where3.test 0a30fe9808b0fa01c46d0fcf4fac0bf6cf75bb30
 F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
+F test/where6.test 81e93cc92f08379f4ade484956c0be622b72bda3
 F test/zeroblob.test 7d1854ea79d048e023e5f2e38106a7e99a17435c
 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
@@ -617,7 +618,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 50de87dc808820a70d3a99277f532e418a2f97e2
-R a9214388e1bd4f84433e05f4820411e2
+P 72ae456239eb9f75b744f6733c4441b380bd1be1
+R 9d9078dbdb76203a989a8fc288298d2a
 U drh
-Z 2631d714b3b1ed6116e6910f891b739c
+Z 23ccaa57eab8690967dced96f6c90551
index 86a7964cd397ed370db09ec2e3dd553bd6ebd94e..795685831a244969ed6fdcb9a112f6333f1bbbc1 100644 (file)
@@ -1 +1 @@
-72ae456239eb9f75b744f6733c4441b380bd1be1
\ No newline at end of file
+3fafa562593b51d38f58e7a691c193d34a812a05
\ No newline at end of file
index 71bc51bc4e66f7d930a914c00c1bb7ebc3548e53..49c76fe0c734cf0f52c0d068b450b6beb98f84df 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.291 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: where.c,v 1.292 2008/03/26 14:56:35 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -743,7 +743,10 @@ static void exprAnalyze(
   }
   prereqAll = exprTableUsage(pMaskSet, pExpr);
   if( ExprHasProperty(pExpr, EP_FromJoin) ){
-    prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable);
+    Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable);
+    prereqAll |= x;
+    pTerm->prereqRight |= x-1; /* ON clause terms may not be used with an index
+                               ** on left table of a LEFT JOIN.  Ticket #3015 */
   }
   pTerm->prereqAll = prereqAll;
   pTerm->leftCursor = -1;
@@ -2043,14 +2046,36 @@ WhereInfo *sqlite3WhereBegin(
     pWhere = 0;
   }
 
+  /* Assign a bit from the bitmask to every term in the FROM clause.
+  **
+  ** When assigning bitmask values to FROM clause cursors, it must be
+  ** the case that if X is the bitmask for the N-th FROM clause term then
+  ** the bitmask for all FROM clause terms to the left of the N-th term
+  ** is (X-1).   An expression from the ON clause of a LEFT JOIN can use
+  ** its Expr.iRightJoinTable value to find the bitmask of the right table
+  ** of the join.  Subtracting one from the right table bitmask gives a
+  ** bitmask for all tables to the left of the join.  Knowing the bitmask
+  ** for all tables to the left of a left join is important.  Ticket #3015.
+  */
+  for(i=0; i<pTabList->nSrc; i++){
+    createMask(&maskSet, pTabList->a[i].iCursor);
+  }
+#ifndef NDEBUG
+  {
+    Bitmask toTheLeft = 0;
+    for(i=0; i<pTabList->nSrc; i++){
+      Bitmask m = getMask(&maskSet, pTabList->a[i].iCursor);
+      assert( (m-1)==toTheLeft );
+      toTheLeft |= m;
+    }
+  }
+#endif
+
   /* Analyze all of the subexpressions.  Note that exprAnalyze() might
   ** add new virtual terms onto the end of the WHERE clause.  We do not
   ** want to analyze these virtual terms, so start analyzing at the end
   ** and work forward so that the added virtual terms are never processed.
   */
-  for(i=0; i<pTabList->nSrc; i++){
-    createMask(&maskSet, pTabList->a[i].iCursor);
-  }
   exprAnalyzeAll(pTabList, &wc);
   if( db->mallocFailed ){
     goto whereBeginNoMem;
diff --git a/test/where6.test b/test/where6.test
new file mode 100644 (file)
index 0000000..2e803b1
--- /dev/null
@@ -0,0 +1,51 @@
+# 2007 June 8
+#
+# 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 terms in the ON clause of
+# a LEFT OUTER JOIN are not used with indices.  See ticket #3015.
+#
+# $Id: where6.test,v 1.1 2008/03/26 14:56:35 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+do_test where6-1.0 {
+  execsql {
+    CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c);
+    INSERT INTO t1 VALUES(1,3,1);
+    INSERT INTO t1 VALUES(2,4,2);
+    CREATE TABLE t2(x INTEGER PRIMARY KEY);
+    INSERT INTO t2 VALUES(3);
+
+    SELECT * FROM t1 LEFT JOIN t2 ON b=x AND c=1;
+  }
+} {1 3 1 3 2 4 2 {}}
+do_test where6-1.1 {
+  execsql {
+    SELECT * FROM t1 LEFT JOIN t2 ON b=x WHERE c=1;
+  }
+} {1 3 1 3}
+do_test where6-1.2 {
+  execsql {
+    CREATE INDEX i1 ON t1(c);
+
+    SELECT * FROM t1 LEFT JOIN t2 ON b=x AND c=1;
+  }
+} {1 3 1 3 2 4 2 {}}
+do_test where6-1.3 {
+  execsql {
+    SELECT * FROM t1 LEFT JOIN t2 ON b=x WHERE c=1;
+  }
+} {1 3 1 3}
+
+finish_test