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
This commit is contained in:
drh 2002-06-24 22:01:57 +00:00
parent bf5cd97ed7
commit 1cc093c2b5
5 changed files with 42 additions and 13 deletions

View File

@ -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

View File

@ -1 +1 @@
d861489e1f7dffd1105c271fe8597f73e5b1703c
8b6574cfa86daaae910f8f3ee3c4723a21fb9e53

View File

@ -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{

View File

@ -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 "<expr> IN (<expr-list)" */

View File

@ -13,7 +13,7 @@
** the WHERE clause of SQL statements. Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.54 2002/06/24 12:20:23 drh Exp $
** $Id: where.c,v 1.55 2002/06/24 22:01:59 drh Exp $
*/
#include "sqliteInt.h"
@ -1007,6 +1007,7 @@ WhereInfo *sqliteWhereBegin(
for(j=0; j<nExpr; j++){
if( aExpr[j].p==0 ) continue;
if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
if( pLevel->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; j<nExpr; j++){
if( aExpr[j].p==0 ) continue;
if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
if( haveKey ){
haveKey = 0;
sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
}
sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
aExpr[j].p = 0;
}
}
}
pWInfo->iContinue = cont;