/ Check-in [8b6574cf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8b6574cfa86daaae910f8f3ee3c4723a21fb9e53
User & Date: drh 2002-06-24 22:01:58
Context
2002-06-25
01:09
Added support for the "sqlite_temp_master" table. Increased the version number to 2.5.2. (CVS 640) check-in: 9c1432bf user: drh tags: trunk
2002-06-24
22:01
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) check-in: 8b6574cf user: drh tags: trunk
12:20
Fix a VDBE stack leak in LEFT OUTER JOIN. Fix a bug in the code generator for JOIN ... USING(...). (CVS 638) check-in: d861489e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.98 2002/06/24 12:20:23 drh Exp $
           15  +** $Id: select.c,v 1.99 2002/06/24 22:01:58 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Allocate a new Select structure and return a pointer to that
    21     21   ** structure.
    22     22   */
................................................................................
   163    163     pE1b = sqliteExpr(TK_ID, 0, 0, &dummy);
   164    164     dummy.z = pTab2->zName;
   165    165     dummy.n = strlen(dummy.z);
   166    166     pE2b = sqliteExpr(TK_ID, 0, 0, &dummy);
   167    167     pE1c = sqliteExpr(TK_DOT, pE1b, pE1a, 0);
   168    168     pE2c = sqliteExpr(TK_DOT, pE2b, pE2a, 0);
   169    169     pE = sqliteExpr(TK_EQ, pE1c, pE2c, 0);
          170  +  pE->isJoinExpr = 1;
   170    171     if( *ppExpr ){
   171    172       *ppExpr = sqliteExpr(TK_AND, *ppExpr, pE, 0);
   172    173     }else{
   173    174       *ppExpr = pE;
   174    175     }
   175    176   }
          177  +
          178  +/*
          179  +** Set the Expr.isJoinExpr flag on all terms of the given expression.
          180  +**
          181  +** The Expr.isJoinExpr flag is used at on terms of an expression to tell
          182  +** the LEFT OUTER JOIN processing logic that this term is part of the
          183  +** join restriction and not a part of the more general WHERE clause.
          184  +*/
          185  +static void setJoinExpr(Expr *p){
          186  +  while( p ){
          187  +    p->isJoinExpr = 1;
          188  +    setJoinExpr(p->pLeft);
          189  +    p = p->pRight;
          190  +  } 
          191  +}
   176    192   
   177    193   /*
   178    194   ** This routine processes the join information for a SELECT statement.
   179    195   ** ON and USING clauses are converted into extra terms of the WHERE clause.
   180    196   ** NATURAL joins also create extra WHERE clause terms.
   181    197   **
   182    198   ** This routine returns the number of errors encountered.
................................................................................
   219    235         return 1;
   220    236       }
   221    237   
   222    238       /* Add the ON clause to the end of the WHERE clause, connected by
   223    239       ** and AND operator.
   224    240       */
   225    241       if( pTerm->pOn ){
          242  +      setJoinExpr(pTerm->pOn);
   226    243         if( p->pWhere==0 ){
   227    244           p->pWhere = pTerm->pOn;
   228    245         }else{
   229    246           p->pWhere = sqliteExpr(TK_AND, p->pWhere, pTerm->pOn, 0);
   230    247         }
   231    248         pTerm->pOn = 0;
   232    249       }

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.129 2002/06/22 02:33:39 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.130 2002/06/24 22:01:58 drh Exp $
    15     15   */
    16     16   #include "sqlite.h"
    17     17   #include "hash.h"
    18     18   #include "vdbe.h"
    19     19   #include "parse.h"
    20     20   #include "btree.h"
    21     21   #include <stdio.h>
................................................................................
   432    432   **
   433    433   ** The Expr.pSelect field points to a SELECT statement.  The SELECT might
   434    434   ** be the right operand of an IN operator.  Or, if a scalar SELECT appears
   435    435   ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
   436    436   ** operand.
   437    437   */
   438    438   struct Expr {
   439         -  u16 op;                /* Operation performed by this node */
          439  +  u8 op;                 /* Operation performed by this node */
   440    440     u8 dataType;           /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */
          441  +  u8 isJoinExpr;         /* Origina is the ON or USING phrase of a join */
   441    442     Expr *pLeft, *pRight;  /* Left and right subnodes */
   442    443     ExprList *pList;       /* A list of expressions used as function arguments
   443    444                            ** or in "<expr> IN (<expr-list)" */
   444    445     Token token;           /* An operand token */
   445    446     Token span;            /* Complete text of the expression */
   446    447     int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the
   447    448                            ** iColumn-th field of the iTable-th table. */

Changes to src/where.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  Also found here are subroutines
    14     14   ** to generate VDBE code to evaluate expressions.
    15     15   **
    16         -** $Id: where.c,v 1.54 2002/06/24 12:20:23 drh Exp $
           16  +** $Id: where.c,v 1.55 2002/06/24 22:01:59 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   
    20     20   /*
    21     21   ** The query generator uses an array of instances of this structure to
    22     22   ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
    23     23   ** clause subexpression is separated from the others by an AND operator.
................................................................................
  1003   1003   
  1004   1004       /* Insert code to test every subexpression that can be completely
  1005   1005       ** computed using the current set of tables.
  1006   1006       */
  1007   1007       for(j=0; j<nExpr; j++){
  1008   1008         if( aExpr[j].p==0 ) continue;
  1009   1009         if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
         1010  +      if( pLevel->iLeftJoin && aExpr[j].p->isJoinExpr==0 ) continue;
  1010   1011         if( haveKey ){
  1011   1012           haveKey = 0;
  1012   1013           sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
  1013   1014         }
  1014   1015         sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
  1015   1016         aExpr[j].p = 0;
  1016   1017       }
................................................................................
  1019   1020       /* For a LEFT OUTER JOIN, generate code that will record the fact that
  1020   1021       ** at least one row of the right table has matched the left table.  
  1021   1022       */
  1022   1023       if( pLevel->iLeftJoin ){
  1023   1024         pLevel->top = sqliteVdbeCurrentAddr(v);
  1024   1025         sqliteVdbeAddOp(v, OP_Integer, 1, 0);
  1025   1026         sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
         1027  +      for(j=0; j<nExpr; j++){
         1028  +        if( aExpr[j].p==0 ) continue;
         1029  +        if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
         1030  +        if( haveKey ){
         1031  +          haveKey = 0;
         1032  +          sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0);
         1033  +        }
         1034  +        sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
         1035  +        aExpr[j].p = 0;
         1036  +      }
  1026   1037       }
  1027   1038     }
  1028   1039     pWInfo->iContinue = cont;
  1029   1040     if( pushKey && !haveKey ){
  1030   1041       sqliteVdbeAddOp(v, OP_Recno, base, 0);
  1031   1042     }
  1032   1043     sqliteFree(aOrder);