diff --git a/manifest b/manifest index 0e25caa4c8..e85c2407bc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Set\sthe\sdefault\smaximum\spage\ssize\sto\s32768,\snot\s8192.\s(CVS\s2724) -D 2005-09-19T19:05:21 +C ON-clause\sterms\sin\sa\sLEFT\sJOIN\sthat\srestrict\sonly\sthe\sleft\stable,\sshould\snot\nreally\srestrict\sthe\sleft\stable\sbut\sinstead\srows\sthat\sfail\sto\smeet\sthe\scondition\nto\sbe\sjoined\swith\sNULL\srows\sfrom\sthe\sright\stable.\s(CVS\s2725) +D 2005-09-19T21:05:49 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -63,10 +63,10 @@ F src/pragma.c 6d773e25e8af13ef0820531ad2793417f8a8959d F src/prepare.c fc098db25d2a121affb08686cf04833fd50452d4 F src/printf.c bd421c1ad5e01013c89af63c60eab02852ccd15e F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4 -F src/select.c 459fb935f1b3f6f0011c548a7664b4d7d062a041 +F src/select.c c3fe1994da81df0e09c4604ef75180f249cabe10 F src/shell.c 3596c1e559b82663057940d19ba533ad421c7dd3 F src/sqlite.h.in 461b2535550cf77aedfd44385da11ef7d63e57a2 -F src/sqliteInt.h f59e1ceccfca73737016b8912ac5f23995dd40c6 +F src/sqliteInt.h 53daa72541b4336c5e89773cf39717ed695bd523 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c ac94682f9e601dd373912c46414a5a842db2089a F src/test1.c 0f1a66f65a54fba029f7e93b7500d49443dc959b @@ -87,7 +87,7 @@ F src/vdbeapi.c 85bbe1d0243a89655433d60711b4bd71979b59cd F src/vdbeaux.c 57a6ced8417bdc6f06c391d9c560ecbbed644ef3 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c fea0744936008831daa17cdc75056c3ca1469690 -F src/where.c 728051085e8c782370a00ab36b494a244b1e9f4e +F src/where.c 2b7b4dd112a027021d9c53e25d221761d572a925 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6 @@ -162,6 +162,7 @@ F test/join.test db3802739fb695bdfa2e88805e3d64ec5ffbebd1 F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 +F test/join5.test 2646825693a6e066ea89b498176d4a68df45ab68 F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 F test/lastinsert.test eaa89c6ee1f13062d87139fd32c1e56753d2fd89 F test/laststmtchanges.test 19a6d0c11f7a31dc45465b495f7b845a62cbec17 @@ -310,7 +311,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 6cc57fcf15cfa3ce73c78b1cac90f7806e5bae40 -R 263668ef8fd093a2fb233495f6df04ab +P b32e9ec2480f9da2c2ea705ed3c88ca77b77cf2a +R 30beedb46fba1ce2f76a3f1396f53cb5 U drh -Z dfe987a06f47431345e9f24e1070f391 +Z a986dad9151bb581e7854782adc6d5e8 diff --git a/manifest.uuid b/manifest.uuid index b6309cb933..a570b9b2ee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b32e9ec2480f9da2c2ea705ed3c88ca77b77cf2a \ No newline at end of file +ea10f9785e3c5248dafcc297f3a2c5465b6e0dba \ No newline at end of file diff --git a/src/select.c b/src/select.c index 369b782fe4..12379f53ca 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.271 2005/09/19 17:35:53 drh Exp $ +** $Id: select.c,v 1.272 2005/09/19 21:05:49 drh Exp $ */ #include "sqliteInt.h" @@ -179,6 +179,7 @@ static void addWhereTerm( const char *zAlias1, /* Alias for first table. May be NULL */ const Table *pTab2, /* Second table */ const char *zAlias2, /* Alias for second table. May be NULL */ + int iRightJoinTable, /* VDBE cursor for the right table */ Expr **ppExpr /* Add the equality term to this expression */ ){ Expr *pE1a, *pE1b, *pE1c; @@ -199,11 +200,14 @@ static void addWhereTerm( pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0); pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0); ExprSetProperty(pE, EP_FromJoin); + pE->iRightJoinTable = iRightJoinTable; *ppExpr = sqlite3ExprAnd(*ppExpr, pE); } /* ** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the +** expression. ** ** The EP_FromJoin property is used on terms of an expression to tell ** the LEFT OUTER JOIN processing logic that this term is part of the @@ -211,11 +215,26 @@ static void addWhereTerm( ** of the more general WHERE clause. These terms are moved over to the ** WHERE clause during join processing but we need to remember that they ** originated in the ON or USING clause. +** +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not +** explicitly mentioned in the expression. That information is needed +** for cases like this: +** +** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 +** +** The where clause needs to defer the handling of the t1.x=5 +** term until after the t2 loop of the join. In that way, a +** NULL t2 row will be inserted whenever t1.x!=5. If we do not +** defer the handling of t1.x=5, it will be processed immediately +** after the t1 loop and rows with t1.x!=5 will never appear in +** the output, which is incorrect. */ -static void setJoinExpr(Expr *p){ +static void setJoinExpr(Expr *p, int iTable){ while( p ){ ExprSetProperty(p, EP_FromJoin); - setJoinExpr(p->pLeft); + p->iRightJoinTable = iTable; + setJoinExpr(p->pLeft, iTable); p = p->pRight; } } @@ -262,7 +281,9 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ char *zName = pLeftTab->aCol[j].zName; if( columnIndex(pRightTab, zName)>=0 ){ addWhereTerm(zName, pLeftTab, pLeft->zAlias, - pRightTab, pRight->zAlias, &p->pWhere); + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); + } } } @@ -279,7 +300,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** an AND operator. */ if( pLeft->pOn ){ - setJoinExpr(pLeft->pOn); + setJoinExpr(pLeft->pOn, pRight->iCursor); p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn); pLeft->pOn = 0; } @@ -301,7 +322,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ return 1; } addWhereTerm(zName, pLeftTab, pLeft->zAlias, - pRightTab, pRight->zAlias, &p->pWhere); + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); } } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b987608b4e..beb198f087 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.420 2005/09/19 17:35:53 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.421 2005/09/19 21:05:49 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -903,6 +903,7 @@ struct Expr { ** iColumn-th field of the iTable-th table. */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ + int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ Select *pSelect; /* When the expression is a sub-select. Also the ** right side of " IN (