/ Check-in [59d2e89e]
Login

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

Overview
Comment:Fix a bug in where.c where a non-temp register was being incorrectly deallocated. Ticket #3408. (CVS 5758)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 59d2e89e2181c26b18eac68ccc80ea3018f70a5e
User & Date: danielk1977 2008-10-01 08:43:03
Context
2008-10-01
13:55
Adjust the memory usage bounds on the memsubsys1.test script so that it works on amd64. (CVS 5759) check-in: aabde23f user: drh tags: trunk
08:43
Fix a bug in where.c where a non-temp register was being incorrectly deallocated. Ticket #3408. (CVS 5758) check-in: 59d2e89e user: danielk1977 tags: trunk
2008-09-30
17:18
Add some testcase() and assert() macros to btree.c to aid with testing recent changes. (CVS 5757) check-in: fb461b78 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
....
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.322 2008/09/06 14:19:11 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
  WhereLevel *pLevel, /* When level of the FROM clause we are working on */
  int iTarget         /* Attempt to leave results in this register */
){
  Expr *pX = pTerm->pExpr;
  Vdbe *v = pParse->pVdbe;
  int iReg;                  /* Register holding results */

  if( iTarget<=0 ){
    iReg = iTarget = sqlite3GetTempReg(pParse);
  }
  if( pX->op==TK_EQ ){
    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
  }else if( pX->op==TK_ISNULL ){
    iReg = iTarget;
    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
  }else{
................................................................................
    if( pLevel->flags & WHERE_ROWID_EQ ){
      /* Case 1:  We can directly reference a single row using an
      **          equality comparison against the ROWID field.  Or
      **          we reference multiple rows using a "rowid IN (...)"
      **          construct.
      */
      int r1;

      pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
      assert( pTerm!=0 );
      assert( pTerm->pExpr!=0 );
      assert( pTerm->leftCursor==iCur );
      assert( omitTable==0 );
      r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0);
      nxt = pLevel->nxt;
      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
      sqlite3ReleaseTempReg(pParse, r1);
      VdbeComment((v, "pk"));
      pLevel->op = OP_Noop;
    }else if( pLevel->flags & WHERE_ROWID_RANGE ){
      /* Case 2:  We have an inequality comparison against the ROWID field.
      */
      int testOp = OP_Noop;
      int start;







|







 







|
<
<







 







>





|



|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1780
1781
1782
1783
1784
1785
1786
1787


1788
1789
1790
1791
1792
1793
1794
....
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.323 2008/10/01 08:43:03 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
  WhereLevel *pLevel, /* When level of the FROM clause we are working on */
  int iTarget         /* Attempt to leave results in this register */
){
  Expr *pX = pTerm->pExpr;
  Vdbe *v = pParse->pVdbe;
  int iReg;                  /* Register holding results */

  assert( iTarget>0 );


  if( pX->op==TK_EQ ){
    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
  }else if( pX->op==TK_ISNULL ){
    iReg = iTarget;
    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
  }else{
................................................................................
    if( pLevel->flags & WHERE_ROWID_EQ ){
      /* Case 1:  We can directly reference a single row using an
      **          equality comparison against the ROWID field.  Or
      **          we reference multiple rows using a "rowid IN (...)"
      **          construct.
      */
      int r1;
      int rtmp = sqlite3GetTempReg(pParse);
      pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
      assert( pTerm!=0 );
      assert( pTerm->pExpr!=0 );
      assert( pTerm->leftCursor==iCur );
      assert( omitTable==0 );
      r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp);
      nxt = pLevel->nxt;
      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
      sqlite3ReleaseTempReg(pParse, rtmp);
      VdbeComment((v, "pk"));
      pLevel->op = OP_Noop;
    }else if( pLevel->flags & WHERE_ROWID_RANGE ){
      /* Case 2:  We have an inequality comparison against the ROWID field.
      */
      int testOp = OP_Noop;
      int start;

Changes to test/where.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1150
1151
1152
1153
1154
1155
1156
1157












































1158
1159
1160
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.47 2008/09/01 15:52:11 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
................................................................................
do_test where-15.1 {
  execsql {
    CREATE TEMP TABLE t1 (a, b, c, d, e);
    CREATE TEMP TABLE t2 (f);
    SELECT t1.e AS alias FROM t2, t1 WHERE alias = 1 ;
  }
} {}













































integrity_check {where-99.0}

finish_test







|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.48 2008/10/01 08:43:03 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
................................................................................
do_test where-15.1 {
  execsql {
    CREATE TEMP TABLE t1 (a, b, c, d, e);
    CREATE TEMP TABLE t2 (f);
    SELECT t1.e AS alias FROM t2, t1 WHERE alias = 1 ;
  }
} {}

# Ticket #3408.
# 
# The branch of code in where.c that generated rowid lookups was
# incorrectly deallocating a constant register, meaning that if the 
# vdbe code ran more than once, the second time around the constant
# value may have been clobbered by some other value.
# 
do_test where-16.1 {
  execsql {
    CREATE TABLE a1(id INTEGER PRIMARY KEY, v);
    CREATE TABLE a2(id INTEGER PRIMARY KEY, v);
    INSERT INTO a1 VALUES(1, 'one');
    INSERT INTO a1 VALUES(2, 'two');
    INSERT INTO a2 VALUES(1, 'one');
    INSERT INTO a2 VALUES(2, 'two');
  }
} {}
do_test where-16.2 {
  execsql {
    SELECT * FROM a2 CROSS JOIN a1 WHERE a1.id=1 AND a1.v='one';
  }
} {1 one 1 one 2 two 1 one}

# The actual problem reported in #3408.
do_test where-16.3 {
  execsql {
    CREATE TEMP TABLE foo(idx INTEGER);
    INSERT INTO foo VALUES(1);
    INSERT INTO foo VALUES(1);
    INSERT INTO foo VALUES(1);
    INSERT INTO foo VALUES(2);
    INSERT INTO foo VALUES(2);
    CREATE TEMP TABLE bar(stuff INTEGER);
    INSERT INTO bar VALUES(100);
    INSERT INTO bar VALUES(200);
    INSERT INTO bar VALUES(300);
  }
} {}
do_test where-16.4 {
  execsql {
    SELECT bar.RowID id FROM foo, bar WHERE foo.idx = bar.RowID AND id = 2;
  }
} {2 2}

integrity_check {where-99.0}

finish_test