/ Check-in [d861489e]
Login

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

Overview
Comment:Fix a VDBE stack leak in LEFT OUTER JOIN. Fix a bug in the code generator for JOIN ... USING(...). (CVS 638)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d861489e1f7dffd1105c271fe8597f73e5b1703c
User & Date: drh 2002-06-24 12:20:23
Context
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
2002-06-22
02:33
An optimization: avoid the use of an intermediate table on UNION ALL if there is no ORDER BY clause. (CVS 637) check-in: 8aa73ce6 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
....
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.97 2002/06/22 02:33:38 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
    */
    if( pTerm->pUsing ){
      IdList *pList;
      int j;
      assert( i<pSrc->nSrc-1 );
      pList = pTerm->pUsing;
      for(j=0; j<pList->nId; j++){
        if( columnIndex(pTerm->pTab, pList->a[i].zName)<0 ||
            columnIndex(pOther->pTab, pList->a[i].zName)<0 ){
          sqliteSetString(&pParse->zErrMsg, "cannot join using column ",
            pList->a[i].zName, " - column not present in both tables", 0);
          pParse->nErr++;
          return 1;
        }
        addWhereTerm(pList->a[i].zName, pTerm->pTab, pOther->pTab, &p->pWhere);
      }
    }
  }
  return 0;
}

/*
................................................................................
  */
  if( p->nLimit<=0 ){
    p->nLimit = -1;
    p->nOffset = 0;
  }else{
    int iMem = pParse->nMem++;
    sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0);
    sqliteVdbeAddOp(v, OP_MemStore, iMem, 0);
    p->nLimit = iMem;
    if( p->nOffset<=0 ){
      p->nOffset = 0;
    }else{
      iMem = pParse->nMem++;
      sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0);
      sqliteVdbeAddOp(v, OP_MemStore, iMem, 0);
      p->nOffset = iMem;
    }
  }

  /* Generate code for all sub-queries in the FROM clause
  */
  for(i=0; i<pTabList->nSrc; i++){







|







 







|
|

|



|







 







|






|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
....
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
    */
    if( pTerm->pUsing ){
      IdList *pList;
      int j;
      assert( i<pSrc->nSrc-1 );
      pList = pTerm->pUsing;
      for(j=0; j<pList->nId; j++){
        if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 ||
            columnIndex(pOther->pTab, pList->a[j].zName)<0 ){
          sqliteSetString(&pParse->zErrMsg, "cannot join using column ",
            pList->a[j].zName, " - column not present in both tables", 0);
          pParse->nErr++;
          return 1;
        }
        addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere);
      }
    }
  }
  return 0;
}

/*
................................................................................
  */
  if( p->nLimit<=0 ){
    p->nLimit = -1;
    p->nOffset = 0;
  }else{
    int iMem = pParse->nMem++;
    sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0);
    sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
    p->nLimit = iMem;
    if( p->nOffset<=0 ){
      p->nOffset = 0;
    }else{
      iMem = pParse->nMem++;
      sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0);
      sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
      p->nOffset = iMem;
    }
  }

  /* Generate code for all sub-queries in the FROM clause
  */
  for(i=0; i<pTabList->nSrc; i++){

Changes to src/where.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.53 2002/06/19 14:27:06 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
    sqliteVdbeResolveLabel(v, pLevel->brk);
    if( pLevel->inOp!=OP_Noop ){
      sqliteVdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);
    }
    if( pLevel->iLeftJoin ){
      int addr;
      addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
      sqliteVdbeAddOp(v, OP_NotNull, 0, addr+4);
      sqliteVdbeAddOp(v, OP_NullRow, base+i, 0);
      sqliteVdbeAddOp(v, OP_Goto, 0, pLevel->top);
    }
  }
  sqliteVdbeResolveLabel(v, pWInfo->iBreak);
  for(i=0; i<pTabList->nSrc; i++){
    if( pTabList->a[i].pTab->isTransient ) continue;







|







 







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** 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 $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
    sqliteVdbeResolveLabel(v, pLevel->brk);
    if( pLevel->inOp!=OP_Noop ){
      sqliteVdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);
    }
    if( pLevel->iLeftJoin ){
      int addr;
      addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
      sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4);
      sqliteVdbeAddOp(v, OP_NullRow, base+i, 0);
      sqliteVdbeAddOp(v, OP_Goto, 0, pLevel->top);
    }
  }
  sqliteVdbeResolveLabel(v, pWInfo->iBreak);
  for(i=0; i<pTabList->nSrc; i++){
    if( pTabList->a[i].pTab->isTransient ) continue;