From 1cc093c2b5af24ccf32de4cf99917fc5e5f92bdb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 24 Jun 2002 22:01:57 +0000 Subject: [PATCH] Partial fix for a problem with LEFT OUTER JOIN. It used to be that the test for the right-hand table not matching the left table occurred after all ON, USING, WHERE clause processing. The test should occur after ON and USING clauses are checked but before the WHERE clause is check. This fix works as long as the total number of "AND" separated terms in the ON, USING, and WHERE clause does not exceed 32. To do: make this work for any number of terms and add test cases. that (CVS 639) FossilOrigin-Name: 8b6574cfa86daaae910f8f3ee3c4723a21fb9e53 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/select.c | 19 ++++++++++++++++++- src/sqliteInt.h | 5 +++-- src/where.c | 13 ++++++++++++- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index baee7203de..1c509bdb70 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sVDBE\sstack\sleak\sin\sLEFT\sOUTER\sJOIN.\s\sFix\sa\sbug\sin\sthe\scode\sgenerator\nfor\sJOIN\s...\sUSING(...).\s(CVS\s638) -D 2002-06-24T12:20:23 +C Partial\sfix\sfor\sa\sproblem\swith\sLEFT\sOUTER\sJOIN.\s\sIt\sused\sto\sbe\sthat\sthe\stest\nfor\sthe\sright-hand\stable\snot\smatching\sthe\sleft\stable\soccurred\safter\sall\nON,\sUSING,\sWHERE\sclause\sprocessing.\s\sThe\stest\sshould\soccur\safter\sON\sand\nUSING\sclauses\sare\schecked\sbut\sbefore\sthe\sWHERE\sclause\sis\scheck.\s\sThis\sfix\nworks\sas\slong\sas\sthe\stotal\snumber\sof\s"AND"\sseparated\sterms\sin\sthe\sON,\sUSING,\nand\sWHERE\sclause\sdoes\snot\sexceed\s32.\s\sTo\sdo:\smake\sthis\swork\sfor\sany\snumber\nof\sterms\sand\sadd\stest\scases.\nthat\s(CVS\s639) +D 2002-06-24T22:01:58 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -37,11 +37,11 @@ F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e F src/parse.y 2285d8967d7334d52a2188089e5a881d73ba56f6 F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c 3e83a18baeeb5c89936ca84bde0bb0d18709b6b5 +F src/select.c f7d74f20f5ecc335fbccba367eda727b9d6fb299 F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 7c8882e352cb70818cfaf9bdb5b1b3bee81ef144 -F src/sqliteInt.h 2f7b1f4d5062a17dfd75caa5639360c76881d5b2 +F src/sqliteInt.h d3c1448890ba65e6be381b50b7e7ce7fca142322 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1 F src/test1.c 5cc4f0bbf38237e04e1b2077e285b41bfb4c4cbf @@ -54,7 +54,7 @@ F src/update.c 6f6a4dcd71cd9ff730b7f12c83de5498cde4924f F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95 F src/vdbe.c 774f79483ce809b27c3bdb02afd7295cc3c7acd4 F src/vdbe.h a9292f2b5fcecef924fa255fb74609e9cbc776c2 -F src/where.c 5ff862869a8ab704070df2ef75a3424c782422cf +F src/where.c 259d7fb77191b13718c271926b7c14afbbe7346b F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/btree.test bf326f546a666617367a7033fa2c07451bd4f8e1 @@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 8aa73ce61268a50d353d9a5c878461290195525f -R 2b416ef8a3e6fcbc67f7c234a7a7ee0f +P d861489e1f7dffd1105c271fe8597f73e5b1703c +R d718b83d86c9331bc69c93f673a44be9 U drh -Z f4ef2a81bcc41a1ff76332fb25825e47 +Z b9b5d0f63e47642b79ff89410dec8a4b diff --git a/manifest.uuid b/manifest.uuid index b19dc370c7..9fc9568e12 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d861489e1f7dffd1105c271fe8597f73e5b1703c \ No newline at end of file +8b6574cfa86daaae910f8f3ee3c4723a21fb9e53 \ No newline at end of file diff --git a/src/select.c b/src/select.c index d17dd23a4b..490ee00d1b 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.98 2002/06/24 12:20:23 drh Exp $ +** $Id: select.c,v 1.99 2002/06/24 22:01:58 drh Exp $ */ #include "sqliteInt.h" @@ -167,6 +167,7 @@ static void addWhereTerm( pE1c = sqliteExpr(TK_DOT, pE1b, pE1a, 0); pE2c = sqliteExpr(TK_DOT, pE2b, pE2a, 0); pE = sqliteExpr(TK_EQ, pE1c, pE2c, 0); + pE->isJoinExpr = 1; if( *ppExpr ){ *ppExpr = sqliteExpr(TK_AND, *ppExpr, pE, 0); }else{ @@ -174,6 +175,21 @@ static void addWhereTerm( } } +/* +** Set the Expr.isJoinExpr flag on all terms of the given expression. +** +** The Expr.isJoinExpr flag is used at on terms of an expression to tell +** the LEFT OUTER JOIN processing logic that this term is part of the +** join restriction and not a part of the more general WHERE clause. +*/ +static void setJoinExpr(Expr *p){ + while( p ){ + p->isJoinExpr = 1; + setJoinExpr(p->pLeft); + p = p->pRight; + } +} + /* ** This routine processes the join information for a SELECT statement. ** ON and USING clauses are converted into extra terms of the WHERE clause. @@ -223,6 +239,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** and AND operator. */ if( pTerm->pOn ){ + setJoinExpr(pTerm->pOn); if( p->pWhere==0 ){ p->pWhere = pTerm->pOn; }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5abc316101..67e7ad6cf9 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.129 2002/06/22 02:33:39 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.130 2002/06/24 22:01:58 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -436,8 +436,9 @@ struct Token { ** operand. */ struct Expr { - u16 op; /* Operation performed by this node */ + u8 op; /* Operation performed by this node */ u8 dataType; /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */ + u8 isJoinExpr; /* Origina is the ON or USING phrase of a join */ Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in " IN (iLeftJoin && aExpr[j].p->isJoinExpr==0 ) continue; if( haveKey ){ haveKey = 0; sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); @@ -1023,6 +1024,16 @@ WhereInfo *sqliteWhereBegin( pLevel->top = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1); + for(j=0; jiContinue = cont;