]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the query optimizer so that it correctly handles constant expressions
authordrh <drh@noemail.net>
Fri, 8 Jun 2007 00:20:47 +0000 (00:20 +0000)
committerdrh <drh@noemail.net>
Fri, 8 Jun 2007 00:20:47 +0000 (00:20 +0000)
in the ON clause of a LEFT JOIN.  Ticket #2403. (CVS 4049)

FossilOrigin-Name: 46fdd195483787eef209a9b8ad108eba147be6fa

manifest
manifest.uuid
src/expr.c
src/sqliteInt.h
src/where.c
test/join5.test

index e5646c2e90a8218575df8049716cd294502a0f1d..d95a5d1dda57edcdbba03defcbe1ebae6dc30872 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\ssure\szeroblob\sdoes\sreasonable\sthings\swith\sa\snegative\sargument\sor\nan\sargument\sthat\sis\slarger\sthan\sthe\smaximum\sblob\ssize.\s(CVS\s4048)
-D 2007-06-07T19:08:33
+C Fix\sthe\squery\soptimizer\sso\sthat\sit\scorrectly\shandles\sconstant\sexpressions\nin\sthe\sON\sclause\sof\sa\sLEFT\sJOIN.\s\sTicket\s#2403.\s(CVS\s4049)
+D 2007-06-08T00:20:48
 F Makefile.in a42354804b50c2708ce72cf79e4daa30f50191b5
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -71,7 +71,7 @@ F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
 F src/date.c 6049db7d5a8fdf2c677ff7d58fa31d4f6593c988
 F src/delete.c 5c0d89b3ef7d48fe1f5124bfe8341f982747fe29
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c fb386ee80026e221869f49159c0963e851c184c9
+F src/expr.c 97819d6a4f2863dd5b04ad1ccd41a1d6bf043a01
 F src/func.c 4668843e6f0d27653939e12fc32276fb8e38d21a
 F src/hash.c 67b23e14f0257b69a3e8aa663e4eeadc1a2b6fd5
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
@@ -105,7 +105,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c d07ae326b3815d80f71c69b3c7584382e47f6447
 F src/sqlite.h.in b174b5508467deec4034c6c8a21f0354b498b46b
 F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
-F src/sqliteInt.h 853d50bfeb72586faada449061a8dcd61f8db42d
+F src/sqliteInt.h 0352ac447c1605e85c9d1d5caaf9641f5839ef93
 F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
 F src/tclsqlite.c f425c7583665ef78dd8397b2de0b8e0028e80ce2
 F src/test1.c 0ec120a4652ee95268a5a45e1e1adee13be9ae28
@@ -142,7 +142,7 @@ F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
 F src/vdbemem.c d86c25bbfe8102499ff7505fca44a779c68694d8
 F src/vtab.c c5ebebf615b2f29499fbe97a584c4bb342632aa0
-F src/where.c 0662fcd87987a8e131dcf8963e4a3ad696c085f3
+F src/where.c 6a3c44fed90af904ec3baac0b0e41592e9acacbb
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test f0ea4b968d5fe05d85e9cab6fa491ec7e3b9fcc4
@@ -278,7 +278,7 @@ F test/join.test af0443185378b64878750aa1cf4b83c216f246b4
 F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 2646825693a6e066ea89b498176d4a68df45ab68
+F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
 F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
 F test/laststmtchanges.test 18ead86c8a87ade949a1d5658f6dc4bb111d1b02
@@ -500,7 +500,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P e66aa2c34a5c767554c022d01386a95558083e84
-R a5d8e1e0d04beefa5c17cf48926f9278
+P f40218434e549144ddb48303df30e5191d44d3fc
+R 6c0f437e174a3996f6b009b6d1c9018d
 U drh
