/ Check-in [face510b]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: face510bc14f440fc08dd5a354882ae05499bfa7
User & Date: drh 2008-01-31 15:53:45
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: c23f51de 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: face510b user: drh tags: trunk
15:31
Add "return rc;" to the end of sqlite3_test_control(). (CVS 4760) check-in: b547e7ea user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4489
4490
4491
4492
4493
4494
4495



4496
4497
4498
4499
4500
4501
4502
....
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
....
4556
4557
4558
4559
4560
4561
4562



4563
4564
4565
4566
4567
4568
4569
**
** 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
................................................................................
*/
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;
................................................................................
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;
  }
................................................................................
*/
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







|







 







>
>
>







 







>
>
>
>
>
>













<
<







 







>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
....
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
....
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
**
** 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
................................................................................
*/
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;
................................................................................
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;
  }
................................................................................
*/
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.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
83
84
85
86
87
88
89


















90
#    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
................................................................................
      WHERE name MATCH 'tcl_*' AND arrayname = '' 
      ORDER BY name;
  }
} $result
unset result
unset var



















finish_test







|







 







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

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
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
#    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
................................................................................
      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