From: drh Date: Mon, 19 Sep 2005 21:05:48 +0000 (+0000) Subject: ON-clause terms in a LEFT JOIN that restrict only the left table, should not X-Git-Tag: version-3.6.10~3435 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=22d6a53a779c7aeb632ae85e80a0316a62dc503b;p=thirdparty%2Fsqlite.git ON-clause terms in a LEFT JOIN that restrict only the left table, should not really restrict the left table but instead rows that fail to meet the condition to be joined with NULL rows from the right table. (CVS 2725) FossilOrigin-Name: ea10f9785e3c5248dafcc297f3a2c5465b6e0dba --- 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 (