-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
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
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
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
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
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
-f40218434e549144ddb48303df30e5191d44d3fc
\ No newline at end of file
+46fdd195483787eef209a9b8ad108eba147be6fa
\ No newline at end of file
** 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>
** 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:
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:
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
*************************************************************************
** 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_
void sqlite3CommitTransaction(Parse*);
void sqlite3RollbackTransaction(Parse*);
int sqlite3ExprIsConstant(Expr*);
+int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
** 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"
/* 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;
}
# 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
}
} {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