-Z a838a68aee7be6bf9246efacd8855808
+Z 16d5acbd30bcbeb8aed6b967cb91d898
index 8121398fafbddbf66a58de3a3fe67c0401c0e886..7be3561f22e2d6d7460d8a49bfb196202fc7d99d 100644 (file)
@@ -1 +1 @@
-f40218434e549144ddb48303df30e5191d44d3fc
\ No newline at end of file
+46fdd195483787eef209a9b8ad108eba147be6fa
\ No newline at end of file
index a6c53ee2133eee65ef1944a087f3647deec6acd4..5c48c0b5efb854c88f61a1dbc242fcd4f7467dc1 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.296 2007/05/30 10:36:47 danielk1977 Exp $
+** $Id: expr.c,v 1.297 2007/06/08 00:20:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -831,11 +831,21 @@ static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
 ** is constant.  See sqlite3ExprIsConstant() for additional information.
 */
 static int exprNodeIsConstant(void *pArg, Expr *pExpr){
+  int *pN = (int*)pArg;
+
+  /* If *pArg is 3 then any term of the expression that comes from
+  ** the ON or USING clauses of a join disqualifies the expression
+  ** from being considered constant. */
+  if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+    *pN = 0;
+    return 2;
+  }
+
   switch( pExpr->op ){
     /* Consider functions to be constant if all their arguments are constant
     ** and *pArg==2 */
     case TK_FUNCTION:
-      if( *((int*)pArg)==2 ) return 0;
+      if( (*pN)==2 ) return 0;
       /* Fall through */
     case TK_ID:
     case TK_COLUMN:
@@ -846,11 +856,11 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
     case TK_SELECT:
     case TK_EXISTS:
 #endif
-      *((int*)pArg) = 0;
+      *pN = 0;
       return 2;
     case TK_IN:
       if( pExpr->pSelect ){
-        *((int*)pArg) = 0;
+        *pN = 0;
         return 2;
       }
     default:
@@ -872,6 +882,18 @@ int sqlite3ExprIsConstant(Expr *p){
   return isConst;
 }
 
+/*
+** Walk an expression tree.  Return 1 if the expression is constant
+** that does no originate from the ON or USING clauses of a join.
+** Return 0 if it involves variables or function calls or terms from
+** an ON or USING clause.
+*/
+int sqlite3ExprIsConstantNotJoin(Expr *p){
+  int isConst = 3;
+  walkExprTree(p, exprNodeIsConstant, &isConst);
+  return isConst!=0;
+}
+
 /*
 ** Walk an expression tree.  Return 1 if the expression is constant
 ** or a function call with constant arguments.  Return and 0 if there
index 4de394aec469168613ac27d3239763399576474b..a6251b38b7be80a27240d56562f0389cfeea3d92 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.570 2007/05/29 12:11:30 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.571 2007/06/08 00:20:48 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1742,6 +1742,7 @@ void sqlite3BeginTransaction(Parse*, int);
 void sqlite3CommitTransaction(Parse*);
 void sqlite3RollbackTransaction(Parse*);
 int sqlite3ExprIsConstant(Expr*);
+int sqlite3ExprIsConstantNotJoin(Expr*);
 int sqlite3ExprIsConstantOrFunction(Expr*);
 int sqlite3ExprIsInteger(Expr*, int*);
 int sqlite3IsRowid(const char*);
index 306e37506a05b931c83e11af1a5479d978f183be..764a4a629ce101f36337dc7ba0424ae690ce71f0 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.250 2007/06/02 07:54:38 danielk1977 Exp $
+** $Id: where.c,v 1.251 2007/06/08 00:20:48 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1987,7 +1987,7 @@ WhereInfo *sqlite3WhereBegin(
   /* Special case: a WHERE clause that is constant.  Evaluate the
   ** expression and either jump over all of the code or fall thru.
   */
-  if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstant(pWhere)) ){
+  if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
     sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
     pWhere = 0;
   }
index 7d7b62e2cf29be2f5616e1b283e578c3933faa91..45d8a31596acaab568295adb19db845d661b98ae 100644 (file)
@@ -13,7 +13,7 @@
 # This file implements tests for left outer joins containing ON
 # clauses that restrict the scope of the left term of the join.
 #
-# $Id: join5.test,v 1.1 2005/09/19 21:05:50 drh Exp $
+# $Id: join5.test,v 1.2 2007/06/08 00:20:48 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -58,5 +58,53 @@ do_test join5-1.5 {
   }
 } {2 11 2 {} {} 11 t3-11}
 
+# Ticket #2403
+#
+do_test join5-2.1 {
+  execsql {
+    CREATE TABLE ab(a,b);
+    INSERT INTO "ab" VALUES(1,2);
+    INSERT INTO "ab" VALUES(3,NULL);
+
+    CREATE TABLE xy(x,y);
+    INSERT INTO "xy" VALUES(2,3);
+    INSERT INTO "xy" VALUES(NULL,1);
+  }
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 0}
+} {2 3 {} {} {} 1 {} {}}
+do_test join5-2.2 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 1}
+} {2 3 1 2 2 3 3 {} {} 1 1 2 {} 1 3 {}}
+do_test join5-2.3 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON NULL}
+} {2 3 {} {} {} 1 {} {}}
+do_test join5-2.4 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 0 WHERE 0}
+} {}
+do_test join5-2.5 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 1 WHERE 0}
+} {}
+do_test join5-2.6 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON NULL WHERE 0}
+} {}
+do_test join5-2.7 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 0 WHERE 1}
+} {2 3 {} {} {} 1 {} {}}
+do_test join5-2.8 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 1 WHERE 1}
+} {2 3 1 2 2 3 3 {} {} 1 1 2 {} 1 3 {}}
+do_test join5-2.9 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON NULL WHERE 1}
+} {2 3 {} {} {} 1 {} {}}
+do_test join5-2.10 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 0 WHERE NULL}
+} {}
+do_test join5-2.11 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON 1 WHERE NULL}
+} {}
+do_test join5-2.12 {
+  execsql {SELECT * FROM xy LEFT JOIN ab ON NULL WHERE NULL}
+} {}
+
 
 finish_test