SQLite

Check-in [face510bc1]
Login

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

Overview
Comment:Make sure virtual table interfaces are not invoked after EOF when the virtual table appears in an outer join. Ticket #2894. (CVS 4761)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: face510bc14f440fc08dd5a354882ae05499bfa7
User & Date: drh 2008-01-31 15:53:45.000
Context
2008-01-31
16:36
Fixes to API definition comments in sqlite.h.in. Updates to the build script - ticket #2874. (CVS 4762) (check-in: c23f51de61 user: drh tags: trunk)
15:53
Make sure virtual table interfaces are not invoked after EOF when the virtual table appears in an outer join. Ticket #2894. (CVS 4761) (check-in: face510bc1 user: drh tags: trunk)
15:31
Add "return rc;" to the end of sqlite3_test_control(). (CVS 4760) (check-in: b547e7ea75 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.705 2008/01/23 03:03:05 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.706 2008/01/31 15:53:45 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
4489
4490
4491
4492
4493
4494
4495



4496
4497
4498
4499
4500
4501
4502
*/
case OP_VRowid: {             /* out2-prerelease */
  const sqlite3_module *pModule;
  sqlite_int64 iRow;
  Cursor *pCur = p->apCsr[pOp->p1];

  assert( pCur->pVtabCursor );



  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xRowid );
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  pOut->flags = MEM_Int;
  pOut->u.i = iRow;







>
>
>







4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
*/
case OP_VRowid: {             /* out2-prerelease */
  const sqlite3_module *pModule;
  sqlite_int64 iRow;
  Cursor *pCur = p->apCsr[pOp->p1];

  assert( pCur->pVtabCursor );
  if( pCur->nullRow ){
    break;
  }
  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xRowid );
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  pOut->flags = MEM_Int;
  pOut->u.i = iRow;
4514
4515
4516
4517
4518
4519
4520






4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
case OP_VColumn: {
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;

  Cursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );






  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xColumn );
  memset(&sContext, 0, sizeof(sContext));
  sContext.s.flags = MEM_Null;
  sContext.s.db = db;
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occured to ensure any
  ** dynamic allocation in sContext.s (a Mem struct) is  released.
  */
  sqlite3VdbeChangeEncoding(&sContext.s, encoding);
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  pDest = &p->aMem[pOp->p3];
  REGISTER_TRACE(pOp->p3, pDest);
  sqlite3VdbeMemMove(pDest, &sContext.s);
  UPDATE_MAX_BLOBSIZE(pDest);

  if( sqlite3SafetyOn(db) ){
    goto abort_due_to_misuse;
  }







>
>
>
>
>
>













<
<







4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542


4543
4544
4545
4546
4547
4548
4549
case OP_VColumn: {
  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;

  Cursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  pDest = &p->aMem[pOp->p3];
  if( pCur->nullRow ){
    sqlite3VdbeMemSetNull(pDest);
    break;
  }
  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xColumn );
  memset(&sContext, 0, sizeof(sContext));
  sContext.s.flags = MEM_Null;
  sContext.s.db = db;
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occured to ensure any
  ** dynamic allocation in sContext.s (a Mem struct) is  released.
  */
  sqlite3VdbeChangeEncoding(&sContext.s, encoding);


  REGISTER_TRACE(pOp->p3, pDest);
  sqlite3VdbeMemMove(pDest, &sContext.s);
  UPDATE_MAX_BLOBSIZE(pDest);

  if( sqlite3SafetyOn(db) ){
    goto abort_due_to_misuse;
  }
4556
4557
4558
4559
4560
4561
4562



4563
4564
4565
4566
4567
4568
4569
*/
case OP_VNext: {   /* jump */
  const sqlite3_module *pModule;
  int res = 0;

  Cursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );



  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xNext );

  /* Invoke the xNext() method of the module. There is no way for the
  ** underlying implementation to return an error if one occurs during
  ** xNext(). Instead, if an error occurs, true is returned (indicating that 
  ** data is available) and the error code returned when xColumn or







>
>
>







4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
*/
case OP_VNext: {   /* jump */
  const sqlite3_module *pModule;
  int res = 0;

  Cursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  if( pCur->nullRow ){
    break;
  }
  pModule = pCur->pVtabCursor->pVtab->pModule;
  assert( pModule->xNext );

  /* Invoke the xNext() method of the module. There is no way for the
  ** underlying implementation to return an error if one occurs during
  ** xNext(). Instead, if an error occurs, true is returned (indicating that 
  ** data is available) and the error code returned when xColumn or
Changes to test/vtab2.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2006 June 10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    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.
#
# $Id: vtab2.test,v 1.7 2007/02/14 09:19:37 danielk1977 Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2006 June 10
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    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.
#
# $Id: vtab2.test,v 1.8 2008/01/31 15:53:46 drh Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return
83
84
85
86
87
88
89


















90
      WHERE name MATCH 'tcl_*' AND arrayname = '' 
      ORDER BY name;
  }
} $result
unset result
unset var



















finish_test







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

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
      WHERE name MATCH 'tcl_*' AND arrayname = '' 
      ORDER BY name;
  }
} $result
unset result
unset var

# Ticket #2894.
#
# Make sure we do call Column(), and Rowid() methods of
# a virtual table when that table is in a LEFT JOIN.
#
do_test vtab2-3.1 {
  execsql {
    SELECT * FROM schema WHERE dflt_value IS NULL LIMIT 1
  }
} {main schema 0 database {} 0 {} 0}
do_test vtab2-3.2 {
  execsql {
    SELECT *, b.rowid
      FROM schema a LEFT JOIN schema b ON a.dflt_value=b.dflt_value
     WHERE a.rowid=1
  }
} {main schema 0 database {} 0 {} 0 {} {} {} {} {} {} {} {} {}}

finish_test