/ Check-in [d04d354d]
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 all cursors are closed when returning from a VDBE subprogram that implements a foreign-key construct.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d04d354d8e423961c3091b6ebcfbbbf10d3ecb04
User & Date: drh 2015-04-16 18:11:50
Context
2015-04-16
20:10
Fix a boundry-value condition in the phrase poslist extractor of FTS3/4. check-in: 55d10baf user: drh tags: trunk
18:11
Make sure all cursors are closed when returning from a VDBE subprogram that implements a foreign-key construct. check-in: d04d354d user: drh tags: trunk
17:31
Fix the VDBE so that it always uses the original opcode for profiling and debugging even after the pOp pointer has been updated due to a jump. check-in: 647495cf user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbeaux.c.

1784
1785
1786
1787
1788
1789
1790
















1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804
1805
....
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
    const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
    assert( pVtabCursor->pVtab->nRef>0 );
    pVtabCursor->pVtab->nRef--;
    pModule->xClose(pVtabCursor);
  }
#endif
}

















/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;

#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  v->anExec = pFrame->anExec;
#endif
  v->aOnceFlag = pFrame->aOnceFlag;
  v->nOnceFlag = pFrame->nOnceFlag;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
................................................................................
    VdbeFrame *pFrame;
    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    sqlite3VdbeFrameRestore(pFrame);
    p->pFrame = 0;
    p->nFrame = 0;
  }
  assert( p->nFrame==0 );

  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite3VdbeFreeCursor(p, pC);
        p->apCsr[i] = 0;
      }
    }
  }

  if( p->aMem ){
    releaseMemArray(&p->aMem[1], p->nMem);
  }
  while( p->pDelFrame ){
    VdbeFrame *pDel = p->pDelFrame;
    p->pDelFrame = pDel->pParent;
    sqlite3VdbeFrameDelete(pDel);







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








>







 







<
<
<
<
<
<
<
<
<
<
<
>







1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
....
1843
1844
1845
1846
1847
1848
1849











1850
1851
1852
1853
1854
1855
1856
1857
    const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
    assert( pVtabCursor->pVtab->nRef>0 );
    pVtabCursor->pVtab->nRef--;
    pModule->xClose(pVtabCursor);
  }
#endif
}

/*
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite3VdbeFreeCursor(p, pC);
        p->apCsr[i] = 0;
      }
    }
  }
}

/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;
  closeCursorsInFrame(v);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  v->anExec = pFrame->anExec;
#endif
  v->aOnceFlag = pFrame->aOnceFlag;
  v->nOnceFlag = pFrame->nOnceFlag;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
................................................................................
    VdbeFrame *pFrame;
    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    sqlite3VdbeFrameRestore(pFrame);
    p->pFrame = 0;
    p->nFrame = 0;
  }
  assert( p->nFrame==0 );











  closeCursorsInFrame(p);
  if( p->aMem ){
    releaseMemArray(&p->aMem[1], p->nMem);
  }
  while( p->pDelFrame ){
    VdbeFrame *pDel = p->pDelFrame;
    p->pDelFrame = pDel->pParent;
    sqlite3VdbeFrameDelete(pDel);

Changes to test/fkey2.test.

672
673
674
675
676
677
678





679
680
681
682
683
684
685
} {6 A 5 6 B 5 3 A 2 3 B 2}
do_test fkey2-9.2.3 {
  execsql {
    DELETE FROM pp WHERE a = 4;
    SELECT * FROM cc;
  }
} {{} A {} {} B {} 3 A 2 3 B 2}






#-------------------------------------------------------------------------
# The following tests, fkey2-10.*, test "foreign key mismatch" and 
# other errors.
#
set tn 0
foreach zSql [list {







>
>
>
>
>







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
} {6 A 5 6 B 5 3 A 2 3 B 2}
do_test fkey2-9.2.3 {
  execsql {
    DELETE FROM pp WHERE a = 4;
    SELECT * FROM cc;
  }
} {{} A {} {} B {} 3 A 2 3 B 2}
do_execsql_test fkey2-9.3.0 {
  CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL);
  INSERT INTO t3(x) VALUES(12345);
  DROP TABLE t3;
} {}

#-------------------------------------------------------------------------
# The following tests, fkey2-10.*, test "foreign key mismatch" and 
# other errors.
#
set tn 0
foreach zSql [list {